From 4a1f15b4497a667d4da639c424d5295e88c2ad33 Mon Sep 17 00:00:00 2001 From: Eden Chuang Date: Wed, 26 Jul 2017 16:07:07 +0800 Subject: [PATCH] Bug 1375345 - Basic card payment implementation. r=baku --HG-- extra : rebase_source : d581a1e117bdfc041940911487187620c5ed35ff --- .../payments/nsIPaymentActionResponse.idl | 54 ++- dom/interfaces/payments/nsIPaymentRequest.idl | 6 +- dom/payments/BasicCardPayment.cpp | 390 ++++++++++++++++++ dom/payments/BasicCardPayment.h | 54 +++ dom/payments/PaymentActionResponse.cpp | 150 ++++++- dom/payments/PaymentActionResponse.h | 47 +++ dom/payments/PaymentRequest.cpp | 25 +- dom/payments/PaymentRequest.h | 3 +- dom/payments/PaymentRequestData.cpp | 22 +- dom/payments/PaymentRequestModule.cpp | 12 + dom/payments/PaymentRequestService.cpp | 60 ++- dom/payments/PaymentRequestService.h | 3 + dom/payments/PaymentRequestUtils.cpp | 35 +- dom/payments/PaymentRequestUtils.h | 10 + dom/payments/PaymentResponse.cpp | 23 +- dom/payments/moz.build | 1 + dom/webidl/BasicCardPayment.webidl | 27 ++ dom/webidl/moz.build | 1 + 18 files changed, 897 insertions(+), 26 deletions(-) create mode 100644 dom/payments/BasicCardPayment.cpp create mode 100644 dom/payments/BasicCardPayment.h create mode 100644 dom/webidl/BasicCardPayment.webidl diff --git a/dom/interfaces/payments/nsIPaymentActionResponse.idl b/dom/interfaces/payments/nsIPaymentActionResponse.idl index 13b548dfa1d3..595a91e08838 100644 --- a/dom/interfaces/payments/nsIPaymentActionResponse.idl +++ b/dom/interfaces/payments/nsIPaymentActionResponse.idl @@ -5,6 +5,48 @@ #include "nsISupports.idl" #include "nsIVariant.idl" +#include "nsIPaymentAddress.idl" + +[builtinclass, scriptable, uuid(2a338575-c688-40ee-a157-7488ab292ef2)] +interface nsIPaymentResponseData: nsISupports +{ + const uint32_t GENERAL_RESPONSE = 0; + const uint32_t BASICCARD_RESPONSE = 1; + + readonly attribute uint32_t type; + void init(in uint32_t aType); +}; + +[builtinclass, scriptable, uuid(b986773e-2b30-4ed2-b8fe-6a96631c8000)] +interface nsIGeneralResponseData : nsIPaymentResponseData +{ + readonly attribute AString data; + + [implicit_jscontext] + void initData(in jsval aData); +}; + +/* + Since PaymentAddress is an no constructor interface type, UI code can not + easy create PaymentAddress by calling new PaymentAddress(). + Unfortunately, BasicCardResponse has a PaymentAddress attribute, billingAddress + , it means UI can not create BsaicCardResponse by calling the init() with a + given JSObject directly, because PaymentAddress creation in JS code is hard. + To let UI code can create BasicCardResponse easier, nsIBasicCardResponse is + provided for UI by passing the raw data of BasicCardResponse, +*/ +[builtinclass, scriptable, uuid(0d55a5e6-d185-44f0-b992-a8e1321e4bce)] +interface nsIBasicCardResponseData : nsIPaymentResponseData +{ + readonly attribute AString data; + + void initData(in AString aCardholderName, + in AString aCardNumber, + in AString aExpiryMonth, + in AString aExpiryYear, + in AString aCardSecurityCode, + in nsIPaymentAddress billingAddress); +}; [builtinclass, scriptable, uuid(a607c095-ef60-4a9b-a3d0-0506c60728b3)] interface nsIPaymentActionResponse : nsISupports @@ -94,7 +136,7 @@ interface nsIPaymentShowActionResponse : nsIPaymentActionResponse void init(in AString aRequestId, in uint32_t aAcceptStatus, in AString aMethodName, - in AString aData, + in nsIPaymentResponseData aData, in AString aPayerName, in AString aPayerEmail, in AString aPayerPhone); @@ -142,6 +184,16 @@ interface nsIPaymentCompleteActionResponse : nsIPaymentActionResponse }; %{C++ +#define NS_GENERAL_RESPONSE_DATA_CID \ + { 0xb986773e, 0x2b30, 0x4ed2, { 0xb8, 0xfe, 0x6a, 0x96, 0x63, 0x1c, 0x80, 0x00 } } +#define NS_GENERAL_RESPONSE_DATA_CONTRACT_ID \ + "@mozilla.org/dom/payments/general-response-data;1" + +#define NS_BASICCARD_RESPONSE_DATA_CID \ + { 0x0d55a5e6, 0xd185, 0x44f0, { 0xb9, 0x92, 0xa8, 0xe1, 0x32, 0x1e, 0x4b, 0xce } } +#define NS_BASICCARD_RESPONSE_DATA_CONTRACT_ID \ + "@mozilla.org/dom/payments/basiccard-response-data;1" + #define NS_PAYMENT_CANMAKE_ACTION_RESPONSE_CID \ { 0x52fc3f9f, 0xc0cb, 0x4874, { 0xb3, 0xd4, 0xee, 0x4b, 0x6e, 0x9c, 0xbe, 0x9c } } #define NS_PAYMENT_CANMAKE_ACTION_RESPONSE_CONTRACT_ID \ diff --git a/dom/interfaces/payments/nsIPaymentRequest.idl b/dom/interfaces/payments/nsIPaymentRequest.idl index 1b312136a427..bc282eac9e53 100644 --- a/dom/interfaces/payments/nsIPaymentRequest.idl +++ b/dom/interfaces/payments/nsIPaymentRequest.idl @@ -12,7 +12,8 @@ interface nsIArray; interface nsIPaymentMethodData : nsISupports { readonly attribute AString supportedMethods; - readonly attribute AString data; + [implicit_jscontext] + readonly attribute jsval data; }; [scriptable, builtinclass, uuid(d22a6f5f-767b-4fea-bf92-68b0b8003eba)] @@ -36,7 +37,8 @@ interface nsIPaymentDetailsModifier : nsISupports readonly attribute AString supportedMethods; readonly attribute nsIPaymentItem total; readonly attribute nsIArray additionalDisplayItems; - readonly attribute AString data; + [implicit_jscontext] + readonly attribute jsval data; }; [scriptable, builtinclass, uuid(68341551-3605-4381-b936-41e830aa88fb)] diff --git a/dom/payments/BasicCardPayment.cpp b/dom/payments/BasicCardPayment.cpp new file mode 100644 index 000000000000..7eac72b03328 --- /dev/null +++ b/dom/payments/BasicCardPayment.cpp @@ -0,0 +1,390 @@ +/* vim:set ts=2 sw=2 sts=2 et cindent: */ +/* 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 "BasicCardPayment.h" +#include "PaymentAddress.h" +#include "mozilla/ClearOnShutdown.h" +#include "nsArrayUtils.h" +#include "nsISupportsPrimitives.h" +#include "nsCharSeparatedTokenizer.h" +#include "nsDataHashtable.h" + +namespace mozilla { +namespace dom { +#ifndef PaymentBasicCardMacros +#define PaymentBasicCardMacros + +#define AMEX NS_LITERAL_STRING("amex") +#define CARTEBANCAIRE NS_LITERAL_STRING("cartebancaire") +#define DINERS NS_LITERAL_STRING("diners") +#define DISCOVER NS_LITERAL_STRING("discover") +#define JCB NS_LITERAL_STRING("jcb") +#define MASTERCARD NS_LITERAL_STRING("mastercard") +#define MIR NS_LITERAL_STRING("mir") +#define UNIONPAY NS_LITERAL_STRING("unionpay") +#define VISA NS_LITERAL_STRING("visa") + +#define CardholderName NS_LITERAL_STRING("cardholderName") +#define CardNumber NS_LITERAL_STRING("cardNumber") +#define ExpiryMonth NS_LITERAL_STRING("expiryMonth") +#define ExpiryYear NS_LITERAL_STRING("expiryYear") +#define CardSecurityCode NS_LITERAL_STRING("cardSecurityCode") + +#define Country NS_LITERAL_STRING("country") +#define AddressLine NS_LITERAL_STRING("addressLine") +#define Region NS_LITERAL_STRING("region") +#define City NS_LITERAL_STRING("city") +#define DependentLocality NS_LITERAL_STRING("dependentLocality") +#define PostalCode NS_LITERAL_STRING("postalCode") +#define SortingCode NS_LITERAL_STRING("sortingCode") +#define LanguageCode NS_LITERAL_STRING("languageCode") +#define Organization NS_LITERAL_STRING("organization") +#define Recipient NS_LITERAL_STRING("recipient") +#define Phone NS_LITERAL_STRING("phone") + +#define PropertySpliter NS_LITERAL_STRING(";") +#define KeyValueSpliter NS_LITERAL_STRING(":") +#define AddressLineSpliter NS_LITERAL_STRING("%") + +#define EncodeBasicCardProperty(aPropertyName, aPropertyValue, aResult) \ + do { \ + if (!(aPropertyValue).IsEmpty()) { \ + (aResult) += (aPropertyName) \ + + KeyValueSpliter \ + + (aPropertyValue) \ + + PropertySpliter; \ + } \ + } while(0) + +#define EncodeAddressProperty(aAddress, aPropertyName, aResult) \ + do { \ + nsAutoString propertyValue; \ + NS_ENSURE_SUCCESS((aAddress)->Get##aPropertyName(propertyValue), \ + NS_ERROR_FAILURE); \ + EncodeBasicCardProperty((aPropertyName) ,propertyValue , (aResult)); \ + } while(0) + +#define DecodeBasicCardProperty(aPropertyName, aPropertyValue, \ + aMatchPropertyName, aResponse) \ + do { \ + if ((aPropertyName).Equals((aMatchPropertyName))) { \ + (aResponse).m##aMatchPropertyName.Construct(); \ + (aResponse).m##aMatchPropertyName.Value() = (aPropertyValue); \ + } \ + } while(0) + +#define DecodeAddressProperty(aPropertyName, aPropertyValue, \ + aMatchPropertyName, aMatchPropertyValue) \ + do { \ + if ((aPropertyName).Equals((aMatchPropertyName))) { \ + (aMatchPropertyValue) = (aPropertyValue); \ + } \ + } while(0) + +#endif + +namespace { + +bool IsValidNetwork(const nsAString& aNetwork) +{ + return AMEX.Equals(aNetwork) || + CARTEBANCAIRE.Equals(aNetwork) || + DINERS.Equals(aNetwork) || + DISCOVER.Equals(aNetwork) || + JCB.Equals(aNetwork) || + MASTERCARD.Equals(aNetwork) || + MIR.Equals(aNetwork) || + UNIONPAY.Equals(aNetwork) || + VISA.Equals(aNetwork); +} + +bool IsBasicCardKey(const nsAString& aKey) +{ + return CardholderName.Equals(aKey) || + CardNumber.Equals(aKey) || + ExpiryMonth.Equals(aKey) || + ExpiryYear.Equals(aKey) || + CardSecurityCode.Equals(aKey); +} + +bool IsAddressKey(const nsAString& aKey) +{ + return Country.Equals(aKey) || + AddressLine.Equals(aKey) || + Region.Equals(aKey) || + City.Equals(aKey) || + DependentLocality.Equals(aKey) || + PostalCode.Equals(aKey) || + SortingCode.Equals(aKey) || + LanguageCode.Equals(aKey) || + Organization.Equals(aKey) || + Recipient.Equals(aKey) || + Phone.Equals(aKey); +} + +} // end of namespace + + +StaticRefPtr gBasicCardService; + +already_AddRefed +BasicCardService::GetService() +{ + if (!gBasicCardService) { + gBasicCardService = new BasicCardService(); + ClearOnShutdown(&gBasicCardService); + } + RefPtr service = gBasicCardService; + return service.forget(); +} + +bool +BasicCardService::IsBasicCardPayment(const nsAString& aSupportedMethods) +{ + return aSupportedMethods.Equals(NS_LITERAL_STRING("basic-card")); +} + +bool +BasicCardService::IsValidBasicCardRequest(JSContext* aCx, + JSObject* aData, + nsAString& aErrorMsg) +{ + if (!aData) { + return true; + } + JS::RootedValue data(aCx, JS::ObjectValue(*aData)); + + BasicCardRequest request; + if (!request.Init(aCx, data)) { + aErrorMsg.AssignLiteral("Fail to convert methodData.data to BasicCardRequest."); + return false; + } + + if (request.mSupportedNetworks.WasPassed()) { + for (const nsString& network : request.mSupportedNetworks.Value()) { + if (!IsValidNetwork(network)) { + aErrorMsg.Assign(network + NS_LITERAL_STRING(" is not an valid network.")); + return false; + } + } + } + return true; +} + +bool +BasicCardService::IsValidExpiryMonth(const nsAString& aExpiryMonth) +{ + // ExpiryMonth can only be + // 1. empty string + // 2. 01 ~ 12 + if (aExpiryMonth.IsEmpty()) { + return true; + } + if (aExpiryMonth.Length() != 2) { + return false; + } + // can only be 00 ~ 09 + if (aExpiryMonth.CharAt(0) == '0') { + if (aExpiryMonth.CharAt(1) < '0' || aExpiryMonth.CharAt(1) > '9') { + return false; + } + return true; + } + // can only be 11 or 12 + if (aExpiryMonth.CharAt(0) == '1') { + if (aExpiryMonth.CharAt(1) != '1' && aExpiryMonth.CharAt(1) != '2') { + return false; + } + return true; + } + return false; +} + +bool +BasicCardService::IsValidExpiryYear(const nsAString& aExpiryYear) +{ + // ExpiryYear can only be + // 1. empty string + // 2. 0000 ~ 9999 + if (!aExpiryYear.IsEmpty()) { + if (aExpiryYear.Length() != 4) { + return false; + } + for (uint32_t index = 0; index < 4; ++index) { + if (aExpiryYear.CharAt(index) < '0' || + aExpiryYear.CharAt(index) > '9') { + return false; + } + } + } + return true; +} + +nsresult +BasicCardService::EncodeBasicCardData(const nsAString& aCardholderName, + const nsAString& aCardNumber, + const nsAString& aExpiryMonth, + const nsAString& aExpiryYear, + const nsAString& aCardSecurityCode, + nsIPaymentAddress* aBillingAddress, + nsAString& aResult) +{ + // aBillingAddress can be nullptr + if (aCardNumber.IsEmpty()) { + return NS_ERROR_FAILURE; + } + EncodeBasicCardProperty(CardholderName, aCardholderName, aResult); + EncodeBasicCardProperty(CardNumber, aCardNumber, aResult); + EncodeBasicCardProperty(ExpiryMonth, aExpiryMonth, aResult); + EncodeBasicCardProperty(ExpiryYear, aExpiryYear, aResult); + EncodeBasicCardProperty(CardSecurityCode, aCardSecurityCode, aResult); + if (!aBillingAddress) { + return NS_OK; + } + EncodeAddressProperty(aBillingAddress, Country, aResult); + nsCOMPtr addressLine; + NS_ENSURE_SUCCESS(aBillingAddress->GetAddressLine(getter_AddRefs(addressLine)), + NS_ERROR_FAILURE); + uint32_t length; + nsAutoString addressLineString; + NS_ENSURE_SUCCESS(addressLine->GetLength(&length), NS_ERROR_FAILURE); + for (uint32_t index = 0; index < length; ++index) { + nsCOMPtr address = do_QueryElementAt(addressLine, index); + MOZ_ASSERT(address); + nsAutoString addressString; + NS_ENSURE_SUCCESS(address->GetData(addressString), NS_ERROR_FAILURE); + addressLineString += addressString + AddressLineSpliter; + } + EncodeBasicCardProperty(AddressLine ,addressLineString , aResult); + EncodeAddressProperty(aBillingAddress, Region, aResult); + EncodeAddressProperty(aBillingAddress, City, aResult); + EncodeAddressProperty(aBillingAddress, DependentLocality, aResult); + EncodeAddressProperty(aBillingAddress, PostalCode, aResult); + EncodeAddressProperty(aBillingAddress, SortingCode, aResult); + EncodeAddressProperty(aBillingAddress, LanguageCode, aResult); + EncodeAddressProperty(aBillingAddress, Organization, aResult); + EncodeAddressProperty(aBillingAddress, Recipient, aResult); + EncodeAddressProperty(aBillingAddress, Phone, aResult); + return NS_OK; +} + +nsresult +BasicCardService::DecodeBasicCardData(const nsAString& aData, + nsPIDOMWindowInner* aWindow, + BasicCardResponse& aResponse) +{ + // aWindow can be nullptr + bool isBillingAddressPassed = false; + nsTArray addressLine; + nsAutoString country; + nsAutoString region; + nsAutoString city; + nsAutoString dependentLocality; + nsAutoString postalCode; + nsAutoString sortingCode; + nsAutoString languageCode; + nsAutoString organization; + nsAutoString recipient; + nsAutoString phone; + + nsCharSeparatedTokenizer propertyTokenizer(aData, PropertySpliter.CharAt(0)); + while (propertyTokenizer.hasMoreTokens()) { + nsDependentSubstring property = propertyTokenizer.nextToken(); + nsCharSeparatedTokenizer keyValueTokenizer(property, KeyValueSpliter.CharAt(0)); + MOZ_ASSERT(keyValueTokenizer.hasMoreTokens()); + nsDependentSubstring key = keyValueTokenizer.nextToken(); + nsDependentSubstring value = keyValueTokenizer.nextToken(); + if (IsAddressKey(key) && !isBillingAddressPassed) { + isBillingAddressPassed = true; + } + if (!IsAddressKey(key) && !IsBasicCardKey(key)) { + return NS_ERROR_FAILURE; + } + + if (key.Equals(CardNumber)) { + aResponse.mCardNumber = (value); + } + + DecodeBasicCardProperty(key, value, CardholderName, aResponse); + DecodeBasicCardProperty(key, value, ExpiryMonth, aResponse); + DecodeBasicCardProperty(key, value, ExpiryYear, aResponse); + DecodeBasicCardProperty(key, value, CardSecurityCode, aResponse); + + DecodeAddressProperty(key, value, Country, country); + DecodeAddressProperty(key, value, Region, region); + DecodeAddressProperty(key, value, City, city); + DecodeAddressProperty(key, value, DependentLocality, dependentLocality); + DecodeAddressProperty(key, value, PostalCode, postalCode); + DecodeAddressProperty(key, value, SortingCode, sortingCode); + DecodeAddressProperty(key, value, LanguageCode, languageCode); + DecodeAddressProperty(key, value, Organization, organization); + DecodeAddressProperty(key, value, Recipient, recipient); + DecodeAddressProperty(key, value, Phone, phone); + + if ((key).Equals(AddressLine)) { + nsCharSeparatedTokenizer addressTokenizer(value, AddressLineSpliter.CharAt(0)); + while (addressTokenizer.hasMoreTokens()) { + addressLine.AppendElement(addressTokenizer.nextToken()); + } + } + } + if (isBillingAddressPassed) { + aResponse.mBillingAddress.Construct(); + aResponse.mBillingAddress.Value() = new PaymentAddress(aWindow, + country, + addressLine, + region, + city, + dependentLocality, + postalCode, + sortingCode, + languageCode, + organization, + recipient, + phone); + } + return NS_OK; +} + +#ifdef PaymentBasicCardMacros +#undef PaymentBasicCardMacros +#undef EncodeBasicCardProperty +#undef EncodeAddressProperty +#undef DecodeBasicCardProperty +#undef DecodeBasicCardCardNumber +#undef DecodeAddressProperty +#undef DecodeAddressLine +#undef AMEX +#undef CARTEBANCAIRE +#undef DINERS +#undef DISCOVER +#undef JCB +#undef MASTERCARD +#undef MIR +#undef UNIONPAY +#undef VISA +#undef CardholderName +#undef CardNumber +#undef ExpiryMonth +#undef ExpiryYear +#undef CardSecurityCode +#undef Country +#undef AddressLine +#undef Region +#undef City +#undef DependentLocality +#undef PostalCode +#undef SortingCode +#undef LanguageCode +#undef Organization +#undef Recipient +#undef Phone +#undef PropertySpliter +#undef KeyValueSpliter +#undef AddressLineSpliter +#endif + +} // end of namespace dom +} // end of namespace mozilla diff --git a/dom/payments/BasicCardPayment.h b/dom/payments/BasicCardPayment.h new file mode 100644 index 000000000000..800826c52ac2 --- /dev/null +++ b/dom/payments/BasicCardPayment.h @@ -0,0 +1,54 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et cindent: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_BasicCardPayment_h +#define mozilla_dom_BasicCardPayment_h + +#include "mozilla/dom/BasicCardPaymentBinding.h" +#include "nsPIDOMWindow.h" +#include "nsIPaymentAddress.h" +#include "nsTArray.h" + +namespace mozilla { +namespace dom { + +class BasicCardService final +{ +public: + NS_INLINE_DECL_REFCOUNTING(BasicCardService) + + static already_AddRefed GetService(); + + bool IsBasicCardPayment(const nsAString& aSupportedMethods); + bool IsValidBasicCardRequest(JSContext* aCx, JSObject* aData, nsAString& aErrorMsg); + bool IsValidExpiryMonth(const nsAString& aExpiryMonth); + bool IsValidExpiryYear(const nsAString& aExpiryYear); + +/* + To let BasicCardResponse using the same data type with non-BasicCard response + in IPC transferring, following two methods is used to Encode/Decode the raw + data of BasicCardResponse. +*/ + nsresult EncodeBasicCardData(const nsAString& aCardholderName, + const nsAString& aCardNumber, + const nsAString& aExpiryMonth, + const nsAString& aExpiryYear, + const nsAString& aCardSecurityCode, + nsIPaymentAddress* aBillingAddress, + nsAString& aResult); + + nsresult DecodeBasicCardData(const nsAString& aData, + nsPIDOMWindowInner* aWindow, + BasicCardResponse& aResponse); +private: + BasicCardService() = default; + ~BasicCardService() = default; +}; + +} // end of namespace dom +} // end of namespace mozilla + +#endif diff --git a/dom/payments/PaymentActionResponse.cpp b/dom/payments/PaymentActionResponse.cpp index 456aaf43bba0..5c35916c9d64 100644 --- a/dom/payments/PaymentActionResponse.cpp +++ b/dom/payments/PaymentActionResponse.cpp @@ -5,11 +5,121 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "PaymentActionResponse.h" -#include "nsIRunnable.h" +#include "PaymentRequestUtils.h" +#include "BasicCardPayment.h" namespace mozilla { namespace dom { +/* PaymentResponseData */ + +NS_IMPL_ISUPPORTS(PaymentResponseData, nsIPaymentResponseData) + +NS_IMETHODIMP +PaymentResponseData::GetType(uint32_t* aType) +{ + NS_ENSURE_ARG_POINTER(aType); + *aType = mType; + return NS_OK; +} + +NS_IMETHODIMP +PaymentResponseData::Init(const uint32_t aType) +{ + if (aType != nsIPaymentResponseData::GENERAL_RESPONSE && + aType != nsIPaymentResponseData::BASICCARD_RESPONSE) { + return NS_ERROR_FAILURE; + } + mType = aType; + return NS_OK; +} + +/* GeneralResponseData */ + +NS_IMPL_ISUPPORTS_INHERITED(GeneralResponseData, + PaymentResponseData, + nsIGeneralResponseData) + +GeneralResponseData::GeneralResponseData() + : mData(NS_LITERAL_STRING("{}")) +{ + Init(nsIPaymentResponseData::GENERAL_RESPONSE); +} + +NS_IMETHODIMP +GeneralResponseData::GetData(nsAString& aData) +{ + aData = mData; + return NS_OK; +} + +NS_IMETHODIMP +GeneralResponseData::InitData(JS::HandleValue aValue, JSContext* aCx) +{ + if (aValue.isNullOrUndefined()) { + return NS_ERROR_FAILURE; + } + nsresult rv = SerializeFromJSVal(aCx, aValue, mData); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + return NS_OK; +} + +/* BasicCardResponseData */ + +NS_IMPL_ISUPPORTS_INHERITED(BasicCardResponseData, + PaymentResponseData, + nsIBasicCardResponseData) + +BasicCardResponseData::BasicCardResponseData() +{ + Init(nsIPaymentResponseData::BASICCARD_RESPONSE); +} + +NS_IMETHODIMP +BasicCardResponseData::GetData(nsAString& aData) +{ + aData = mData; + return NS_OK; +} + +NS_IMETHODIMP +BasicCardResponseData::InitData(const nsAString& aCardholderName, + const nsAString& aCardNumber, + const nsAString& aExpiryMonth, + const nsAString& aExpiryYear, + const nsAString& aCardSecurityCode, + nsIPaymentAddress* aBillingAddress) +{ + // cardNumber is a required attribute, cannot be empty; + if (aCardNumber.IsEmpty()) { + return NS_ERROR_FAILURE; + } + + RefPtr service = BasicCardService::GetService(); + MOZ_ASSERT(service); + + if (!service->IsValidExpiryMonth(aExpiryMonth)) { + return NS_ERROR_FAILURE; + } + + if (!service->IsValidExpiryYear(aExpiryYear)) { + return NS_ERROR_FAILURE; + } + nsresult rv = service->EncodeBasicCardData(aCardholderName, + aCardNumber, + aExpiryMonth, + aExpiryYear, + aCardSecurityCode, + aBillingAddress, + mData); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + return NS_OK; +} + /* PaymentActionResponse */ NS_IMPL_ISUPPORTS(PaymentActionResponse, @@ -121,15 +231,49 @@ NS_IMETHODIMP PaymentShowActionResponse::Init(const nsAString& aRequestId, const uint32_t aAcceptStatus, const nsAString& aMethodName, - const nsAString& aData, + nsIPaymentResponseData* aData, const nsAString& aPayerName, const nsAString& aPayerEmail, const nsAString& aPayerPhone) { + NS_ENSURE_ARG_POINTER(aData); mRequestId = aRequestId; mAcceptStatus = aAcceptStatus; mMethodName = aMethodName; - mData = aData; + + RefPtr service = BasicCardService::GetService(); + MOZ_ASSERT(service); + bool isBasicCardPayment = service->IsBasicCardPayment(mMethodName); + + uint32_t responseType; + NS_ENSURE_SUCCESS(aData->GetType(&responseType), NS_ERROR_FAILURE); + switch (responseType) { + case nsIPaymentResponseData::GENERAL_RESPONSE: { + if (isBasicCardPayment) { + return NS_ERROR_FAILURE; + } + nsCOMPtr data = do_QueryInterface(aData); + MOZ_ASSERT(data); + NS_ENSURE_SUCCESS(data->GetData(mData), NS_ERROR_FAILURE); + break; + } + case nsIPaymentResponseData::BASICCARD_RESPONSE: { + if (!isBasicCardPayment) { + return NS_ERROR_FAILURE; + } + nsCOMPtr data = do_QueryInterface(aData); + MOZ_ASSERT(data); + NS_ENSURE_SUCCESS(data->GetData(mData), NS_ERROR_FAILURE); + break; + } + default: { + return NS_ERROR_FAILURE; + } + } + if (mData.IsEmpty()) { + return NS_ERROR_FAILURE; + } + mPayerName = aPayerName; mPayerEmail = aPayerEmail; mPayerPhone = aPayerPhone; diff --git a/dom/payments/PaymentActionResponse.h b/dom/payments/PaymentActionResponse.h index 1eae27104113..7f5bb1a190ed 100644 --- a/dom/payments/PaymentActionResponse.h +++ b/dom/payments/PaymentActionResponse.h @@ -14,6 +14,53 @@ namespace dom { class PaymentRequestParent; +class PaymentResponseData : public nsIPaymentResponseData +{ +public: + NS_DECL_ISUPPORTS + NS_DECL_NSIPAYMENTRESPONSEDATA + + PaymentResponseData() = default; + +protected: + virtual ~PaymentResponseData() = default; + + uint32_t mType; +}; + +class GeneralResponseData final : public PaymentResponseData + , public nsIGeneralResponseData +{ +public: + NS_DECL_ISUPPORTS_INHERITED + NS_FORWARD_NSIPAYMENTRESPONSEDATA(PaymentResponseData::) + NS_DECL_NSIGENERALRESPONSEDATA + + GeneralResponseData(); + +private: + ~GeneralResponseData() = default; + + nsString mData; +}; + +class BasicCardResponseData final : public nsIBasicCardResponseData + , public PaymentResponseData +{ +public: + NS_DECL_ISUPPORTS_INHERITED + NS_FORWARD_NSIPAYMENTRESPONSEDATA(PaymentResponseData::) + NS_DECL_NSIBASICCARDRESPONSEDATA + + BasicCardResponseData(); + +private: + ~BasicCardResponseData() = default; + + nsString mData; + nsCOMPtr mBillingAddress; +}; + class PaymentActionResponse : public nsIPaymentActionResponse { public: diff --git a/dom/payments/PaymentRequest.cpp b/dom/payments/PaymentRequest.cpp index b3c6c5116be7..b58d0b3dfeb2 100644 --- a/dom/payments/PaymentRequest.cpp +++ b/dom/payments/PaymentRequest.cpp @@ -8,6 +8,7 @@ #include "mozilla/dom/PaymentRequest.h" #include "mozilla/dom/PaymentResponse.h" #include "nsContentUtils.h" +#include "BasicCardPayment.h" #include "PaymentRequestManager.h" namespace mozilla { @@ -52,7 +53,8 @@ PaymentRequest::PrefEnabled(JSContext* aCx, JSObject* aObj) } bool -PaymentRequest::IsValidMethodData(const Sequence& aMethodData, +PaymentRequest::IsValidMethodData(JSContext* aCx, + const Sequence& aMethodData, nsAString& aErrorMsg) { if (!aMethodData.Length()) { @@ -61,11 +63,24 @@ PaymentRequest::IsValidMethodData(const Sequence& aMethodData } for (const PaymentMethodData& methodData : aMethodData) { - if (!methodData.mSupportedMethods.Length()) { + if (methodData.mSupportedMethods.IsEmpty()) { aErrorMsg.AssignLiteral( - "At least one payment method identifier is required."); + "Payment method identifier is required."); return false; } + RefPtr service = BasicCardService::GetService(); + MOZ_ASSERT(service); + if (service->IsBasicCardPayment(methodData.mSupportedMethods)) { + if (!methodData.mData.WasPassed()) { + continue; + } + MOZ_ASSERT(aCx); + if (!service->IsValidBasicCardRequest(aCx, + methodData.mData.Value(), + aErrorMsg)) { + return false; + } + } } return true; @@ -259,7 +274,9 @@ PaymentRequest::Constructor(const GlobalObject& aGlobal, // Check payment methods and details nsAutoString message; - if (!IsValidMethodData(aMethodData, message) || + if (!IsValidMethodData(nsContentUtils::GetCurrentJSContext(), + aMethodData, + message) || !IsValidDetailsInit(aDetails, message)) { aRv.ThrowTypeError(message); return nullptr; diff --git a/dom/payments/PaymentRequest.h b/dom/payments/PaymentRequest.h index 57f0b88ad257..d32b97cbf175 100644 --- a/dom/payments/PaymentRequest.h +++ b/dom/payments/PaymentRequest.h @@ -36,7 +36,8 @@ public: static bool PrefEnabled(JSContext* aCx, JSObject* aObj); - static bool IsValidMethodData(const Sequence& aMethodData, + static bool IsValidMethodData(JSContext* aCx, + const Sequence& aMethodData, nsAString& aErrorMsg); static bool diff --git a/dom/payments/PaymentRequestData.cpp b/dom/payments/PaymentRequestData.cpp index af4ee43da23d..8b1d5defda11 100644 --- a/dom/payments/PaymentRequestData.cpp +++ b/dom/payments/PaymentRequestData.cpp @@ -44,9 +44,16 @@ PaymentMethodData::GetSupportedMethods(nsAString& aSupportedMethods) } NS_IMETHODIMP -PaymentMethodData::GetData(nsAString& aData) +PaymentMethodData::GetData(JSContext* aCx, JS::MutableHandleValue aData) { - aData = mData; + if (mData.IsEmpty()) { + aData.set(JS::NullValue()); + return NS_OK; + } + nsresult rv = DeserializeToJSValue(mData, aCx ,aData); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } return NS_OK; } @@ -222,9 +229,16 @@ PaymentDetailsModifier::GetAdditionalDisplayItems(nsIArray** aAdditionalDisplayI } NS_IMETHODIMP -PaymentDetailsModifier::GetData(nsAString& aData) +PaymentDetailsModifier::GetData(JSContext* aCx, JS::MutableHandleValue aData) { - aData = mData; + if (mData.IsEmpty()) { + aData.set(JS::NullValue()); + return NS_OK; + } + nsresult rv = DeserializeToJSValue(mData, aCx ,aData); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } return NS_OK; } diff --git a/dom/payments/PaymentRequestModule.cpp b/dom/payments/PaymentRequestModule.cpp index 13e7c54c9dd2..0210adba7d78 100644 --- a/dom/payments/PaymentRequestModule.cpp +++ b/dom/payments/PaymentRequestModule.cpp @@ -10,6 +10,8 @@ #include "PaymentRequestData.h" #include "PaymentRequestService.h" +using mozilla::dom::GeneralResponseData; +using mozilla::dom::BasicCardResponseData; using mozilla::dom::PaymentActionRequest; using mozilla::dom::PaymentCreateActionRequest; using mozilla::dom::PaymentCompleteActionRequest; @@ -21,6 +23,8 @@ using mozilla::dom::PaymentCompleteActionResponse; using mozilla::dom::payments::PaymentAddress; using mozilla::dom::PaymentRequestService; +NS_GENERIC_FACTORY_CONSTRUCTOR(GeneralResponseData) +NS_GENERIC_FACTORY_CONSTRUCTOR(BasicCardResponseData) NS_GENERIC_FACTORY_CONSTRUCTOR(PaymentActionRequest) NS_GENERIC_FACTORY_CONSTRUCTOR(PaymentCreateActionRequest) NS_GENERIC_FACTORY_CONSTRUCTOR(PaymentCompleteActionRequest) @@ -33,6 +37,8 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(PaymentAddress) NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(PaymentRequestService, PaymentRequestService::GetSingleton) +NS_DEFINE_NAMED_CID(NS_GENERAL_RESPONSE_DATA_CID); +NS_DEFINE_NAMED_CID(NS_BASICCARD_RESPONSE_DATA_CID); NS_DEFINE_NAMED_CID(NS_PAYMENT_ACTION_REQUEST_CID); NS_DEFINE_NAMED_CID(NS_PAYMENT_CREATE_ACTION_REQUEST_CID); NS_DEFINE_NAMED_CID(NS_PAYMENT_COMPLETE_ACTION_REQUEST_CID); @@ -45,6 +51,8 @@ NS_DEFINE_NAMED_CID(NS_PAYMENT_ADDRESS_CID); NS_DEFINE_NAMED_CID(NS_PAYMENT_REQUEST_SERVICE_CID); static const mozilla::Module::CIDEntry kPaymentRequestCIDs[] = { + { &kNS_GENERAL_RESPONSE_DATA_CID, false, nullptr, GeneralResponseDataConstructor}, + { &kNS_BASICCARD_RESPONSE_DATA_CID, false, nullptr, BasicCardResponseDataConstructor}, { &kNS_PAYMENT_ACTION_REQUEST_CID, false, nullptr, PaymentActionRequestConstructor}, { &kNS_PAYMENT_CREATE_ACTION_REQUEST_CID, false, nullptr, PaymentCreateActionRequestConstructor}, { &kNS_PAYMENT_COMPLETE_ACTION_REQUEST_CID, false, nullptr, PaymentCompleteActionRequestConstructor}, @@ -59,6 +67,8 @@ static const mozilla::Module::CIDEntry kPaymentRequestCIDs[] = { }; static const mozilla::Module::ContractIDEntry kPaymentRequestContracts[] = { + { NS_GENERAL_RESPONSE_DATA_CONTRACT_ID, &kNS_GENERAL_RESPONSE_DATA_CID }, + { NS_BASICCARD_RESPONSE_DATA_CONTRACT_ID, &kNS_BASICCARD_RESPONSE_DATA_CID }, { NS_PAYMENT_ACTION_REQUEST_CONTRACT_ID, &kNS_PAYMENT_ACTION_REQUEST_CID }, { NS_PAYMENT_CREATE_ACTION_REQUEST_CONTRACT_ID, &kNS_PAYMENT_CREATE_ACTION_REQUEST_CID }, { NS_PAYMENT_COMPLETE_ACTION_REQUEST_CONTRACT_ID, &kNS_PAYMENT_COMPLETE_ACTION_REQUEST_CID }, @@ -73,6 +83,8 @@ static const mozilla::Module::ContractIDEntry kPaymentRequestContracts[] = { }; static const mozilla::Module::CategoryEntry kPaymentRequestCategories[] = { + { "payment-request", "GeneralResponseData", NS_GENERAL_RESPONSE_DATA_CONTRACT_ID }, + { "payment-request", "BasicCardResponseData", NS_BASICCARD_RESPONSE_DATA_CONTRACT_ID }, { "payment-request", "PaymentActionRequest", NS_PAYMENT_ACTION_REQUEST_CONTRACT_ID }, { "payment-request", "PaymentCreateActionRequest", NS_PAYMENT_CREATE_ACTION_REQUEST_CONTRACT_ID }, { "payment-request", "PaymentCompleteActionRequest", NS_PAYMENT_COMPLETE_ACTION_REQUEST_CONTRACT_ID }, diff --git a/dom/payments/PaymentRequestService.cpp b/dom/payments/PaymentRequestService.cpp index 40f97d9b0dcb..d0a0e63adb20 100644 --- a/dom/payments/PaymentRequestService.cpp +++ b/dom/payments/PaymentRequestService.cpp @@ -7,6 +7,7 @@ #include "mozilla/ClearOnShutdown.h" #include "PaymentRequestData.h" #include "PaymentRequestService.h" +#include "BasicCardPayment.h" namespace mozilla { namespace dom { @@ -300,16 +301,29 @@ PaymentRequestService::RequestPayment(nsIPaymentActionRequest* aRequest) break; } /* - * TODO: 1. Check basic card support once the Basic Card Payment spec is - * implemented. - * https://www.w3.org/TR/payment-method-basic-card/ - * 2. Check third party payment app support by traversing all + * TODO: 1. Check third party payment app support by traversing all * registered third party payment apps. */ case nsIPaymentActionRequest::CANMAKE_ACTION: { - rv = CallTestingUIAction(requestId, type); - if (NS_WARN_IF(NS_FAILED(rv))) { - return NS_ERROR_FAILURE; + if (IsBasicCardPayment(requestId)) { + nsCOMPtr canMakeResponse = + do_CreateInstance(NS_PAYMENT_CANMAKE_ACTION_RESPONSE_CONTRACT_ID); + MOZ_ASSERT(canMakeResponse); + rv = canMakeResponse->Init(requestId, true); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + nsCOMPtr response = do_QueryInterface(canMakeResponse); + MOZ_ASSERT(response); + rv = RespondPayment(response); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + } else { + rv = CallTestingUIAction(requestId, type); + if (NS_WARN_IF(NS_FAILED(rv))) { + return NS_ERROR_FAILURE; + } } break; } @@ -318,13 +332,16 @@ PaymentRequestService::RequestPayment(nsIPaymentActionRequest* aRequest) */ case nsIPaymentActionRequest::SHOW_ACTION: { if (mShowingRequest) { + nsCOMPtr responseData = + do_CreateInstance(NS_GENERAL_RESPONSE_DATA_CONTRACT_ID); + MOZ_ASSERT(responseData); nsCOMPtr showResponse = do_CreateInstance(NS_PAYMENT_SHOW_ACTION_RESPONSE_CONTRACT_ID); MOZ_ASSERT(showResponse); rv = showResponse->Init(requestId, nsIPaymentActionResponse::PAYMENT_REJECTED, EmptyString(), - EmptyString(), + responseData, EmptyString(), EmptyString(), EmptyString()); @@ -519,5 +536,32 @@ PaymentRequestService::RemoveActionCallback(const nsAString& aRequestId) return NS_OK; } +bool +PaymentRequestService::IsBasicCardPayment(const nsAString& aRequestId) +{ + nsCOMPtr payment; + nsresult rv = GetPaymentRequestById(aRequestId, getter_AddRefs(payment)); + NS_ENSURE_SUCCESS(rv, false); + nsCOMPtr methods; + rv = payment->GetPaymentMethods(getter_AddRefs(methods)); + NS_ENSURE_SUCCESS(rv, false); + uint32_t length; + rv = methods->GetLength(&length); + NS_ENSURE_SUCCESS(rv, false); + RefPtr service = BasicCardService::GetService(); + MOZ_ASSERT(service); + for (uint32_t index = 0; index < length; ++index) { + nsCOMPtr method = do_QueryElementAt(methods, index); + MOZ_ASSERT(method); + nsAutoString supportedMethods; + rv = method->GetSupportedMethods(supportedMethods); + NS_ENSURE_SUCCESS(rv, false); + if (service->IsBasicCardPayment(supportedMethods)) { + return true; + } + } + return false; +} + } // end of namespace dom } // end of namespace mozilla diff --git a/dom/payments/PaymentRequestService.h b/dom/payments/PaymentRequestService.h index 1ef033b5f161..d45f5026af5b 100644 --- a/dom/payments/PaymentRequestService.h +++ b/dom/payments/PaymentRequestService.h @@ -46,6 +46,9 @@ private: nsresult CallTestingUIAction(const nsAString& aRequestId, uint32_t aActionType); + bool + IsBasicCardPayment(const nsAString& aRequestId); + FallibleTArray> mRequestQueue; nsInterfaceHashtable mCallbackHashtable; diff --git a/dom/payments/PaymentRequestUtils.cpp b/dom/payments/PaymentRequestUtils.cpp index c5173a571e7c..49d6220a9453 100644 --- a/dom/payments/PaymentRequestUtils.cpp +++ b/dom/payments/PaymentRequestUtils.cpp @@ -14,7 +14,9 @@ namespace mozilla { namespace dom { nsresult -SerializeFromJSObject(JSContext* aCx, JS::HandleObject aObject, nsAString& aSerializedObject) { +SerializeFromJSObject(JSContext* aCx, JS::HandleObject aObject, nsAString& aSerializedObject) +{ + MOZ_ASSERT(aCx); nsCOMPtr serializer = do_CreateInstance("@mozilla.org/dom/json;1"); if (NS_WARN_IF(!serializer)) { return NS_ERROR_FAILURE; @@ -24,7 +26,21 @@ SerializeFromJSObject(JSContext* aCx, JS::HandleObject aObject, nsAString& aSeri } nsresult -DeserializeToJSObject(const nsAString& aSerializedObject, JSContext* aCx, JS::MutableHandleObject aObject) { +SerializeFromJSVal(JSContext* aCx, JS::HandleValue aValue, nsAString& aSerializedValue) +{ + MOZ_ASSERT(aCx); + nsCOMPtr serializer = do_CreateInstance("@mozilla.org/dom/json;1"); + if (NS_WARN_IF(!serializer)) { + return NS_ERROR_FAILURE; + } + JS::RootedValue value(aCx, aValue.get()); + return serializer->EncodeFromJSVal(value.address(), aCx, aSerializedValue); +} + +nsresult +DeserializeToJSObject(const nsAString& aSerializedObject, JSContext* aCx, JS::MutableHandleObject aObject) +{ + MOZ_ASSERT(aCx); nsCOMPtr deserializer = do_CreateInstance("@mozilla.org/dom/json;1"); if (NS_WARN_IF(!deserializer)) { return NS_ERROR_FAILURE; @@ -43,5 +59,20 @@ DeserializeToJSObject(const nsAString& aSerializedObject, JSContext* aCx, JS::Mu return NS_OK; } +nsresult +DeserializeToJSValue(const nsAString& aSerializedObject, JSContext* aCx, JS::MutableHandleValue aValue) +{ + MOZ_ASSERT(aCx); + nsCOMPtr deserializer = do_CreateInstance("@mozilla.org/dom/json;1"); + if (NS_WARN_IF(!deserializer)) { + return NS_ERROR_FAILURE; + } + nsresult rv = deserializer->DecodeToJSVal(aSerializedObject, aCx, aValue); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + return NS_OK; +} + } // end of namespace dom } // end of namespace mozilla diff --git a/dom/payments/PaymentRequestUtils.h b/dom/payments/PaymentRequestUtils.h index 76e85aac3ec1..9738caa4987f 100644 --- a/dom/payments/PaymentRequestUtils.h +++ b/dom/payments/PaymentRequestUtils.h @@ -18,11 +18,21 @@ SerializeFromJSObject(JSContext* aCx, JS::HandleObject aObject, nsAString& aSerializedObject); +nsresult +SerializeFromJSVal(JSContext* aCx, + JS::HandleValue aValue, + nsAString& aSerializedValue); + nsresult DeserializeToJSObject(const nsAString& aSerializedObject, JSContext* aCx, JS::MutableHandleObject aObject); +nsresult +DeserializeToJSValue(const nsAString& aSerializedObject, + JSContext* aCx, + JS::MutableHandleValue aValue); + } // end of namespace dom } // end of namespace mozilla diff --git a/dom/payments/PaymentResponse.cpp b/dom/payments/PaymentResponse.cpp index 87150967c46c..473dfb0dd60c 100644 --- a/dom/payments/PaymentResponse.cpp +++ b/dom/payments/PaymentResponse.cpp @@ -5,6 +5,9 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "mozilla/dom/PaymentResponse.h" +#include "mozilla/dom/BasicCardPaymentBinding.h" +#include "BasicCardPayment.h" +#include "PaymentAddress.h" #include "PaymentRequestUtils.h" namespace mozilla { @@ -73,7 +76,25 @@ PaymentResponse::GetMethodName(nsString& aRetVal) const void PaymentResponse::GetDetails(JSContext* aCx, JS::MutableHandle aRetVal) const { - DeserializeToJSObject(mDetails, aCx, aRetVal); + RefPtr service = BasicCardService::GetService(); + MOZ_ASSERT(service); + if (!service->IsBasicCardPayment(mMethodName)) { + DeserializeToJSObject(mDetails, aCx, aRetVal); + } else { + BasicCardResponse response; + nsresult rv = service->DecodeBasicCardData(mDetails, mOwner, response); + if (NS_WARN_IF(NS_FAILED(rv))) { + return; + } + + MOZ_ASSERT(aCx); + JS::RootedValue value(aCx); + JS::MutableHandleValue handleValue(&value); + if (NS_WARN_IF(!response.ToObjectInternal(aCx, handleValue))) { + return; + } + aRetVal.set(&handleValue.toObject()); + } } void diff --git a/dom/payments/moz.build b/dom/payments/moz.build index 24bf7eca583d..1f77316dc0c4 100644 --- a/dom/payments/moz.build +++ b/dom/payments/moz.build @@ -22,6 +22,7 @@ EXPORTS.mozilla.dom += [ ] UNIFIED_SOURCES += [ + 'BasicCardPayment.cpp', 'PaymentActionRequest.cpp', 'PaymentActionResponse.cpp', 'PaymentAddress.cpp', diff --git a/dom/webidl/BasicCardPayment.webidl b/dom/webidl/BasicCardPayment.webidl new file mode 100644 index 000000000000..3cd62a43aa62 --- /dev/null +++ b/dom/webidl/BasicCardPayment.webidl @@ -0,0 +1,27 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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/. + * + * The origin of this WebIDL file is + * https://www.w3.org/TR/payment-request/#paymentrequest-interface + */ +enum BasicCardType { + "credit", + "debit", + "prepaid" +}; + +dictionary BasicCardRequest { + sequence supportedNetworks; + sequence supportedTypes; +}; + +dictionary BasicCardResponse { + DOMString cardholderName; + required DOMString cardNumber; + DOMString expiryMonth; + DOMString expiryYear; + DOMString cardSecurityCode; + PaymentAddress? billingAddress; +}; diff --git a/dom/webidl/moz.build b/dom/webidl/moz.build index 41cd5a1cbf8c..124d89d81fb2 100644 --- a/dom/webidl/moz.build +++ b/dom/webidl/moz.build @@ -411,6 +411,7 @@ WEBIDL_FILES = [ 'BarProp.webidl', 'BaseAudioContext.webidl', 'BaseKeyframeTypes.webidl', + 'BasicCardPayment.webidl', 'BatteryManager.webidl', 'BeforeUnloadEvent.webidl', 'BiquadFilterNode.webidl',