Bug 1376623 - PaymentMethodData.supportedMethods is now DOMString. r=baku
authorEden Chuang <echuang@mozilla.com>
Sat, 01 Jul 2017 01:17:12 +0800
changeset 418186 0c719d83c30b85739d5bb573db59bcc65ca5fac4
parent 418185 72aa740f3363f8142d78dbb5d3b5c6214530da55
child 418187 6604eaddc743d8f415beef4fa9746b8ec308740d
push id1517
push userjlorenzo@mozilla.com
push dateThu, 14 Sep 2017 16:50:54 +0000
treeherdermozilla-release@3b41fd564418 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbaku
bugs1376623
milestone56.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1376623 - PaymentMethodData.supportedMethods is now DOMString. r=baku
dom/interfaces/payments/nsIPaymentRequest.idl
dom/payments/PaymentRequestData.cpp
dom/payments/PaymentRequestData.h
dom/payments/PaymentRequestManager.cpp
dom/payments/PaymentRequestUtils.cpp
dom/payments/PaymentRequestUtils.h
dom/payments/ipc/PPaymentRequest.ipdl
dom/payments/test/ConstructorChromeScript.js
dom/payments/test/head.js
dom/payments/test/multiple_payment_request.html
dom/payments/test/simple_payment_request.html
dom/payments/test/test_abortPayment.html
dom/payments/test/test_canMakePayment.html
dom/payments/test/test_constructor.html
dom/payments/test/test_showPayment.html
dom/webidl/PaymentRequest.webidl
--- a/dom/interfaces/payments/nsIPaymentRequest.idl
+++ b/dom/interfaces/payments/nsIPaymentRequest.idl
@@ -6,17 +6,17 @@
 #include "nsISupports.idl"
 #include "nsIVariant.idl"
 
 interface nsIArray;
 
 [scriptable, builtinclass, uuid(2fe296cc-d917-4820-b492-aa42df23f9b4)]
 interface nsIPaymentMethodData : nsISupports
 {
-  readonly attribute nsIArray supportedMethods;
+  readonly attribute AString supportedMethods;
   readonly attribute AString data;
 };
 
 [scriptable, builtinclass, uuid(d22a6f5f-767b-4fea-bf92-68b0b8003eba)]
 interface nsIPaymentCurrencyAmount : nsISupports
 {
   readonly attribute AString currency;
   readonly attribute AString value;
@@ -28,17 +28,17 @@ interface nsIPaymentItem : nsISupports
   readonly attribute AString label;
   readonly attribute nsIPaymentCurrencyAmount amount;
   readonly attribute boolean pending;
 };
 
 [scriptable, builtinclass, uuid(74259861-c318-40e8-b3d5-518e701bed80)]
 interface nsIPaymentDetailsModifier : nsISupports
 {
-  readonly attribute nsIArray supportedMethods;
+  readonly attribute AString supportedMethods;
   readonly attribute nsIPaymentItem total;
   readonly attribute nsIArray additionalDisplayItems;
   readonly attribute AString data;
 };
 
 [scriptable, builtinclass, uuid(68341551-3605-4381-b936-41e830aa88fb)]
 interface nsIPaymentShippingOption : nsISupports
 {
--- a/dom/payments/PaymentRequestData.cpp
+++ b/dom/payments/PaymentRequestData.cpp
@@ -13,47 +13,38 @@ namespace mozilla {
 namespace dom {
 namespace payments {
 
 /* PaymentMethodData */
 
 NS_IMPL_ISUPPORTS(PaymentMethodData,
                   nsIPaymentMethodData)
 
-PaymentMethodData::PaymentMethodData(nsIArray* aSupportedMethods,
+PaymentMethodData::PaymentMethodData(const nsAString& aSupportedMethods,
                                      const nsAString& aData)
   : mSupportedMethods(aSupportedMethods)
   , mData(aData)
 {
 }
 
 nsresult
 PaymentMethodData::Create(const IPCPaymentMethodData& aIPCMethodData,
                           nsIPaymentMethodData** aMethodData)
 {
   NS_ENSURE_ARG_POINTER(aMethodData);
-  nsCOMPtr<nsIArray> supportedMethods;
-  nsresult rv = ConvertStringstoISupportsStrings(aIPCMethodData.supportedMethods(),
-                                                 getter_AddRefs(supportedMethods));
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return rv;
-  }
   nsCOMPtr<nsIPaymentMethodData> methodData =
-    new PaymentMethodData(supportedMethods, aIPCMethodData.data());
+    new PaymentMethodData(aIPCMethodData.supportedMethods(), aIPCMethodData.data());
   methodData.forget(aMethodData);
   return NS_OK;
 }
 
 NS_IMETHODIMP
-PaymentMethodData::GetSupportedMethods(nsIArray** aSupportedMethods)
+PaymentMethodData::GetSupportedMethods(nsAString& aSupportedMethods)
 {
-  NS_ENSURE_ARG_POINTER(aSupportedMethods);
-  MOZ_ASSERT(mSupportedMethods);
-  nsCOMPtr<nsIArray> supportedMethods = mSupportedMethods;
-  supportedMethods.forget(aSupportedMethods);
+  aSupportedMethods = mSupportedMethods;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 PaymentMethodData::GetData(nsAString& aData)
 {
   aData = mData;
   return NS_OK;
@@ -151,17 +142,17 @@ PaymentItem::GetPending(bool* aPending)
   return NS_OK;
 }
 
 /* PaymentDetailsModifier */
 
 NS_IMPL_ISUPPORTS(PaymentDetailsModifier,
                   nsIPaymentDetailsModifier)
 
-PaymentDetailsModifier::PaymentDetailsModifier(nsIArray* aSupportedMethods,
+PaymentDetailsModifier::PaymentDetailsModifier(const nsAString& aSupportedMethods,
                                                nsIPaymentItem* aTotal,
                                                nsIArray* aAdditionalDisplayItems,
                                                const nsAString& aData)
   : mSupportedMethods(aSupportedMethods)
   , mTotal(aTotal)
   , mAdditionalDisplayItems(aAdditionalDisplayItems)
   , mData(aData)
 {
@@ -173,23 +164,16 @@ PaymentDetailsModifier::Create(const IPC
 {
   NS_ENSURE_ARG_POINTER(aModifier);
   nsCOMPtr<nsIPaymentItem> total;
   nsresult rv = PaymentItem::Create(aIPCModifier.total(), getter_AddRefs(total));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
-  nsCOMPtr<nsIArray> supportedMethods;
-  rv = ConvertStringstoISupportsStrings(aIPCModifier.supportedMethods(),
-                                        getter_AddRefs(supportedMethods));
-   if (NS_WARN_IF(NS_FAILED(rv))) {
-    return rv;
-  }
-
   nsCOMPtr<nsIArray> displayItems;
   if (aIPCModifier.additionalDisplayItemsPassed()) {
     nsCOMPtr<nsIMutableArray> items = do_CreateInstance(NS_ARRAY_CONTRACTID);
     MOZ_ASSERT(items);
     for (const IPCPaymentItem& item : aIPCModifier.additionalDisplayItems()) {
       nsCOMPtr<nsIPaymentItem> additionalItem;
       rv = PaymentItem::Create(item, getter_AddRefs(additionalItem));
       if (NS_WARN_IF(NS_FAILED(rv))) {
@@ -198,28 +182,28 @@ PaymentDetailsModifier::Create(const IPC
       rv = items->AppendElement(additionalItem, false);
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
     }
     displayItems = items.forget();
   }
   nsCOMPtr<nsIPaymentDetailsModifier> modifier =
-    new PaymentDetailsModifier(supportedMethods, total, displayItems, aIPCModifier.data());
+    new PaymentDetailsModifier(aIPCModifier.supportedMethods(),
+                               total,
+                               displayItems,
+                               aIPCModifier.data());
   modifier.forget(aModifier);
   return NS_OK;
 }
 
 NS_IMETHODIMP
-PaymentDetailsModifier::GetSupportedMethods(nsIArray** aSupportedMethods)
+PaymentDetailsModifier::GetSupportedMethods(nsAString& aSupportedMethods)
 {
-  NS_ENSURE_ARG_POINTER(aSupportedMethods);
-  MOZ_ASSERT(mSupportedMethods);
-  nsCOMPtr<nsIArray> supportedMethods = mSupportedMethods;
-  supportedMethods.forget(aSupportedMethods);
+  aSupportedMethods = mSupportedMethods;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 PaymentDetailsModifier::GetTotal(nsIPaymentItem** aTotal)
 {
   NS_ENSURE_ARG_POINTER(aTotal);
   MOZ_ASSERT(mTotal);
@@ -654,17 +638,17 @@ PaymentRequest::UpdatePaymentDetails(nsI
   MOZ_ASSERT(aPaymentDetails);
   return mPaymentDetails->Update(aPaymentDetails);
 }
 
 /* PaymentAddress */
 
 NS_IMPL_ISUPPORTS(PaymentAddress, nsIPaymentAddress)
 
-nsresult
+NS_IMETHODIMP
 PaymentAddress::Init(const nsAString& aCountry,
                      nsIArray* aAddressLine,
                      const nsAString& aRegion,
                      const nsAString& aCity,
                      const nsAString& aDependentLocality,
                      const nsAString& aPostalCode,
                      const nsAString& aSortingCode,
                      const nsAString& aLanguageCode,
@@ -681,89 +665,89 @@ PaymentAddress::Init(const nsAString& aC
   mSortingCode = aSortingCode;
   mLanguageCode = aLanguageCode;
   mOrganization = aOrganization;
   mRecipient = aRecipient;
   mPhone = aPhone;
   return NS_OK;
 }
 
-nsresult
+NS_IMETHODIMP
 PaymentAddress::GetCountry(nsAString& aCountry)
 {
   aCountry = mCountry;
   return NS_OK;
 }
 
-nsresult
+NS_IMETHODIMP
 PaymentAddress::GetAddressLine(nsIArray** aAddressLine)
 {
   NS_ENSURE_ARG_POINTER(aAddressLine);
   nsCOMPtr<nsIArray> addressLine = mAddressLine;
   addressLine.forget(aAddressLine);
   return NS_OK;
 }
 
-nsresult
+NS_IMETHODIMP
 PaymentAddress::GetRegion(nsAString& aRegion)
 {
   aRegion = mRegion;
   return NS_OK;
 }
 
-nsresult
+NS_IMETHODIMP
 PaymentAddress::GetCity(nsAString& aCity)
 {
   aCity = mCity;
   return NS_OK;
 }
 
-nsresult
+NS_IMETHODIMP
 PaymentAddress::GetDependentLocality(nsAString& aDependentLocality)
 {
   aDependentLocality = mDependentLocality;
   return NS_OK;
 }
 
-nsresult
+NS_IMETHODIMP
 PaymentAddress::GetPostalCode(nsAString& aPostalCode)
 {
   aPostalCode = mPostalCode;
   return NS_OK;
 }
 
-nsresult
+NS_IMETHODIMP
 PaymentAddress::GetSortingCode(nsAString& aSortingCode)
 {
   aSortingCode = mSortingCode;
   return NS_OK;
 }
 
-nsresult
+NS_IMETHODIMP
 PaymentAddress::GetLanguageCode(nsAString& aLanguageCode)
 {
   aLanguageCode = mLanguageCode;
   return NS_OK;
 }
 
-nsresult
+NS_IMETHODIMP
 PaymentAddress::GetOrganization(nsAString& aOrganization)
 {
   aOrganization = mOrganization;
   return NS_OK;
 }
 
-nsresult
+NS_IMETHODIMP
 PaymentAddress::GetRecipient(nsAString& aRecipient)
 {
   aRecipient = mRecipient;
   return NS_OK;
 }
 
-nsresult
+NS_IMETHODIMP
 PaymentAddress::GetPhone(nsAString& aPhone)
 {
   aPhone = mPhone;
   return NS_OK;
 }
 
 } // end of namespace payment
 } // end of namespace dom
--- a/dom/payments/PaymentRequestData.h
+++ b/dom/payments/PaymentRequestData.h
@@ -21,22 +21,22 @@ class PaymentMethodData final : public n
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIPAYMENTMETHODDATA
 
   static nsresult Create(const IPCPaymentMethodData& aIPCMethodData,
                          nsIPaymentMethodData** aMethodData);
 
 private:
-  PaymentMethodData(nsIArray* aSupportedMethods,
+  PaymentMethodData(const nsAString& aSupportedMethods,
                     const nsAString& aData);
 
   ~PaymentMethodData() = default;
 
-  nsCOMPtr<nsIArray> mSupportedMethods;
+  nsString mSupportedMethods;
   nsString mData;
 };
 
 class PaymentCurrencyAmount final : public nsIPaymentCurrencyAmount
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIPAYMENTCURRENCYAMOUNT
@@ -79,24 +79,24 @@ class PaymentDetailsModifier final : pub
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIPAYMENTDETAILSMODIFIER
 
   static nsresult Create(const IPCPaymentDetailsModifier& aIPCModifier,
                          nsIPaymentDetailsModifier** aModifier);
 
 private:
-  PaymentDetailsModifier(nsIArray* aSupportedMethods,
+  PaymentDetailsModifier(const nsAString& aSupportedMethods,
                          nsIPaymentItem* aTotal,
                          nsIArray* aAdditionalDisplayItems,
                          const nsAString& aData);
 
   ~PaymentDetailsModifier() = default;
 
-  nsCOMPtr<nsIArray> mSupportedMethods;
+  nsString mSupportedMethods;
   nsCOMPtr<nsIPaymentItem> mTotal;
   nsCOMPtr<nsIArray> mAdditionalDisplayItems;
   nsString mData;
 };
 
 class PaymentShippingOption final : public nsIPaymentShippingOption
 {
 public:
--- a/dom/payments/PaymentRequestManager.cpp
+++ b/dom/payments/PaymentRequestManager.cpp
@@ -20,34 +20,28 @@ namespace {
 /*
  *  Following Convert* functions are used for convert PaymentRequest structs
  *  to transferable structs for IPC.
  */
 nsresult
 ConvertMethodData(const PaymentMethodData& aMethodData,
                   IPCPaymentMethodData& aIPCMethodData)
 {
-  // Convert Sequence<nsString> to nsTArray<nsString>
-  nsTArray<nsString> supportedMethods;
-  for (const nsString& method : aMethodData.mSupportedMethods) {
-    supportedMethods.AppendElement(method);
-  }
-
   // Convert JSObject to a serialized string
   nsAutoString serializedData;
   if (aMethodData.mData.WasPassed()) {
     JSContext* cx = nsContentUtils::GetCurrentJSContext();
     MOZ_ASSERT(cx);
     JS::RootedObject object(cx, aMethodData.mData.Value());
     nsresult rv = SerializeFromJSObject(cx, object, serializedData);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
   }
-  aIPCMethodData = IPCPaymentMethodData(supportedMethods, serializedData);
+  aIPCMethodData = IPCPaymentMethodData(aMethodData.mSupportedMethods, serializedData);
   return NS_OK;
 }
 
 void
 ConvertCurrencyAmount(const PaymentCurrencyAmount& aAmount,
                       IPCPaymentCurrencyAmount& aIPCCurrencyAmount)
 {
   aIPCCurrencyAmount = IPCPaymentCurrencyAmount(aAmount.mCurrency, aAmount.mValue);
@@ -60,22 +54,16 @@ ConvertItem(const PaymentItem& aItem, IP
   ConvertCurrencyAmount(aItem.mAmount, amount);
   aIPCItem = IPCPaymentItem(aItem.mLabel, amount, aItem.mPending);
 }
 
 nsresult
 ConvertModifier(const PaymentDetailsModifier& aModifier,
                 IPCPaymentDetailsModifier& aIPCModifier)
 {
-  // Convert Sequence<nsString> to nsTArray<nsString>
-  nsTArray<nsString> supportedMethods;
-  for (const nsString& method : aModifier.mSupportedMethods) {
-    supportedMethods.AppendElement(method);
-  }
-
   // Convert JSObject to a serialized string
   nsAutoString serializedData;
   if (aModifier.mData.WasPassed()) {
     JSContext* cx = nsContentUtils::GetCurrentJSContext();
     MOZ_ASSERT(cx);
     JS::RootedObject object(cx, aModifier.mData.Value());
     nsresult rv = SerializeFromJSObject(cx, object, serializedData);
     if (NS_WARN_IF(NS_FAILED(rv))) {
@@ -89,21 +77,21 @@ ConvertModifier(const PaymentDetailsModi
   nsTArray<IPCPaymentItem> additionalDisplayItems;
   if (aModifier.mAdditionalDisplayItems.WasPassed()) {
     for (const PaymentItem& item : aModifier.mAdditionalDisplayItems.Value()) {
       IPCPaymentItem displayItem;
       ConvertItem(item, displayItem);
       additionalDisplayItems.AppendElement(displayItem);
     }
   }
-  aIPCModifier = IPCPaymentDetailsModifier(supportedMethods,
-                                          total,
-                                          additionalDisplayItems,
-                                          serializedData,
-                                          aModifier.mAdditionalDisplayItems.WasPassed());
+  aIPCModifier = IPCPaymentDetailsModifier(aModifier.mSupportedMethods,
+                                           total,
+                                           additionalDisplayItems,
+                                           serializedData,
+                                           aModifier.mAdditionalDisplayItems.WasPassed());
   return NS_OK;
 }
 
 void
 ConvertShippingOption(const PaymentShippingOption& aOption,
                       IPCPaymentShippingOption& aIPCOption)
 {
   IPCPaymentCurrencyAmount amount;
--- a/dom/payments/PaymentRequestUtils.cpp
+++ b/dom/payments/PaymentRequestUtils.cpp
@@ -38,36 +38,10 @@ DeserializeToJSObject(const nsAString& a
   if (value.isObject()) {
     aObject.set(&value.toObject());
   } else {
     aObject.set(nullptr);
   }
   return NS_OK;
 }
 
-nsresult
-ConvertStringstoISupportsStrings(const nsTArray<nsString>& aStrings,
-                                 nsIArray** aIStrings)
-{
-  NS_ENSURE_ARG_POINTER(aIStrings);
-  *aIStrings = nullptr;
-  nsCOMPtr<nsIMutableArray> iStrings = do_CreateInstance(NS_ARRAY_CONTRACTID);
-  for (const nsString& string : aStrings) {
-    nsCOMPtr<nsISupportsString> iString =
-      do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID);
-    if (NS_WARN_IF(!iString)) {
-      return NS_ERROR_FAILURE;
-    }
-    nsresult rv = iString->SetData(string);
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-      return rv;
-    }
-    rv = iStrings->AppendElement(iString, false);
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-      return rv;
-    }
-  }
-  iStrings.forget(aIStrings);
-  return NS_OK;
-}
-
 } // end of namespace dom
 } // end of namespace mozilla
--- a/dom/payments/PaymentRequestUtils.h
+++ b/dom/payments/PaymentRequestUtils.h
@@ -18,16 +18,12 @@ SerializeFromJSObject(JSContext* aCx,
                       JS::HandleObject aObject,
                       nsAString& aSerializedObject);
 
 nsresult
 DeserializeToJSObject(const nsAString& aSerializedObject,
                       JSContext* aCx,
                       JS::MutableHandleObject aObject);
 
-nsresult
-ConvertStringstoISupportsStrings(const nsTArray<nsString>& aStrings,
-                                 nsIArray** aIStrings);
-
 } // end of namespace dom
 } // end of namespace mozilla
 
 #endif
--- a/dom/payments/ipc/PPaymentRequest.ipdl
+++ b/dom/payments/ipc/PPaymentRequest.ipdl
@@ -6,17 +6,17 @@
 
 include protocol PBrowser;
 
 namespace mozilla {
 namespace dom {
 
 struct IPCPaymentMethodData
 {
-  nsString[] supportedMethods;
+  nsString supportedMethods;
   nsString data;
 };
 
 struct IPCPaymentCurrencyAmount
 {
   nsString currency;
   nsString value;
 };
@@ -25,17 +25,17 @@ struct IPCPaymentItem
 {
   nsString label;
   IPCPaymentCurrencyAmount amount;
   bool pending;
 };
 
 struct IPCPaymentDetailsModifier
 {
-  nsString[] supportedMethods;
+  nsString supportedMethods;
   IPCPaymentItem total;
   IPCPaymentItem[] additionalDisplayItems;
   nsString data;
   bool additionalDisplayItemsPassed;
 };
 
 struct IPCPaymentShippingOption
 {
--- a/dom/payments/test/ConstructorChromeScript.js
+++ b/dom/payments/test/ConstructorChromeScript.js
@@ -17,20 +17,17 @@ function checkSimplestRequest(payRequest
   if (payRequest.paymentMethods.length != 1) {
     emitTestFail("paymentMethods' length should be 1.");
   }
 
   const methodData = payRequest.paymentMethods.queryElementAt(0, Ci.nsIPaymentMethodData);
   if (!methodData) {
     emitTestFail("Fail to get payment methodData.");
   }
-  if (methodData.supportedMethods.length != 1) {
-    emitTestFail("supportedMethods' length should be 1.");
-  }
-  const supportedMethod = methodData.supportedMethods.queryElementAt(0, Ci.nsISupportsString);
+  const supportedMethod = methodData.supportedMethods;
   if (supportedMethod != "basic-card") {
     emitTestFail("supported method should be 'basic-card'.");
   }
 
   // checking the passed PaymentDetails parameter
   const details = payRequest.paymentDetails;
   if (details.totalItem.label != "Total") {
     emitTestFail("total item's label should be 'Total'.");
@@ -75,20 +72,17 @@ function checkComplexRequest(payRequest)
   if (payRequest.paymentMethods.length != 1) {
     emitTestFail("paymentMethods' length should be 1.");
   }
 
   const methodData = payRequest.paymentMethods.queryElementAt(0, Ci.nsIPaymentMethodData);
   if (!methodData) {
     emitTestFail("Fail to get payment methodData.");
   }
-  if (methodData.supportedMethods.length != 1) {
-    emitTestFail("supportedMethods' length should be 1.");
-  }
-  let supportedMethod = methodData.supportedMethods.queryElementAt(0, Ci.nsISupportsString);
+  let supportedMethod = methodData.supportedMethods;
   if (supportedMethod != "basic-card") {
     emitTestFail("supported method should be 'basic-card'.");
   }
   const data = methodData.data;
   if (data != "{\"supportedNetworks\":[\"unionpay\",\"visa\",\"mastercard\",\"amex\",\"discover\",\"diners\",\"jcb\",\"mir\"],\"supportedTypes\":[\"prepaid\",\"debit\",\"credit\"]}") {
     emitTestFail("method data should be '{\"supportedNetworks\":[\"unionpay\",\"visa\",\"mastercard\",\"amex\",\"discover\",\"diners\",\"jcb\",\"mir\"],\"supportedTypes\":[\"prepaid\",\"debit\",\"credit\"]}', but got '" + data + "'.");
   }
   // checking the passed PaymentDetails parameter
@@ -137,21 +131,17 @@ function checkComplexRequest(payRequest)
   const modifiers = details.modifiers;
   if (!modifiers) {
     emitTestFail("details.displayItems should not be undefined.");
   }
   if (modifiers.length != 1) {
     emitTestFail("modifiers' length should be 1.");
   }
   const modifier = modifiers.queryElementAt(0, Ci.nsIPaymentDetailsModifier);
-  const modifierSupportedMethods = modifier.supportedMethods;
-  if (modifierSupportedMethods.length != 1) {
-    emitTestFail("modifier's supported methods length should be 1.");
-  }
-  supportedMethod = modifierSupportedMethods.queryElementAt(0, Ci.nsISupportsString);
+  const supportedMethods = modifier.supportedMethods;
   if (supportedMethod != "basic-card") {
     emitTestFail("modifier's supported method name should be 'basic-card'.");
   }
   if (modifier.total.label != "Discounted Total") {
     emitTestFail("modifier's total label should be 'Discounted Total'.");
   }
   if (modifier.total.amount.currency != "USD") {
     emitTestFail("modifier's total currency should be 'USD'.");
--- a/dom/payments/test/head.js
+++ b/dom/payments/test/head.js
@@ -2,21 +2,17 @@ const kTestRoot = getRootDirectory(gTest
                                                       "https://example.com");
 
 function checkSimplePayment(aSimplePayment) {
   // checking the passed PaymentMethods parameter
   is(aSimplePayment.paymentMethods.length, 1, "paymentMethods' length should be 1.");
 
   const methodData = aSimplePayment.paymentMethods.queryElementAt(0, Ci.nsIPaymentMethodData);
   ok(methodData, "Fail to get payment methodData.");
-  is(methodData.supportedMethods.length, 2, "supportedMethods' length should be 2.");
-  let supportedMethod = methodData.supportedMethods.queryElementAt(0, Ci.nsISupportsString);
-  is(supportedMethod, "MyPay", "1st supported method should be 'MyPay'.");
-  supportedMethod = methodData.supportedMethods.queryElementAt(1, Ci.nsISupportsString);
-  is(supportedMethod, "TestPay", "2nd supported method should be 'TestPay'.");
+  is(methodData.supportedMethods, "MyPay", "supported method should be 'MyPay'.");
   is(methodData.data, "", "method data should be empty");
 
   // checking the passed PaymentDetails parameter
   const details = aSimplePayment.paymentDetails;
   is(details.id, "simple details", "details.id should be 'simple details'.");
   is(details.totalItem.label, "Donation", "total item's label should be 'Donation'.");
   is(details.totalItem.amount.currency, "USD", "total item's currency should be 'USD'.");
   is(details.totalItem.amount.value, "55.00", "total item's value should be '55.00'.");
@@ -35,21 +31,17 @@ function checkSimplePayment(aSimplePayme
 }
 
 function checkComplexPayment(aPayment) {
   // checking the passed PaymentMethods parameter
   is(aPayment.paymentMethods.length, 1, "paymentMethods' length should be 1.");
 
   const methodData = aPayment.paymentMethods.queryElementAt(0, Ci.nsIPaymentMethodData);
   ok(methodData, "Fail to get payment methodData.");
-  is(methodData.supportedMethods.length, 2, "supportedMethods' length should be 2.");
-  let supportedMethod = methodData.supportedMethods.queryElementAt(0, Ci.nsISupportsString);
-  is(supportedMethod, "MyPay", "1st supported method should be 'MyPay'.");
-  supportedMethod = methodData.supportedMethods.queryElementAt(1, Ci.nsISupportsString);
-  is(supportedMethod, "TestPay", "2nd supported method should be 'TestPay'.");
+  is(methodData.supportedMethods, "MyPay", "supported method should be 'MyPay'.");
   is(methodData.data, "", "method data should be empty");
 
   // checking the passed PaymentDetails parameter
   const details = aPayment.paymentDetails;
   is(details.id, "complex details", "details.id should be 'complex details'.");
   is(details.totalItem.label, "Donation", "total item's label should be 'Donation'.");
   is(details.totalItem.amount.currency, "USD", "total item's currency should be 'USD'.");
   is(details.totalItem.amount.value, "55.00", "total item's value should be '55.00'.");
@@ -64,20 +56,17 @@ function checkComplexPayment(aPayment) {
   is(item.label, "Friends and family discount", "2nd display item's label should be 'Friends and family discount'.");
   is(item.amount.currency, "USD", "2nd display item's currency should be 'USD'.");
   is(item.amount.value, "10.00", "2nd display item's value should be '10.00'.");
 
   const modifiers = details.modifiers;
   is(modifiers.length, 1, "modifiers' length should be 1.");
 
   const modifier = modifiers.queryElementAt(0, Ci.nsIPaymentDetailsModifier);
-  const modifierSupportedMethods = modifier.supportedMethods;
-  is(modifierSupportedMethods.length, 1, "modifier's supported methods length should be 1.");
-  supportedMethod = modifierSupportedMethods.queryElementAt(0, Ci.nsISupportsString);
-  is(supportedMethod, "MyPay", "modifier's supported method name should be 'MyPay'.");
+  is(modifier.supportedMethods, "MyPay", "modifier's supported method name should be 'MyPay'.");
   is(modifier.total.label, "Discounted donation", "modifier's total label should be 'Discounted donation'.");
   is(modifier.total.amount.currency, "USD", "modifier's total currency should be 'USD'.");
   is(modifier.total.amount.value, "45.00", "modifier's total value should be '45.00'.");
 
   const additionalItems = modifier.additionalDisplayItems;
   is(additionalItems.length, "1", "additionalDisplayItems' length should be 1.");
   const additionalItem = additionalItems.queryElementAt(0, Ci.nsIPaymentItem);
   is(additionalItem.label, "MyPay discount", "additional item's label should be 'MyPay discount'.");
--- a/dom/payments/test/multiple_payment_request.html
+++ b/dom/payments/test/multiple_payment_request.html
@@ -3,17 +3,17 @@
   <head>
     <title>Payment Request Testing</title>
     <meta content="text/html;charset=utf-8" http-equiv="Content-Type">
     <meta content="utf-8" http-equiv="encoding">
   </head>
   <body>
     <script type="text/javascript">
     const supportedInstruments = [{
-      supportedMethods: [ "MyPay", "TestPay" ]
+      supportedMethods: "MyPay"
     }];
     const complexDetails = {
       id: "complex details",
       total: {
         label: "Donation",
         amount: { currency: "USD", value: "55.00" }
       },
       displayItems: [
@@ -23,17 +23,17 @@
         },
         {
           label: "Friends and family discount",
           amount: { currency: "USD", value: "10.00", }
         }
       ],
       modifiers: [
         {
-          supportedMethods: ["MyPay"],
+          supportedMethods: "MyPay",
           total: {
             label: "Discounted donation",
             amount: { currency: "USD", value: "45.00", }
           },
           additionalDisplayItems: [
             {
               label: "MyPay discount",
               amount: { currency: "USD", value: "-10.00", }
--- a/dom/payments/test/simple_payment_request.html
+++ b/dom/payments/test/simple_payment_request.html
@@ -3,17 +3,17 @@
   <head>
     <title>Payment Request Testing</title>
     <meta content="text/html;charset=utf-8" http-equiv="Content-Type">
     <meta content="utf-8" http-equiv="encoding">
   </head>
   <body>
     <script type="text/javascript">
     const supportedInstruments = [{
-      supportedMethods: [ "MyPay", "TestPay" ]
+      supportedMethods: "MyPay",
     }];
     const details = {
       id: "simple details",
       total: {
         label: "Donation",
         amount: { currency: "USD", value: "55.00" }
       },
     };
--- a/dom/payments/test/test_abortPayment.html
+++ b/dom/payments/test/test_abortPayment.html
@@ -9,17 +9,17 @@ https://bugzilla.mozilla.org/show_bug.cg
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
   <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <script type="application/javascript">
 
   "use strict";
   SimpleTest.waitForExplicitFinish();
 
   const defaultMethods = [{
-    supportedMethods: ["basic-card"],
+    supportedMethods: "basic-card",
   }];
   const defaultDetails = {
     total: {
       label: "Total",
       amount: {
         currency: "USD",
         value: "1.00"
       }
--- a/dom/payments/test/test_canMakePayment.html
+++ b/dom/payments/test/test_canMakePayment.html
@@ -12,17 +12,17 @@ https://bugzilla.mozilla.org/show_bug.cg
 
   "use strict";
   SimpleTest.waitForExplicitFinish();
 
   var gUrl = SimpleTest.getTestFileURL('CanMakePaymentChromeScript.js');
   var gScript = SpecialPowers.loadChromeScript(gUrl);
 
   const defaultMethods = [{
-    supportedMethods: ["basic-card"],
+    supportedMethods: "basic-card",
   }];
   const defaultDetails = {
     total: {
       label: "Total",
       amount: {
         currency: "USD",
         value: "1.00"
       }
--- a/dom/payments/test/test_constructor.html
+++ b/dom/payments/test/test_constructor.html
@@ -17,30 +17,30 @@ https://bugzilla.mozilla.org/show_bug.cg
   var gScript = SpecialPowers.loadChromeScript(gUrl);
 
   function testFailHandler(message) {
     ok(false, message);
   }
   gScript.addMessageListener("test-fail", testFailHandler);
 
   const simplestMethods = [{
-    supportedMethods: [ "basic-card" ],
+    supportedMethods: "basic-card",
   }];
   const simplestDetails = {
     total: {
       label: "Total",
       amount: {
         currency: "USD",
         value: "1.00"
       }
     }
   };
 
   const complexMethods = [{
-    supportedMethods: [ "basic-card" ],
+    supportedMethods: "basic-card",
     data: {
       supportedNetworks: ['unionpay', 'visa', 'mastercard', 'amex', 'discover',
                           'diners', 'jcb', 'mir',
       ],
       supportedTypes: ['prepaid', 'debit', 'credit'],
     },
   }];
 
@@ -66,17 +66,17 @@ https://bugzilla.mozilla.org/show_bug.cg
         amount: {
           currency: "USD",
           value: "40.00"
         }
       }
     ],
     modifiers: [
       {
-        supportedMethods: ["basic-card"],
+        supportedMethods: "basic-card",
         total: {
           label: "Discounted Total",
           amount: {
             currency: "USD",
             value: "90.00"
           }
         },
         additionalDisplayItems: [
--- a/dom/payments/test/test_showPayment.html
+++ b/dom/payments/test/test_showPayment.html
@@ -17,17 +17,17 @@ https://bugzilla.mozilla.org/show_bug.cg
   var gScript = SpecialPowers.loadChromeScript(gUrl);
 
   function testFailHandler(message) {
     ok(false, message);
   }
   gScript.addMessageListener("test-fail", testFailHandler);
 
   const defaultMethods = [{
-    supportedMethods: ["basic-card"],
+    supportedMethods: "basic-card",
     data: { 
       supportedNetworks: ['unionpay', 'visa', 'mastercard', 'amex', 'discover',
                           'diners', 'jcb', 'mir',
       ],
       supportedTypes: ['prepaid', 'debit', 'credit'],
     },
   }];
   const defaultDetails = {
--- a/dom/webidl/PaymentRequest.webidl
+++ b/dom/webidl/PaymentRequest.webidl
@@ -3,17 +3,17 @@
  * 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
  */
 
 dictionary PaymentMethodData {
-  required sequence<DOMString> supportedMethods;
+  required DOMString           supportedMethods;
            object              data;
 };
 
 dictionary PaymentCurrencyAmount {
   required DOMString currency;
   required DOMString value;
            DOMString currencySystem = "urn:iso:std:iso:4217";
 };
@@ -27,17 +27,17 @@ dictionary PaymentItem {
 dictionary PaymentShippingOption {
   required DOMString             id;
   required DOMString             label;
   required PaymentCurrencyAmount amount;
            boolean               selected = false;
 };
 
 dictionary PaymentDetailsModifier {
-  required sequence<DOMString>   supportedMethods;
+  required DOMString             supportedMethods;
            PaymentItem           total;
            sequence<PaymentItem> additionalDisplayItems;
            object                data;
 };
 
 dictionary PaymentDetailsBase {
   sequence<PaymentItem>            displayItems;
   sequence<PaymentShippingOption>  shippingOptions;