tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

PaymentRequestService.cpp (19377B)


      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/. */
      6 
      7 #include "PaymentRequestService.h"
      8 
      9 #include "BasicCardPayment.h"
     10 #include "mozilla/ClearOnShutdown.h"
     11 #include "mozilla/dom/BasicCardPaymentBinding.h"
     12 #include "mozilla/dom/PaymentRequestParent.h"
     13 #include "nsArrayUtils.h"
     14 #include "nsCOMPtr.h"
     15 #include "nsComponentManagerUtils.h"
     16 #include "nsIMutableArray.h"
     17 #include "nsServiceManagerUtils.h"
     18 #include "nsSimpleEnumerator.h"
     19 
     20 namespace mozilla::dom {
     21 
     22 StaticRefPtr<PaymentRequestService> gPaymentService;
     23 
     24 namespace {
     25 
     26 class PaymentRequestEnumerator final : public nsSimpleEnumerator {
     27 public:
     28  NS_DECL_NSISIMPLEENUMERATOR
     29 
     30  PaymentRequestEnumerator() : mIndex(0) {}
     31 
     32  const nsID& DefaultInterface() override {
     33    return NS_GET_IID(nsIPaymentRequest);
     34  }
     35 
     36 private:
     37  ~PaymentRequestEnumerator() override = default;
     38  uint32_t mIndex;
     39 };
     40 
     41 NS_IMETHODIMP
     42 PaymentRequestEnumerator::HasMoreElements(bool* aReturn) {
     43  NS_ENSURE_ARG_POINTER(aReturn);
     44  *aReturn = false;
     45  if (NS_WARN_IF(!gPaymentService)) {
     46    return NS_ERROR_FAILURE;
     47  }
     48  RefPtr<PaymentRequestService> service = gPaymentService;
     49  *aReturn = mIndex < service->NumPayments();
     50  return NS_OK;
     51 }
     52 
     53 NS_IMETHODIMP
     54 PaymentRequestEnumerator::GetNext(nsISupports** aItem) {
     55  NS_ENSURE_ARG_POINTER(aItem);
     56  if (NS_WARN_IF(!gPaymentService)) {
     57    return NS_ERROR_FAILURE;
     58  }
     59  RefPtr<payments::PaymentRequest> rowRequest =
     60      gPaymentService->GetPaymentRequestByIndex(mIndex);
     61  if (!rowRequest) {
     62    return NS_ERROR_FAILURE;
     63  }
     64  mIndex++;
     65  rowRequest.forget(aItem);
     66  return NS_OK;
     67 }
     68 
     69 }  // end of anonymous namespace
     70 
     71 /* PaymentRequestService */
     72 
     73 NS_IMPL_ISUPPORTS(PaymentRequestService, nsIPaymentRequestService)
     74 
     75 already_AddRefed<PaymentRequestService> PaymentRequestService::GetSingleton() {
     76  MOZ_ASSERT(NS_IsMainThread());
     77  if (!gPaymentService) {
     78    gPaymentService = new PaymentRequestService();
     79    ClearOnShutdown(&gPaymentService);
     80  }
     81  RefPtr<PaymentRequestService> service = gPaymentService;
     82  return service.forget();
     83 }
     84 
     85 uint32_t PaymentRequestService::NumPayments() const {
     86  return mRequestQueue.Length();
     87 }
     88 
     89 already_AddRefed<payments::PaymentRequest>
     90 PaymentRequestService::GetPaymentRequestByIndex(const uint32_t aIndex) {
     91  if (aIndex >= mRequestQueue.Length()) {
     92    return nullptr;
     93  }
     94  RefPtr<payments::PaymentRequest> request = mRequestQueue[aIndex];
     95  MOZ_ASSERT(request);
     96  return request.forget();
     97 }
     98 
     99 NS_IMETHODIMP
    100 PaymentRequestService::GetPaymentRequestById(const nsAString& aRequestId,
    101                                             nsIPaymentRequest** aRequest) {
    102  NS_ENSURE_ARG_POINTER(aRequest);
    103  *aRequest = nullptr;
    104  RefPtr<payments::PaymentRequest> rowRequest;
    105  nsresult rv = GetPaymentRequestById(aRequestId, getter_AddRefs(rowRequest));
    106  if (NS_WARN_IF(NS_FAILED(rv))) {
    107    return rv;
    108  }
    109  rowRequest.forget(aRequest);
    110  return NS_OK;
    111 }
    112 
    113 nsresult PaymentRequestService::GetPaymentRequestById(
    114    const nsAString& aRequestId, payments::PaymentRequest** aRequest) {
    115  NS_ENSURE_ARG_POINTER(aRequest);
    116  *aRequest = nullptr;
    117  uint32_t numRequests = mRequestQueue.Length();
    118  for (uint32_t index = 0; index < numRequests; ++index) {
    119    RefPtr<payments::PaymentRequest> request = mRequestQueue[index];
    120    MOZ_ASSERT(request);
    121    nsAutoString requestId;
    122    nsresult rv = request->GetRequestId(requestId);
    123    NS_ENSURE_SUCCESS(rv, rv);
    124    if (requestId == aRequestId) {
    125      request.forget(aRequest);
    126      break;
    127    }
    128  }
    129  return NS_OK;
    130 }
    131 
    132 NS_IMETHODIMP
    133 PaymentRequestService::Enumerate(nsISimpleEnumerator** aEnumerator) {
    134  NS_ENSURE_ARG_POINTER(aEnumerator);
    135  nsCOMPtr<nsISimpleEnumerator> enumerator = new PaymentRequestEnumerator();
    136  enumerator.forget(aEnumerator);
    137  return NS_OK;
    138 }
    139 
    140 NS_IMETHODIMP
    141 PaymentRequestService::Cleanup() {
    142  mRequestQueue.Clear();
    143  return NS_OK;
    144 }
    145 
    146 NS_IMETHODIMP
    147 PaymentRequestService::SetTestingUIService(nsIPaymentUIService* aUIService) {
    148  // aUIService can be nullptr
    149  mTestingUIService = aUIService;
    150  return NS_OK;
    151 }
    152 
    153 nsresult PaymentRequestService::LaunchUIAction(const nsAString& aRequestId,
    154                                               uint32_t aActionType) {
    155  nsCOMPtr<nsIPaymentUIService> uiService;
    156  nsresult rv;
    157  if (mTestingUIService) {
    158    uiService = mTestingUIService;
    159  } else {
    160    uiService = do_GetService(NS_PAYMENT_UI_SERVICE_CONTRACT_ID, &rv);
    161    if (NS_WARN_IF(NS_FAILED(rv))) {
    162      return rv;
    163    }
    164  }
    165  switch (aActionType) {
    166    case IPCPaymentActionRequest::TIPCPaymentShowActionRequest: {
    167      rv = uiService->ShowPayment(aRequestId);
    168      break;
    169    }
    170    case IPCPaymentActionRequest::TIPCPaymentAbortActionRequest: {
    171      rv = uiService->AbortPayment(aRequestId);
    172      break;
    173    }
    174    case IPCPaymentActionRequest::TIPCPaymentCompleteActionRequest: {
    175      rv = uiService->CompletePayment(aRequestId);
    176      break;
    177    }
    178    case IPCPaymentActionRequest::TIPCPaymentUpdateActionRequest: {
    179      rv = uiService->UpdatePayment(aRequestId);
    180      break;
    181    }
    182    case IPCPaymentActionRequest::TIPCPaymentCloseActionRequest: {
    183      rv = uiService->ClosePayment(aRequestId);
    184      break;
    185    }
    186    default: {
    187      return NS_ERROR_FAILURE;
    188    }
    189  }
    190  if (NS_WARN_IF(NS_FAILED(rv))) {
    191    return rv;
    192  }
    193  return NS_OK;
    194 }
    195 
    196 nsresult PaymentRequestService::RequestPayment(
    197    const nsAString& aRequestId, const IPCPaymentActionRequest& aAction,
    198    PaymentRequestParent* aIPC) {
    199  NS_ENSURE_ARG_POINTER(aIPC);
    200 
    201  nsresult rv = NS_OK;
    202  uint32_t type = aAction.type();
    203 
    204  RefPtr<payments::PaymentRequest> request;
    205  if (type != IPCPaymentActionRequest::TIPCPaymentCreateActionRequest) {
    206    rv = GetPaymentRequestById(aRequestId, getter_AddRefs(request));
    207    if (NS_WARN_IF(NS_FAILED(rv))) {
    208      return rv;
    209    }
    210    if (!request &&
    211        type != IPCPaymentActionRequest::TIPCPaymentCloseActionRequest) {
    212      return NS_ERROR_FAILURE;
    213    }
    214    if (request) {
    215      request->SetIPC(aIPC);
    216    }
    217  }
    218 
    219  switch (type) {
    220    case IPCPaymentActionRequest::TIPCPaymentCreateActionRequest: {
    221      MOZ_ASSERT(!request);
    222      const IPCPaymentCreateActionRequest& action = aAction;
    223      nsCOMPtr<nsIMutableArray> methodData =
    224          do_CreateInstance(NS_ARRAY_CONTRACTID);
    225      MOZ_ASSERT(methodData);
    226      for (IPCPaymentMethodData data : action.methodData()) {
    227        nsCOMPtr<nsIPaymentMethodData> method;
    228        rv = payments::PaymentMethodData::Create(data, getter_AddRefs(method));
    229        NS_ENSURE_SUCCESS(rv, rv);
    230        rv = methodData->AppendElement(method);
    231        NS_ENSURE_SUCCESS(rv, rv);
    232      }
    233      nsCOMPtr<nsIPaymentDetails> details;
    234      rv = payments::PaymentDetails::Create(action.details(),
    235                                            getter_AddRefs(details));
    236      NS_ENSURE_SUCCESS(rv, rv);
    237      nsCOMPtr<nsIPaymentOptions> options;
    238      rv = payments::PaymentOptions::Create(action.options(),
    239                                            getter_AddRefs(options));
    240      NS_ENSURE_SUCCESS(rv, rv);
    241      RefPtr<payments::PaymentRequest> request = new payments::PaymentRequest(
    242          action.topOuterWindowId(), aRequestId, action.topLevelPrincipal(),
    243          methodData, details, options, action.shippingOption());
    244 
    245      if (!mRequestQueue.AppendElement(request, mozilla::fallible)) {
    246        return NS_ERROR_OUT_OF_MEMORY;
    247      }
    248      break;
    249    }
    250    case IPCPaymentActionRequest::TIPCPaymentCanMakeActionRequest: {
    251      nsCOMPtr<nsIPaymentCanMakeActionResponse> canMakeResponse =
    252          do_CreateInstance(NS_PAYMENT_CANMAKE_ACTION_RESPONSE_CONTRACT_ID);
    253      MOZ_ASSERT(canMakeResponse);
    254      rv = canMakeResponse->Init(aRequestId, CanMakePayment(aRequestId));
    255      if (NS_WARN_IF(NS_FAILED(rv))) {
    256        return rv;
    257      }
    258      rv = RespondPayment(canMakeResponse.get());
    259      if (NS_WARN_IF(NS_FAILED(rv))) {
    260        return rv;
    261      }
    262      break;
    263    }
    264    case IPCPaymentActionRequest::TIPCPaymentShowActionRequest: {
    265      const IPCPaymentShowActionRequest& action = aAction;
    266      rv = ShowPayment(aRequestId, action.isUpdating());
    267      if (NS_WARN_IF(NS_FAILED(rv))) {
    268        return rv;
    269      }
    270      break;
    271    }
    272    case IPCPaymentActionRequest::TIPCPaymentAbortActionRequest: {
    273      MOZ_ASSERT(request);
    274      request->SetState(payments::PaymentRequest::eInteractive);
    275      rv = LaunchUIAction(aRequestId, type);
    276      if (NS_WARN_IF(NS_FAILED(rv))) {
    277        return rv;
    278      }
    279      break;
    280    }
    281    case IPCPaymentActionRequest::TIPCPaymentCompleteActionRequest: {
    282      MOZ_ASSERT(request);
    283      const IPCPaymentCompleteActionRequest& action = aAction;
    284      request->SetCompleteStatus(action.completeStatus());
    285      rv = LaunchUIAction(aRequestId, type);
    286      if (NS_WARN_IF(NS_FAILED(rv))) {
    287        return rv;
    288      }
    289      break;
    290    }
    291    case IPCPaymentActionRequest::TIPCPaymentUpdateActionRequest: {
    292      const IPCPaymentUpdateActionRequest& action = aAction;
    293      nsCOMPtr<nsIPaymentDetails> details;
    294      rv = payments::PaymentDetails::Create(action.details(),
    295                                            getter_AddRefs(details));
    296      if (NS_WARN_IF(NS_FAILED(rv))) {
    297        return rv;
    298      }
    299      MOZ_ASSERT(request);
    300      rv = request->UpdatePaymentDetails(details, action.shippingOption());
    301      if (NS_WARN_IF(NS_FAILED(rv))) {
    302        return rv;
    303      }
    304      nsAutoString completeStatus;
    305      rv = request->GetCompleteStatus(completeStatus);
    306      if (NS_WARN_IF(NS_FAILED(rv))) {
    307        return rv;
    308      }
    309      if (completeStatus.Equals(u"initial"_ns)) {
    310        request->SetCompleteStatus(u""_ns);
    311      }
    312      MOZ_ASSERT(mShowingRequest && mShowingRequest == request);
    313      rv = LaunchUIAction(aRequestId, type);
    314      if (NS_WARN_IF(NS_FAILED(rv))) {
    315        return rv;
    316      }
    317      break;
    318    }
    319    case IPCPaymentActionRequest::TIPCPaymentCloseActionRequest: {
    320      rv = LaunchUIAction(aRequestId, type);
    321      if (NS_WARN_IF(NS_FAILED(rv))) {
    322        return rv;
    323      }
    324      if (mShowingRequest == request) {
    325        mShowingRequest = nullptr;
    326      }
    327      mRequestQueue.RemoveElement(request);
    328      break;
    329    }
    330    case IPCPaymentActionRequest::TIPCPaymentRetryActionRequest: {
    331      const IPCPaymentRetryActionRequest& action = aAction;
    332      MOZ_ASSERT(request);
    333      request->UpdateErrors(action.error(), action.payerErrors(),
    334                            action.paymentMethodErrors(),
    335                            action.shippingAddressErrors());
    336      request->SetState(payments::PaymentRequest::eInteractive);
    337      MOZ_ASSERT(mShowingRequest == request);
    338      rv = LaunchUIAction(
    339          aRequestId, IPCPaymentActionRequest::TIPCPaymentUpdateActionRequest);
    340      break;
    341    }
    342    default: {
    343      return NS_ERROR_FAILURE;
    344    }
    345  }
    346  return NS_OK;
    347 }
    348 
    349 NS_IMETHODIMP
    350 PaymentRequestService::RespondPayment(nsIPaymentActionResponse* aResponse) {
    351  NS_ENSURE_ARG_POINTER(aResponse);
    352  nsAutoString requestId;
    353  nsresult rv = aResponse->GetRequestId(requestId);
    354  NS_ENSURE_SUCCESS(rv, rv);
    355 
    356  RefPtr<payments::PaymentRequest> request;
    357  rv = GetPaymentRequestById(requestId, getter_AddRefs(request));
    358  if (NS_WARN_IF(NS_FAILED(rv))) {
    359    return rv;
    360  }
    361  if (!request) {
    362    return NS_ERROR_FAILURE;
    363  }
    364  uint32_t type;
    365  rv = aResponse->GetType(&type);
    366  NS_ENSURE_SUCCESS(rv, rv);
    367 
    368  // PaymentRequest can only be responded when
    369  // 1. the state is eInteractive
    370  // 2. the state is eClosed and response type is COMPLETE_ACTION
    371  // 3. the state is eCreated and response type is CANMAKE_ACTION
    372  payments::PaymentRequest::eState state = request->GetState();
    373  bool canBeResponded = (state == payments::PaymentRequest::eInteractive) ||
    374                        (state == payments::PaymentRequest::eClosed &&
    375                         type == nsIPaymentActionResponse::COMPLETE_ACTION) ||
    376                        (state == payments::PaymentRequest::eCreated &&
    377                         type == nsIPaymentActionResponse::CANMAKE_ACTION);
    378  if (!canBeResponded) {
    379    return NS_ERROR_FAILURE;
    380  }
    381 
    382  if (!request->GetIPC()) {
    383    return NS_ERROR_FAILURE;
    384  }
    385  rv = request->GetIPC()->RespondPayment(aResponse);
    386  if (NS_WARN_IF(NS_FAILED(rv))) {
    387    return rv;
    388  }
    389 
    390  // Remove PaymentRequest from mRequestQueue while receive succeeded abort
    391  // response or complete response
    392  switch (type) {
    393    case nsIPaymentActionResponse::ABORT_ACTION: {
    394      nsCOMPtr<nsIPaymentAbortActionResponse> response =
    395          do_QueryInterface(aResponse);
    396      MOZ_ASSERT(response);
    397      bool isSucceeded;
    398      rv = response->IsSucceeded(&isSucceeded);
    399      NS_ENSURE_SUCCESS(rv, rv);
    400      mShowingRequest = nullptr;
    401      if (isSucceeded) {
    402        mRequestQueue.RemoveElement(request);
    403        request->SetState(payments::PaymentRequest::eClosed);
    404      }
    405      break;
    406    }
    407    case nsIPaymentActionResponse::SHOW_ACTION: {
    408      request->SetState(payments::PaymentRequest::eClosed);
    409      nsCOMPtr<nsIPaymentShowActionResponse> response =
    410          do_QueryInterface(aResponse);
    411      MOZ_ASSERT(response);
    412      uint32_t acceptStatus;
    413      rv = response->GetAcceptStatus(&acceptStatus);
    414      NS_ENSURE_SUCCESS(rv, rv);
    415      if (acceptStatus != nsIPaymentActionResponse::PAYMENT_ACCEPTED) {
    416        // Check if rejecting the showing PaymentRequest.
    417        // If yes, set mShowingRequest as nullptr.
    418        if (mShowingRequest == request) {
    419          mShowingRequest = nullptr;
    420        }
    421        mRequestQueue.RemoveElement(request);
    422      }
    423      break;
    424    }
    425    case nsIPaymentActionResponse::COMPLETE_ACTION: {
    426      mShowingRequest = nullptr;
    427      mRequestQueue.RemoveElement(request);
    428      break;
    429    }
    430    default: {
    431      break;
    432    }
    433  }
    434  return NS_OK;
    435 }
    436 
    437 NS_IMETHODIMP
    438 PaymentRequestService::ChangeShippingAddress(const nsAString& aRequestId,
    439                                             nsIPaymentAddress* aAddress) {
    440  RefPtr<payments::PaymentRequest> request;
    441  nsresult rv = GetPaymentRequestById(aRequestId, getter_AddRefs(request));
    442  if (NS_WARN_IF(NS_FAILED(rv))) {
    443    return rv;
    444  }
    445  if (!request) {
    446    return NS_ERROR_FAILURE;
    447  }
    448  if (request->GetState() != payments::PaymentRequest::eInteractive) {
    449    return NS_ERROR_FAILURE;
    450  }
    451  if (!request->GetIPC()) {
    452    return NS_ERROR_FAILURE;
    453  }
    454  rv = request->GetIPC()->ChangeShippingAddress(aRequestId, aAddress);
    455  if (NS_WARN_IF(NS_FAILED(rv))) {
    456    return rv;
    457  }
    458  return NS_OK;
    459 }
    460 
    461 NS_IMETHODIMP
    462 PaymentRequestService::ChangeShippingOption(const nsAString& aRequestId,
    463                                            const nsAString& aOption) {
    464  RefPtr<payments::PaymentRequest> request;
    465  nsresult rv = GetPaymentRequestById(aRequestId, getter_AddRefs(request));
    466  if (NS_WARN_IF(NS_FAILED(rv))) {
    467    return rv;
    468  }
    469  if (!request) {
    470    return NS_ERROR_FAILURE;
    471  }
    472  if (request->GetState() != payments::PaymentRequest::eInteractive) {
    473    return NS_ERROR_FAILURE;
    474  }
    475  if (!request->GetIPC()) {
    476    return NS_ERROR_FAILURE;
    477  }
    478  rv = request->GetIPC()->ChangeShippingOption(aRequestId, aOption);
    479  if (NS_WARN_IF(NS_FAILED(rv))) {
    480    return rv;
    481  }
    482  return NS_OK;
    483 }
    484 
    485 NS_IMETHODIMP
    486 PaymentRequestService::ChangePayerDetail(const nsAString& aRequestId,
    487                                         const nsAString& aPayerName,
    488                                         const nsAString& aPayerEmail,
    489                                         const nsAString& aPayerPhone) {
    490  RefPtr<payments::PaymentRequest> request;
    491  nsresult rv = GetPaymentRequestById(aRequestId, getter_AddRefs(request));
    492  if (NS_WARN_IF(NS_FAILED(rv))) {
    493    return rv;
    494  }
    495  MOZ_ASSERT(request);
    496  if (!request->GetIPC()) {
    497    return NS_ERROR_FAILURE;
    498  }
    499  rv = request->GetIPC()->ChangePayerDetail(aRequestId, aPayerName, aPayerEmail,
    500                                            aPayerPhone);
    501  if (NS_WARN_IF(NS_FAILED(rv))) {
    502    return rv;
    503  }
    504  return NS_OK;
    505 }
    506 
    507 NS_IMETHODIMP
    508 PaymentRequestService::ChangePaymentMethod(
    509    const nsAString& aRequestId, const nsAString& aMethodName,
    510    nsIMethodChangeDetails* aMethodDetails) {
    511  RefPtr<payments::PaymentRequest> request;
    512  nsresult rv = GetPaymentRequestById(aRequestId, getter_AddRefs(request));
    513  if (NS_WARN_IF(NS_FAILED(rv))) {
    514    return rv;
    515  }
    516  if (!request) {
    517    return NS_ERROR_FAILURE;
    518  }
    519  if (request->GetState() != payments::PaymentRequest::eInteractive) {
    520    return NS_ERROR_FAILURE;
    521  }
    522  if (!request->GetIPC()) {
    523    return NS_ERROR_FAILURE;
    524  }
    525  rv = request->GetIPC()->ChangePaymentMethod(aRequestId, aMethodName,
    526                                              aMethodDetails);
    527  if (NS_WARN_IF(NS_FAILED(rv))) {
    528    return rv;
    529  }
    530  return NS_OK;
    531 }
    532 
    533 bool PaymentRequestService::CanMakePayment(const nsAString& aRequestId) {
    534  /*
    535   *  TODO: Check third party payment app support by traversing all
    536   *        registered third party payment apps.
    537   */
    538  return IsBasicCardPayment(aRequestId);
    539 }
    540 
    541 nsresult PaymentRequestService::ShowPayment(const nsAString& aRequestId,
    542                                            bool aIsUpdating) {
    543  nsresult rv;
    544  RefPtr<payments::PaymentRequest> request;
    545  rv = GetPaymentRequestById(aRequestId, getter_AddRefs(request));
    546  if (NS_WARN_IF(NS_FAILED(rv))) {
    547    return rv;
    548  }
    549  MOZ_ASSERT(request);
    550  request->SetState(payments::PaymentRequest::eInteractive);
    551  if (aIsUpdating) {
    552    request->SetCompleteStatus(u"initial"_ns);
    553  }
    554 
    555  if (mShowingRequest || !CanMakePayment(aRequestId)) {
    556    uint32_t responseStatus;
    557    if (mShowingRequest) {
    558      responseStatus = nsIPaymentActionResponse::PAYMENT_REJECTED;
    559    } else {
    560      responseStatus = nsIPaymentActionResponse::PAYMENT_NOTSUPPORTED;
    561    }
    562    nsCOMPtr<nsIPaymentShowActionResponse> showResponse =
    563        do_CreateInstance(NS_PAYMENT_SHOW_ACTION_RESPONSE_CONTRACT_ID);
    564    MOZ_ASSERT(showResponse);
    565    rv = showResponse->Init(aRequestId, responseStatus, u""_ns, nullptr, u""_ns,
    566                            u""_ns, u""_ns);
    567    rv = RespondPayment(showResponse.get());
    568    if (NS_WARN_IF(NS_FAILED(rv))) {
    569      return rv;
    570    }
    571  } else {
    572    mShowingRequest = request;
    573    rv = LaunchUIAction(aRequestId,
    574                        IPCPaymentActionRequest::TIPCPaymentShowActionRequest);
    575    if (NS_WARN_IF(NS_FAILED(rv))) {
    576      return rv;
    577    }
    578  }
    579  return NS_OK;
    580 }
    581 
    582 bool PaymentRequestService::IsBasicCardPayment(const nsAString& aRequestId) {
    583  RefPtr<payments::PaymentRequest> request;
    584  nsresult rv = GetPaymentRequestById(aRequestId, getter_AddRefs(request));
    585  NS_ENSURE_SUCCESS(rv, false);
    586  nsCOMPtr<nsIArray> methods;
    587  rv = request->GetPaymentMethods(getter_AddRefs(methods));
    588  NS_ENSURE_SUCCESS(rv, false);
    589  uint32_t length;
    590  rv = methods->GetLength(&length);
    591  NS_ENSURE_SUCCESS(rv, false);
    592  RefPtr<BasicCardService> service = BasicCardService::GetService();
    593  MOZ_ASSERT(service);
    594  for (uint32_t index = 0; index < length; ++index) {
    595    nsCOMPtr<nsIPaymentMethodData> method = do_QueryElementAt(methods, index);
    596    MOZ_ASSERT(method);
    597    nsAutoString supportedMethods;
    598    rv = method->GetSupportedMethods(supportedMethods);
    599    NS_ENSURE_SUCCESS(rv, false);
    600    if (service->IsBasicCardPayment(supportedMethods)) {
    601      return true;
    602    }
    603  }
    604  return false;
    605 }
    606 
    607 }  // namespace mozilla::dom