Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Firefox/dom/payments/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 26 kB image not shown  

Quelle  PaymentRequestManager.cpp   Sprache: C

 
/* -*- 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/ClearOnShutdown.h"
#include "mozilla/dom/PaymentRequestChild.h"
#include "mozilla/dom/BrowserChild.h"
#include "mozilla/Preferences.h"
#include "nsContentUtils.h"
#include "nsString.h"
#include "nsIPrincipal.h"
#include "nsIPaymentActionResponse.h"
#include "PaymentRequestManager.h"
#include "PaymentRequestUtils.h"
#include "PaymentResponse.h"

namespace mozilla::dom {
namespace {

/*
 *  Following Convert* functions are used for convert PaymentRequest structs
 *  to transferable structs for IPC.
 */

void ConvertMethodData(JSContext* aCx, const PaymentMethodData& aMethodData,
                       IPCPaymentMethodData& aIPCMethodData, ErrorResult& aRv) {
  MOZ_ASSERT(aCx);
  // Convert JSObject to a serialized string
  nsAutoString serializedData;
  if (aMethodData.mData.WasPassed()) {
    JS::Rooted<JSObject*> object(aCx, aMethodData.mData.Value());
    if (NS_WARN_IF(
            NS_FAILED(SerializeFromJSObject(aCx, object, serializedData)))) {
      aRv.ThrowTypeError(
          "The PaymentMethodData.data must be a serializable object");
      return;
    }
  }
  aIPCMethodData =
      IPCPaymentMethodData(aMethodData.mSupportedMethods, serializedData);
}

void ConvertCurrencyAmount(const PaymentCurrencyAmount& aAmount,
                           IPCPaymentCurrencyAmount& aIPCCurrencyAmount) {
  aIPCCurrencyAmount =
      IPCPaymentCurrencyAmount(aAmount.mCurrency, aAmount.mValue);
}

void ConvertItem(const PaymentItem& aItem, IPCPaymentItem& aIPCItem) {
  IPCPaymentCurrencyAmount amount;
  ConvertCurrencyAmount(aItem.mAmount, amount);
  aIPCItem = IPCPaymentItem(aItem.mLabel, amount, aItem.mPending);
}

void ConvertModifier(JSContext* aCx, const PaymentDetailsModifier& aModifier,
                     IPCPaymentDetailsModifier& aIPCModifier,
                     ErrorResult& aRv) {
  MOZ_ASSERT(aCx);
  // Convert JSObject to a serialized string
  nsAutoString serializedData;
  if (aModifier.mData.WasPassed()) {
    JS::Rooted<JSObject*> object(aCx, aModifier.mData.Value());
    if (NS_WARN_IF(
            NS_FAILED(SerializeFromJSObject(aCx, object, serializedData)))) {
      aRv.ThrowTypeError("The Modifier.data must be a serializable object");
      return;
    }
  }

  IPCPaymentItem total;
  if (aModifier.mTotal.WasPassed()) {
    ConvertItem(aModifier.mTotal.Value(), total);
  }

  nsTArray<IPCPaymentItem> additionalDisplayItems;
  if (aModifier.mAdditionalDisplayItems.WasPassed()) {
    for (const PaymentItem& item : aModifier.mAdditionalDisplayItems.Value()) {
      IPCPaymentItem displayItem;
      ConvertItem(item, displayItem);
      additionalDisplayItems.AppendElement(displayItem);
    }
  }
  aIPCModifier = IPCPaymentDetailsModifier(
      aModifier.mSupportedMethods, total, additionalDisplayItems,
      serializedData, aModifier.mAdditionalDisplayItems.WasPassed());
}

void ConvertShippingOption(const PaymentShippingOption& aOption,
                           IPCPaymentShippingOption& aIPCOption) {
  IPCPaymentCurrencyAmount amount;
  ConvertCurrencyAmount(aOption.mAmount, amount);
  aIPCOption = IPCPaymentShippingOption(aOption.mId, aOption.mLabel, amount,
                                        aOption.mSelected);
}

void ConvertDetailsBase(JSContext* aCx, const PaymentDetailsBase& aDetails,
                        nsTArray<IPCPaymentItem>& aDisplayItems,
                        nsTArray<IPCPaymentShippingOption>& aShippingOptions,
                        nsTArray<IPCPaymentDetailsModifier>& aModifiers,
                        bool aRequestShipping, ErrorResult& aRv) {
  MOZ_ASSERT(aCx);
  if (aDetails.mDisplayItems.WasPassed()) {
    for (const PaymentItem& item : aDetails.mDisplayItems.Value()) {
      IPCPaymentItem displayItem;
      ConvertItem(item, displayItem);
      aDisplayItems.AppendElement(displayItem);
    }
  }
  if (aRequestShipping && aDetails.mShippingOptions.WasPassed()) {
    for (const PaymentShippingOption& option :
         aDetails.mShippingOptions.Value()) {
      IPCPaymentShippingOption shippingOption;
      ConvertShippingOption(option, shippingOption);
      aShippingOptions.AppendElement(shippingOption);
    }
  }
  if (aDetails.mModifiers.WasPassed()) {
    for (const PaymentDetailsModifier& modifier : aDetails.mModifiers.Value()) {
      IPCPaymentDetailsModifier detailsModifier;
      ConvertModifier(aCx, modifier, detailsModifier, aRv);
      if (aRv.Failed()) {
        return;
      }
      aModifiers.AppendElement(detailsModifier);
    }
  }
}

void ConvertDetailsInit(JSContext* aCx, const PaymentDetailsInit& aDetails,
                        IPCPaymentDetails& aIPCDetails, bool aRequestShipping,
                        ErrorResult& aRv) {
  MOZ_ASSERT(aCx);
  // Convert PaymentDetailsBase members
  nsTArray<IPCPaymentItem> displayItems;
  nsTArray<IPCPaymentShippingOption> shippingOptions;
  nsTArray<IPCPaymentDetailsModifier> modifiers;
  ConvertDetailsBase(aCx, aDetails, displayItems, shippingOptions, modifiers,
                     aRequestShipping, aRv);
  if (aRv.Failed()) {
    return;
  }

  // Convert |id|
  nsAutoString id;
  if (aDetails.mId.WasPassed()) {
    id = aDetails.mId.Value();
  }

  // Convert required |total|
  IPCPaymentItem total;
  ConvertItem(aDetails.mTotal, total);

  aIPCDetails =
      IPCPaymentDetails(id, total, displayItems, shippingOptions, modifiers,
                        u""_ns,   // error message
                        u""_ns,   // shippingAddressErrors
                        u""_ns,   // payerErrors
                        u""_ns);  // paymentMethodErrors
}

void ConvertDetailsUpdate(JSContext* aCx, const PaymentDetailsUpdate& aDetails,
                          IPCPaymentDetails& aIPCDetails, bool aRequestShipping,
                          ErrorResult& aRv) {
  MOZ_ASSERT(aCx);
  // Convert PaymentDetailsBase members
  nsTArray<IPCPaymentItem> displayItems;
  nsTArray<IPCPaymentShippingOption> shippingOptions;
  nsTArray<IPCPaymentDetailsModifier> modifiers;
  ConvertDetailsBase(aCx, aDetails, displayItems, shippingOptions, modifiers,
                     aRequestShipping, aRv);
  if (aRv.Failed()) {
    return;
  }

  // Convert required |total|
  IPCPaymentItem total;
  if (aDetails.mTotal.WasPassed()) {
    ConvertItem(aDetails.mTotal.Value(), total);
  }

  // Convert |error|
  nsAutoString error;
  if (aDetails.mError.WasPassed()) {
    error = aDetails.mError.Value();
  }

  nsAutoString shippingAddressErrors;
  if (aDetails.mShippingAddressErrors.WasPassed()) {
    if (!aDetails.mShippingAddressErrors.Value().ToJSON(
            shippingAddressErrors)) {
      aRv.ThrowTypeError("The ShippingAddressErrors can not be serailized");
      return;
    }
  }

  nsAutoString payerErrors;
  if (aDetails.mPayerErrors.WasPassed()) {
    if (!aDetails.mPayerErrors.Value().ToJSON(payerErrors)) {
      aRv.ThrowTypeError("The PayerErrors can not be serialized");
      return;
    }
  }

  nsAutoString paymentMethodErrors;
  if (aDetails.mPaymentMethodErrors.WasPassed()) {
    JS::Rooted<JSObject*> object(aCx, aDetails.mPaymentMethodErrors.Value());
    if (NS_WARN_IF(NS_FAILED(
            SerializeFromJSObject(aCx, object, paymentMethodErrors)))) {
      aRv.ThrowTypeError("The PaymentMethodErrors can not be serialized");
      return;
    }
  }

  aIPCDetails = IPCPaymentDetails(u""_ns,  // id
                                  total, displayItems, shippingOptions,
                                  modifiers, error, shippingAddressErrors,
                                  payerErrors, paymentMethodErrors);
}

void ConvertOptions(const PaymentOptions& aOptions,
                    IPCPaymentOptions& aIPCOption) {
  NS_ConvertASCIItoUTF16 shippingType(GetEnumString(aOptions.mShippingType));
  aIPCOption =
      IPCPaymentOptions(aOptions.mRequestPayerName, aOptions.mRequestPayerEmail,
                        aOptions.mRequestPayerPhone, aOptions.mRequestShipping,
                        aOptions.mRequestBillingAddress, shippingType);
}

void ConvertResponseData(const IPCPaymentResponseData& aIPCData,
                         ResponseData& aData) {
  switch (aIPCData.type()) {
    case IPCPaymentResponseData::TIPCGeneralResponse: {
      const IPCGeneralResponse& data = aIPCData;
      GeneralData gData;
      gData.data = data.data();
      aData = gData;
      break;
    }
    case IPCPaymentResponseData::TIPCBasicCardResponse: {
      const IPCBasicCardResponse& data = aIPCData;
      BasicCardData bData;
      bData.cardholderName = data.cardholderName();
      bData.cardNumber = data.cardNumber();
      bData.expiryMonth = data.expiryMonth();
      bData.expiryYear = data.expiryYear();
      bData.cardSecurityCode = data.cardSecurityCode();
      bData.billingAddress.country = data.billingAddress().country();
      bData.billingAddress.addressLine =
          data.billingAddress().addressLine().Clone();
      bData.billingAddress.region = data.billingAddress().region();
      bData.billingAddress.regionCode = data.billingAddress().regionCode();
      bData.billingAddress.city = data.billingAddress().city();
      bData.billingAddress.dependentLocality =
          data.billingAddress().dependentLocality();
      bData.billingAddress.postalCode = data.billingAddress().postalCode();
      bData.billingAddress.sortingCode = data.billingAddress().sortingCode();
      bData.billingAddress.organization = data.billingAddress().organization();
      bData.billingAddress.recipient = data.billingAddress().recipient();
      bData.billingAddress.phone = data.billingAddress().phone();
      aData = bData;
      break;
    }
    default: {
      break;
    }
  }
}

void ConvertMethodChangeDetails(const IPCMethodChangeDetails& aIPCDetails,
                                ChangeDetails& aDetails) {
  switch (aIPCDetails.type()) {
    case IPCMethodChangeDetails::TIPCGeneralChangeDetails: {
      const IPCGeneralChangeDetails& details = aIPCDetails;
      GeneralDetails gDetails;
      gDetails.details = details.details();
      aDetails = gDetails;
      break;
    }
    case IPCMethodChangeDetails::TIPCBasicCardChangeDetails: {
      const IPCBasicCardChangeDetails& details = aIPCDetails;
      BasicCardDetails bDetails;
      bDetails.billingAddress.country = details.billingAddress().country();
      bDetails.billingAddress.addressLine =
          details.billingAddress().addressLine();
      bDetails.billingAddress.region = details.billingAddress().region();
      bDetails.billingAddress.regionCode =
          details.billingAddress().regionCode();
      bDetails.billingAddress.city = details.billingAddress().city();
      bDetails.billingAddress.dependentLocality =
          details.billingAddress().dependentLocality();
      bDetails.billingAddress.postalCode =
          details.billingAddress().postalCode();
      bDetails.billingAddress.sortingCode =
          details.billingAddress().sortingCode();
      bDetails.billingAddress.organization =
          details.billingAddress().organization();
      bDetails.billingAddress.recipient = details.billingAddress().recipient();
      bDetails.billingAddress.phone = details.billingAddress().phone();
      aDetails = bDetails;
      break;
    }
    default: {
      break;
    }
  }
}
}  // end of namespace

/* PaymentRequestManager */

StaticRefPtr<PaymentRequestManager> gPaymentManager;
const char kSupportedRegionsPref[] = "dom.payments.request.supportedRegions";

void SupportedRegionsPrefChangedCallback(const char* aPrefName, void* aRetval) {
  auto retval = static_cast<nsTArray<nsString>*>(aRetval);
  MOZ_ASSERT(NS_IsMainThread());
  MOZ_ASSERT(!strcmp(aPrefName, kSupportedRegionsPref));

  nsAutoString supportedRegions;
  Preferences::GetString(aPrefName, supportedRegions);
  retval->Clear();
  for (const nsAString& each : supportedRegions.Split(',')) {
    retval->AppendElement(each);
  }
}

PaymentRequestManager::PaymentRequestManager() {
  Preferences::RegisterCallbackAndCall(SupportedRegionsPrefChangedCallback,
                                       kSupportedRegionsPref,
                                       &this->mSupportedRegions);
}

PaymentRequestManager::~PaymentRequestManager() {
  MOZ_ASSERT(mActivePayments.Count() == 0);
  Preferences::UnregisterCallback(SupportedRegionsPrefChangedCallback,
                                  kSupportedRegionsPref,
                                  &this->mSupportedRegions);
  mSupportedRegions.Clear();
}

bool PaymentRequestManager::IsRegionSupported(const nsAString& region) const {
  return mSupportedRegions.Contains(region);
}

PaymentRequestChild* PaymentRequestManager::GetPaymentChild(
    PaymentRequest* aRequest) {
  MOZ_ASSERT(aRequest);

  if (PaymentRequestChild* child = aRequest->GetIPC()) {
    return child;
  }

  nsPIDOMWindowInner* win = aRequest->GetOwnerWindow();
  NS_ENSURE_TRUE(win, nullptr);
  BrowserChild* browserChild = BrowserChild::GetFrom(win->GetDocShell());
  NS_ENSURE_TRUE(browserChild, nullptr);
  nsAutoString requestId;
  aRequest->GetInternalId(requestId);

  PaymentRequestChild* paymentChild = new PaymentRequestChild(aRequest);
  if (!browserChild->SendPPaymentRequestConstructor(paymentChild)) {
    // deleted by Constructor
    return nullptr;
  }

  return paymentChild;
}

nsresult PaymentRequestManager::SendRequestPayment(
    PaymentRequest* aRequest, const IPCPaymentActionRequest& aAction,
    bool aResponseExpected) {
  PaymentRequestChild* requestChild = GetPaymentChild(aRequest);
  // bug 1580496, ignoring the case that requestChild is nullptr. It could be
  // nullptr while the corresponding nsPIDOMWindowInner is nullptr.
  if (NS_WARN_IF(!requestChild)) {
    return NS_ERROR_FAILURE;
  }
  nsresult rv = requestChild->RequestPayment(aAction);
  if (NS_WARN_IF(NS_FAILED(rv))) {
    return rv;
  }

  if (aResponseExpected) {
    ++mActivePayments.LookupOrInsert(aRequest, 0);
  }
  return NS_OK;
}

void PaymentRequestManager::NotifyRequestDone(PaymentRequest* aRequest) {
  auto entry = mActivePayments.Lookup(aRequest);
  MOZ_ASSERT(entry);
  MOZ_ASSERT(entry.Data() > 0);

  uint32_t count = --entry.Data();
  if (count == 0) {
    entry.Remove();
  }
}

void PaymentRequestManager::RequestIPCOver(PaymentRequest* aRequest) {
  // This must only be called from ActorDestroy or if we're sure we won't
  // receive any more IPC for aRequest.
  mActivePayments.Remove(aRequest);
}

already_AddRefed<PaymentRequestManager> PaymentRequestManager::GetSingleton() {
  if (!gPaymentManager) {
    gPaymentManager = new PaymentRequestManager();
    ClearOnShutdown(&gPaymentManager);
  }
  RefPtr<PaymentRequestManager> manager = gPaymentManager;
  return manager.forget();
}

void GetSelectedShippingOption(const PaymentDetailsBase& aDetails,
                               nsAString& aOption) {
  SetDOMStringToNull(aOption);
  if (!aDetails.mShippingOptions.WasPassed()) {
    return;
  }

  const Sequence<PaymentShippingOption>& shippingOptions =
      aDetails.mShippingOptions.Value();
  for (const PaymentShippingOption& shippingOption : shippingOptions) {
    // set aOption to last selected option's ID
    if (shippingOption.mSelected) {
      aOption = shippingOption.mId;
    }
  }
}

void PaymentRequestManager::CreatePayment(
    JSContext* aCx, nsPIDOMWindowInner* aWindow,
    nsIPrincipal* aTopLevelPrincipal,
    const Sequence<PaymentMethodData>& aMethodData,
    const PaymentDetailsInit& aDetails, const PaymentOptions& aOptions,
    PaymentRequest** aRequest, ErrorResult& aRv) {
  MOZ_ASSERT(NS_IsMainThread());
  MOZ_ASSERT(aCx);
  MOZ_ASSERT(aRequest);
  MOZ_ASSERT(aTopLevelPrincipal);
  *aRequest = nullptr;

  RefPtr<PaymentRequest> request =
      PaymentRequest::CreatePaymentRequest(aWindow, aRv);
  if (aRv.Failed()) {
    return;
  }
  request->SetOptions(aOptions);
  /*
   *  Set request's |mId| to details.id if details.id exists.
   *  Otherwise, set |mId| to internal id.
   */

  nsAutoString requestId;
  if (aDetails.mId.WasPassed() && !aDetails.mId.Value().IsEmpty()) {
    requestId = aDetails.mId.Value();
  } else {
    request->GetInternalId(requestId);
  }
  request->SetId(requestId);

  /*
   * Set request's |mShippingType| and |mShippingOption| if shipping is
   * required. Set request's mShippingOption to last selected option's ID if
   * details.shippingOptions exists, otherwise set it as null.
   */

  nsAutoString shippingOption;
  SetDOMStringToNull(shippingOption);
  if (aOptions.mRequestShipping) {
    request->ShippingWasRequested();
    request->SetShippingType(
        Nullable<PaymentShippingType>(aOptions.mShippingType));
    GetSelectedShippingOption(aDetails, shippingOption);
  }
  request->SetShippingOption(shippingOption);

  nsAutoString internalId;
  request->GetInternalId(internalId);

  nsTArray<IPCPaymentMethodData> methodData;
  for (const PaymentMethodData& data : aMethodData) {
    IPCPaymentMethodData ipcMethodData;
    ConvertMethodData(aCx, data, ipcMethodData, aRv);
    if (aRv.Failed()) {
      return;
    }
    methodData.AppendElement(ipcMethodData);
  }

  IPCPaymentDetails details;
  ConvertDetailsInit(aCx, aDetails, details, aOptions.mRequestShipping, aRv);
  if (aRv.Failed()) {
    return;
  }

  IPCPaymentOptions options;
  ConvertOptions(aOptions, options);

  uint64_t topOuterWindowId =
      aWindow->GetWindowContext()->TopWindowContext()->OuterWindowId();
  IPCPaymentCreateActionRequest action(topOuterWindowId, internalId,
                                       aTopLevelPrincipal, methodData, details,
                                       options, shippingOption);

  if (NS_WARN_IF(NS_FAILED(SendRequestPayment(request, action, false)))) {
    aRv.ThrowUnknownError("Internal error sending payment request");
    return;
  }
  request.forget(aRequest);
}

void PaymentRequestManager::CanMakePayment(PaymentRequest* aRequest,
                                           ErrorResult& aRv) {
  nsAutoString requestId;
  aRequest->GetInternalId(requestId);
  IPCPaymentCanMakeActionRequest action(requestId);
  if (NS_WARN_IF(NS_FAILED(SendRequestPayment(aRequest, action)))) {
    aRv.ThrowUnknownError("Internal error sending payment request");
  }
}

void PaymentRequestManager::ShowPayment(PaymentRequest* aRequest,
                                        ErrorResult& aRv) {
  nsAutoString requestId;
  aRequest->GetInternalId(requestId);
  IPCPaymentShowActionRequest action(requestId, aRequest->IsUpdating());
  if (NS_WARN_IF(NS_FAILED(SendRequestPayment(aRequest, action)))) {
    aRv.ThrowUnknownError("Internal error sending payment request");
  }
}

void PaymentRequestManager::AbortPayment(PaymentRequest* aRequest,
                                         ErrorResult& aRv) {
  nsAutoString requestId;
  aRequest->GetInternalId(requestId);
  IPCPaymentAbortActionRequest action(requestId);
  if (NS_WARN_IF(NS_FAILED(SendRequestPayment(aRequest, action)))) {
    aRv.ThrowUnknownError("Internal error sending payment request");
  }
}

void PaymentRequestManager::CompletePayment(PaymentRequest* aRequest,
                                            const PaymentComplete& aComplete,
                                            ErrorResult& aRv, bool aTimedOut) {
  nsString completeStatusString(u"unknown"_ns);
  if (aTimedOut) {
    completeStatusString.AssignLiteral("timeout");
  } else {
    completeStatusString.AssignASCII(GetEnumString(aComplete));
  }

  nsAutoString requestId;
  aRequest->GetInternalId(requestId);
  IPCPaymentCompleteActionRequest action(requestId, completeStatusString);
  if (NS_WARN_IF(NS_FAILED(SendRequestPayment(aRequest, action, false)))) {
    aRv.ThrowUnknownError("Internal error sending payment request");
  }
}

void PaymentRequestManager::UpdatePayment(JSContext* aCx,
                                          PaymentRequest* aRequest,
                                          const PaymentDetailsUpdate& aDetails,
                                          bool aRequestShipping,
                                          ErrorResult& aRv) {
  MOZ_ASSERT(aCx);
  IPCPaymentDetails details;
  ConvertDetailsUpdate(aCx, aDetails, details, aRequestShipping, aRv);
  if (aRv.Failed()) {
    return;
  }

  nsAutoString shippingOption;
  SetDOMStringToNull(shippingOption);
  if (aRequestShipping) {
    GetSelectedShippingOption(aDetails, shippingOption);
    aRequest->SetShippingOption(shippingOption);
  }

  nsAutoString requestId;
  aRequest->GetInternalId(requestId);
  IPCPaymentUpdateActionRequest action(requestId, details, shippingOption);
  if (NS_WARN_IF(NS_FAILED(SendRequestPayment(aRequest, action, false)))) {
    aRv.ThrowUnknownError("Internal error sending payment request");
  }
}

nsresult PaymentRequestManager::ClosePayment(PaymentRequest* aRequest) {
  // for the case, the payment request is waiting for response from user.
  if (auto entry = mActivePayments.Lookup(aRequest)) {
    NotifyRequestDone(aRequest);
  }
  nsAutoString requestId;
  aRequest->GetInternalId(requestId);
  IPCPaymentCloseActionRequest action(requestId);
  return SendRequestPayment(aRequest, action, false);
}

void PaymentRequestManager::RetryPayment(JSContext* aCx,
                                         PaymentRequest* aRequest,
                                         const PaymentValidationErrors& aErrors,
                                         ErrorResult& aRv) {
  MOZ_ASSERT(aCx);
  MOZ_ASSERT(aRequest);

  nsAutoString requestId;
  aRequest->GetInternalId(requestId);

  nsAutoString error;
  if (aErrors.mError.WasPassed()) {
    error = aErrors.mError.Value();
  }

  nsAutoString shippingAddressErrors;
  if (aErrors.mShippingAddress.WasPassed()) {
    if (!aErrors.mShippingAddress.Value().ToJSON(shippingAddressErrors)) {
      aRv.ThrowTypeError("The ShippingAddressErrors can not be serialized");
      return;
    }
  }

  nsAutoString payerErrors;
  if (aErrors.mPayer.WasPassed()) {
    if (!aErrors.mPayer.Value().ToJSON(payerErrors)) {
      aRv.ThrowTypeError("The PayerErrors can not be serialized");
      return;
    }
  }

  nsAutoString paymentMethodErrors;
  if (aErrors.mPaymentMethod.WasPassed()) {
    JS::Rooted<JSObject*> object(aCx, aErrors.mPaymentMethod.Value());
    if (NS_WARN_IF(NS_FAILED(
            SerializeFromJSObject(aCx, object, paymentMethodErrors)))) {
      aRv.ThrowTypeError("The PaymentMethodErrors can not be serialized");
      return;
    }
  }
  IPCPaymentRetryActionRequest action(requestId, error, payerErrors,
                                      paymentMethodErrors,
                                      shippingAddressErrors);
  if (NS_WARN_IF(NS_FAILED(SendRequestPayment(aRequest, action)))) {
    aRv.ThrowUnknownError("Internal error sending payment request");
  }
}

nsresult PaymentRequestManager::RespondPayment(
    PaymentRequest* aRequest, const IPCPaymentActionResponse& aResponse) {
  switch (aResponse.type()) {
    case IPCPaymentActionResponse::TIPCPaymentCanMakeActionResponse: {
      const IPCPaymentCanMakeActionResponse& response = aResponse;
      aRequest->RespondCanMakePayment(response.result());
      NotifyRequestDone(aRequest);
      break;
    }
    case IPCPaymentActionResponse::TIPCPaymentShowActionResponse: {
      const IPCPaymentShowActionResponse& response = aResponse;
      ErrorResult rejectedReason;
      ResponseData responseData;
      ConvertResponseData(response.data(), responseData);
      switch (response.status()) {
        case nsIPaymentActionResponse::PAYMENT_ACCEPTED: {
          break;
        }
        case nsIPaymentActionResponse::PAYMENT_REJECTED: {
          rejectedReason.ThrowAbortError("The user rejected the payment");
          break;
        }
        case nsIPaymentActionResponse::PAYMENT_NOTSUPPORTED: {
          rejectedReason.ThrowNotSupportedError("No supported payment method");
          break;
        }
        default: {
          rejectedReason.ThrowUnknownError("Unknown response for the payment");
          break;
        }
      }
      // If PaymentActionResponse is not PAYMENT_ACCEPTED, no need to keep the
      // PaymentRequestChild instance. Otherwise, keep PaymentRequestChild for
      // merchants call PaymentResponse.complete()
      if (rejectedReason.Failed()) {
        NotifyRequestDone(aRequest);
      }
      aRequest->RespondShowPayment(response.methodName(), responseData,
                                   response.payerName(), response.payerEmail(),
                                   response.payerPhone(),
                                   std::move(rejectedReason));
      break;
    }
    case IPCPaymentActionResponse::TIPCPaymentAbortActionResponse: {
      const IPCPaymentAbortActionResponse& response = aResponse;
      aRequest->RespondAbortPayment(response.isSucceeded());
      NotifyRequestDone(aRequest);
      break;
    }
    case IPCPaymentActionResponse::TIPCPaymentCompleteActionResponse: {
      aRequest->RespondComplete();
      NotifyRequestDone(aRequest);
      break;
    }
    default: {
      return NS_ERROR_FAILURE;
    }
  }
  return NS_OK;
}

nsresult PaymentRequestManager::ChangeShippingAddress(
    PaymentRequest* aRequest, const IPCPaymentAddress& aAddress) {
  return aRequest->UpdateShippingAddress(
      aAddress.country(), aAddress.addressLine(), aAddress.region(),
      aAddress.regionCode(), aAddress.city(), aAddress.dependentLocality(),
      aAddress.postalCode(), aAddress.sortingCode(), aAddress.organization(),
      aAddress.recipient(), aAddress.phone());
}

nsresult PaymentRequestManager::ChangeShippingOption(PaymentRequest* aRequest,
                                                     const nsAString& aOption) {
  return aRequest->UpdateShippingOption(aOption);
}

nsresult PaymentRequestManager::ChangePayerDetail(
    PaymentRequest* aRequest, const nsAString& aPayerName,
    const nsAString& aPayerEmail, const nsAString& aPayerPhone) {
  MOZ_ASSERT(aRequest);
  RefPtr<PaymentResponse> response = aRequest->GetResponse();
  // ignoring the case call changePayerDetail during show().
  if (!response) {
    return NS_OK;
  }
  return response->UpdatePayerDetail(aPayerName, aPayerEmail, aPayerPhone);
}

nsresult PaymentRequestManager::ChangePaymentMethod(
    PaymentRequest* aRequest, const nsAString& aMethodName,
    const IPCMethodChangeDetails& aMethodDetails) {
  NS_ENSURE_ARG_POINTER(aRequest);
  ChangeDetails methodDetails;
  ConvertMethodChangeDetails(aMethodDetails, methodDetails);
  return aRequest->UpdatePaymentMethod(aMethodName, methodDetails);
}

}  // namespace mozilla::dom

Messung V0.5
C=99 H=99 G=98

¤ Dauer der Verarbeitung: 0.16 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.