Bug 1345361 - PaymentRequest constructor implementation. r=baku
authorEden Chuang <echuang@mozilla.com>
Fri, 26 May 2017 01:50:32 +0800
changeset 411312 d2370b6a03e89aff5cecb43dada104f887df04bd
parent 411243 edab8a23147dc530ec191b23b880b36df18ffbdd
child 411313 9db4c2096741d7645d9e9a11b363c6ed007e50ab
push id1490
push usermtabara@mozilla.com
push dateMon, 31 Jul 2017 14:08:16 +0000
treeherdermozilla-release@70e32e6bf15e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbaku
bugs1345361
milestone55.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 1345361 - PaymentRequest constructor implementation. r=baku
.eslintignore
browser/installer/package-manifest.in
dom/base/nsGkAtomList.h
dom/bindings/Errors.msg
dom/interfaces/payments/moz.build
dom/interfaces/payments/nsIPaymentActionRequest.idl
dom/interfaces/payments/nsIPaymentRequest.idl
dom/interfaces/payments/nsIPaymentRequestService.idl
dom/ipc/PBrowser.ipdl
dom/ipc/TabChild.cpp
dom/ipc/TabChild.h
dom/ipc/TabParent.cpp
dom/ipc/TabParent.h
dom/moz.build
dom/payments/PaymentActionRequest.cpp
dom/payments/PaymentActionRequest.h
dom/payments/PaymentRequest.cpp
dom/payments/PaymentRequest.h
dom/payments/PaymentRequestData.cpp
dom/payments/PaymentRequestData.h
dom/payments/PaymentRequestManager.cpp
dom/payments/PaymentRequestManager.h
dom/payments/PaymentRequestModule.cpp
dom/payments/PaymentRequestService.cpp
dom/payments/PaymentRequestService.h
dom/payments/PaymentRequestUtils.cpp
dom/payments/PaymentRequestUtils.h
dom/payments/ipc/PPaymentRequest.ipdl
dom/payments/ipc/PaymentRequestChild.cpp
dom/payments/ipc/PaymentRequestChild.h
dom/payments/ipc/PaymentRequestParent.cpp
dom/payments/ipc/PaymentRequestParent.h
dom/payments/ipc/moz.build
dom/payments/moz.build
dom/payments/test/browser.ini
dom/payments/test/browser_multiple_construction.js
dom/payments/test/browser_payment_construction.js
dom/payments/test/browser_payment_in_different_tabs.js
dom/payments/test/head.js
dom/payments/test/multiple_payment_request.html
dom/payments/test/simple_payment_request.html
dom/webidl/PaymentRequest.webidl
dom/webidl/moz.build
mobile/android/installer/package-manifest.in
modules/libpref/init/all.js
--- a/.eslintignore
+++ b/.eslintignore
@@ -212,16 +212,17 @@ dom/jsurl/**
 dom/locales/**
 dom/manifest/**
 dom/mathml/**
 dom/media/**
 dom/messagechannel/**
 dom/network/**
 dom/notification/**
 dom/offline/**
+dom/payments/**
 dom/performance/**
 dom/permission/**
 dom/plugins/**
 dom/power/**
 dom/presentation/**
 dom/promise/**
 dom/push/**
 dom/quota/**
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -208,16 +208,17 @@
 @RESPATH@/components/dom_events.xpt
 @RESPATH@/components/dom_geolocation.xpt
 @RESPATH@/components/dom_media.xpt
 @RESPATH@/components/dom_network.xpt
 @RESPATH@/components/dom_notification.xpt
 @RESPATH@/components/dom_html.xpt
 @RESPATH@/components/dom_offline.xpt
 @RESPATH@/components/dom_json.xpt
+@RESPATH@/components/dom_payments.xpt
 @RESPATH@/components/dom_power.xpt
 @RESPATH@/components/dom_push.xpt
 @RESPATH@/components/dom_quota.xpt
 @RESPATH@/components/dom_range.xpt
 @RESPATH@/components/dom_security.xpt
 @RESPATH@/components/dom_sidebar.xpt
 @RESPATH@/components/dom_storage.xpt
 @RESPATH@/components/dom_stylesheets.xpt
--- a/dom/base/nsGkAtomList.h
+++ b/dom/base/nsGkAtomList.h
@@ -953,16 +953,18 @@ GK_ATOM(onscanningstatechanged, "onscann
 GK_ATOM(onscostatuschanged, "onscostatuschanged")
 GK_ATOM(onscroll, "onscroll")
 GK_ATOM(onselect, "onselect")
 GK_ATOM(onselectionchange, "onselectionchange")
 GK_ATOM(onselectstart, "onselectstart")
 GK_ATOM(onsending, "onsending")
 GK_ATOM(onsent, "onsent")
 GK_ATOM(onset, "onset")
+GK_ATOM(onshippingaddresschange, "onshippingaddresschange")
+GK_ATOM(onshippingoptionchange, "onshippingoptionchange")
 GK_ATOM(onshow, "onshow")
 GK_ATOM(onstatechange, "onstatechange")
 GK_ATOM(onstatuschanged, "onstatuschanged")
 GK_ATOM(onstkcommand, "onstkcommand")
 GK_ATOM(onstksessionend, "onstksessionend")
 GK_ATOM(onstorage, "onstorage")
 GK_ATOM(onstorageareachanged, "onstorageareachanged")
 GK_ATOM(onsubmit, "onsubmit")
--- a/dom/bindings/Errors.msg
+++ b/dom/bindings/Errors.msg
@@ -28,16 +28,17 @@ MSG_DEF(MSG_NOT_OBJECT, 1, JSEXN_TYPEERR
 MSG_DEF(MSG_NOT_CALLABLE, 1, JSEXN_TYPEERR, "{0} is not callable.")
 MSG_DEF(MSG_NOT_CONSTRUCTOR, 1, JSEXN_TYPEERR, "{0} is not a constructor.")
 MSG_DEF(MSG_DOES_NOT_IMPLEMENT_INTERFACE, 2, JSEXN_TYPEERR, "{0} does not implement interface {1}.")
 MSG_DEF(MSG_METHOD_THIS_DOES_NOT_IMPLEMENT_INTERFACE, 2, JSEXN_TYPEERR, "'{0}' called on an object that does not implement interface {1}.")
 MSG_DEF(MSG_METHOD_THIS_UNWRAPPING_DENIED, 1, JSEXN_TYPEERR, "Permission to call '{0}' denied.")
 MSG_DEF(MSG_THIS_DOES_NOT_IMPLEMENT_INTERFACE, 1, JSEXN_TYPEERR, "\"this\" object does not implement interface {0}.")
 MSG_DEF(MSG_NOT_IN_UNION, 2, JSEXN_TYPEERR, "{0} could not be converted to any of: {1}.")
 MSG_DEF(MSG_ILLEGAL_CONSTRUCTOR, 0, JSEXN_TYPEERR, "Illegal constructor.")
+MSG_DEF(MSG_ILLEGAL_PR_CONSTRUCTOR, 1, JSEXN_TYPEERR, "TypeError:{0}")
 MSG_DEF(MSG_CONSTRUCTOR_WITHOUT_NEW, 1, JSEXN_TYPEERR, "Constructor {0} requires 'new'")
 MSG_DEF(MSG_ENFORCE_RANGE_NON_FINITE, 1, JSEXN_TYPEERR, "Non-finite value is out of range for {0}.")
 MSG_DEF(MSG_ENFORCE_RANGE_OUT_OF_RANGE, 1, JSEXN_TYPEERR, "Value is out of range for {0}.")
 MSG_DEF(MSG_NOT_SEQUENCE, 1, JSEXN_TYPEERR, "{0} can't be converted to a sequence.")
 MSG_DEF(MSG_NOT_DICTIONARY, 1, JSEXN_TYPEERR, "{0} can't be converted to a dictionary.")
 MSG_DEF(MSG_OVERLOAD_RESOLUTION_FAILED, 3, JSEXN_TYPEERR, "Argument {0} is not valid for any of the {1}-argument overloads of {2}.")
 MSG_DEF(MSG_GLOBAL_NOT_NATIVE, 0, JSEXN_TYPEERR, "Global is not a native object.")
 MSG_DEF(MSG_ENCODING_NOT_SUPPORTED, 1, JSEXN_RANGEERR, "The given encoding '{0}' is not supported.")
new file mode 100644
--- /dev/null
+++ b/dom/interfaces/payments/moz.build
@@ -0,0 +1,13 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# 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/.
+
+XPIDL_SOURCES += [
+    'nsIPaymentActionRequest.idl',
+    'nsIPaymentRequest.idl',
+    'nsIPaymentRequestService.idl',
+]
+
+XPIDL_MODULE = 'dom_payments'
new file mode 100644
--- /dev/null
+++ b/dom/interfaces/payments/nsIPaymentActionRequest.idl
@@ -0,0 +1,76 @@
+/* -*- Mode: C++; 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/. */
+
+#include "nsISupports.idl"
+#include "nsIVariant.idl"
+#include "nsIPaymentRequest.idl"
+
+interface nsIArray;
+
+[builtinclass, uuid(7ddbe8be-beac-4952-96f6-619981dff7a6)]
+interface nsIPaymentActionRequest : nsISupports
+{
+  const uint32_t CREATE_ACTION = 1;
+  /*
+   *  The payment request identifier.
+   */
+  readonly attribute AString requestId;
+
+  /*
+   *  The type of the requested task.
+   */
+  readonly attribute uint32_t type;
+
+  /*
+   *  Initialize function for this request.
+   */
+  void init(in AString aRequestId,
+            in uint32_t aType);
+};
+
+[builtinclass, uuid(1d38dce6-8bcd-441b-aa94-68e300b6e175)]
+interface nsIPaymentCreateActionRequest : nsIPaymentActionRequest
+{
+  /*
+   *  The tab identifier
+   */
+  readonly attribute uint64_t tabId;
+
+  /*
+   *  The methodData information of the payment request.
+   */
+  readonly attribute nsIArray methodData;
+
+  /*
+   *  The Details information of the payment request.
+   */
+  readonly attribute nsIPaymentDetails details;
+
+  /*
+   *  The Options information of the payment request.
+   */
+  readonly attribute nsIPaymentOptions options;
+
+  /*
+   *  Initialize function the this request.
+   */
+  void initRequest(in AString aRequestId,
+                   in uint64_t aTabId,
+                   in nsIArray aMethodData,
+                   in nsIPaymentDetails aDetails,
+                   in nsIPaymentOptions aOptions);
+};
+
+%{C++
+#define NS_PAYMENT_ACTION_REQUEST_CID \
+  { 0x7ddbe8be, 0xbeac, 0x4952, { 0x96, 0xf6, 0x61, 0x99, 0x81, 0xdf, 0xf7, 0xa6 } }
+#define NS_PAYMENT_ACTION_REQUEST_CONTRACT_ID \
+  "@mozilla.org/dom/payments/payment-action-request;1"
+
+#define NS_PAYMENT_CREATE_ACTION_REQUEST_CID \
+  { 0x1d38dce6, 0x8bcd, 0x441b, { 0xaa, 0x94, 0x68, 0xe3, 0x00, 0xb6, 0xe1, 0x75 } }
+#define NS_PAYMENT_CREATE_ACTION_REQUEST_CONTRACT_ID \
+  "@mozilla.org/dom/payments/payment-create-action-request;1"
+%}
new file mode 100644
--- /dev/null
+++ b/dom/interfaces/payments/nsIPaymentRequest.idl
@@ -0,0 +1,84 @@
+/* -*- Mode: C++; 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/. */
+
+#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 data;
+};
+
+[scriptable, builtinclass, uuid(d22a6f5f-767b-4fea-bf92-68b0b8003eba)]
+interface nsIPaymentCurrencyAmount : nsISupports
+{
+  readonly attribute AString currency;
+  readonly attribute AString value;
+};
+
+[scriptable, builtinclass, uuid(4f78a59f-b5ff-4fb5-ab48-3b37d0101b02)]
+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 nsIPaymentItem total;
+  readonly attribute nsIArray additionalDisplayItems;
+  readonly attribute AString data;
+};
+
+[scriptable, builtinclass, uuid(68341551-3605-4381-b936-41e830aa88fb)]
+interface nsIPaymentShippingOption : nsISupports
+{
+  readonly attribute AString id;
+  readonly attribute AString label;
+  readonly attribute nsIPaymentCurrencyAmount amount;
+  attribute boolean selected;
+};
+
+[scriptable, builtinclass, uuid(73a5a3f1-45b9-4605-a6e6-7aa60daa9039)]
+interface nsIPaymentDetails : nsISupports
+{
+  readonly attribute AString id;
+  readonly attribute nsIPaymentItem totalItem;
+  readonly attribute nsIArray displayItems;
+  readonly attribute nsIArray shippingOptions;
+  readonly attribute nsIArray modifiers;
+  readonly attribute AString error;
+
+  void update(in nsIPaymentDetails aDetails);
+};
+
+[scriptable, builtinclass, uuid(d53f9f20-138e-47cc-9fd5-db16a3f6d301)]
+interface nsIPaymentOptions : nsISupports
+{
+  readonly attribute boolean requestPayerName;
+  readonly attribute boolean requestPayerEmail;
+  readonly attribute boolean requestPayerPhone;
+  readonly attribute boolean requestShipping;
+  readonly attribute AString shippingType;
+};
+
+[scriptable, builtinclass, uuid(2fa36783-d684-4487-b7a8-9def6ae3128f)]
+interface nsIPaymentRequest : nsISupports
+{
+  readonly attribute uint64_t tabId;
+  readonly attribute AString requestId;
+  readonly attribute nsIArray paymentMethods;
+  readonly attribute nsIPaymentDetails paymentDetails;
+  readonly attribute nsIPaymentOptions paymentOptions;
+
+  void updatePaymentDetails(in nsIPaymentDetails aDetails);
+};
new file mode 100644
--- /dev/null
+++ b/dom/interfaces/payments/nsIPaymentRequestService.idl
@@ -0,0 +1,40 @@
+/* -*- Mode: C++; 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/. */
+
+#include "nsISupports.idl"
+#include "nsIVariant.idl"
+#include "nsIPaymentRequest.idl"
+#include "nsIPaymentActionRequest.idl"
+#include "nsISimpleEnumerator.idl"
+
+/*
+ *  nsPaymentRequestService is used to manage the created PaymentRequest in the
+ *  chrome process. It is also the IPC agent for payment UI to communicate with
+ *  merchant side.
+ */
+[scriptable, builtinclass, uuid(cccd665f-edf3-41fc-ab9b-fc55b37340aa)]
+interface nsIPaymentRequestService : nsISupports
+{
+  nsIPaymentRequest getPaymentRequestById(in AString requestId);
+  nsISimpleEnumerator enumerate();
+
+  /*
+   *  This method is only for testing.
+   */
+  void cleanup();
+
+  /*
+   *  requestPayment is used to handle the asked action request of the payment
+   *  from content process.
+   */
+  void requestPayment(in nsIPaymentActionRequest aRequest);
+};
+
+%{C++
+#define NS_PAYMENT_REQUEST_SERVICE_CID \
+  { 0xcccd665f, 0xedf3, 0x41fc, { 0xab, 0x9b, 0xfc, 0x55, 0xb3, 0x73, 0x40, 0xaa } }
+#define NS_PAYMENT_REQUEST_SERVICE_CONTRACT_ID \
+  "@mozilla.org/dom/payments/payment-request-service;1"
+%}
--- a/dom/ipc/PBrowser.ipdl
+++ b/dom/ipc/PBrowser.ipdl
@@ -14,16 +14,17 @@ include protocol PFilePicker;
 include protocol PIndexedDBPermissionRequest;
 include protocol PRenderFrame;
 include protocol PPluginWidget;
 include protocol PRemotePrintJob;
 include protocol PChildToParentStream;
 include protocol PParentToChildStream;
 include protocol PFileDescriptorSet;
 include protocol PIPCBlobInputStream;
+include protocol PPaymentRequest;
 
 include DOMTypes;
 include IPCBlob;
 include IPCStream;
 include JavaScriptTypes;
 include URIParams;
 include PPrintingTypes;
 include PTabContext;
@@ -110,16 +111,17 @@ nested(upto inside_cpow) sync protocol P
 
     manages PColorPicker;
     manages PDocAccessible;
     manages PDocumentRenderer;
     manages PFilePicker;
     manages PIndexedDBPermissionRequest;
     manages PRenderFrame;
     manages PPluginWidget;
+    manages PPaymentRequest;
 
 both:
     async AsyncMessage(nsString aMessage, CpowEntry[] aCpows,
                        Principal aPrincipal, ClonedMessageData aData);
 
     /**
      * Create a layout frame (encapsulating a remote layer tree) for
      * the page that is currently loaded in the <browser>.
@@ -140,16 +142,18 @@ parent:
 
     /*
      * Creates a new remoted nsIWidget connection for windowed plugins
      * in e10s mode. This is always initiated from the child in response
      * to windowed plugin creation.
      */
     sync PPluginWidget();
 
+    async PPaymentRequest();
+
     /**
      * Return native data of root widget
      */
     nested(inside_cpow) sync GetWidgetNativeData() returns (WindowsHandle value);
 
     /**
      * Sends an NS_NATIVE_CHILD_OF_SHAREABLE_WINDOW to be adopted by the
      * widget's shareable window on the chrome side. Only used on Windows.
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -15,16 +15,17 @@
 #include "Layers.h"
 #include "ContentChild.h"
 #include "TabParent.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/BrowserElementParent.h"
 #include "mozilla/ClearOnShutdown.h"
 #include "mozilla/EventListenerManager.h"
 #include "mozilla/dom/indexedDB/PIndexedDBPermissionRequestChild.h"
+#include "mozilla/dom/PaymentRequestChild.h"
 #include "mozilla/dom/TelemetryScrollProbe.h"
 #include "mozilla/IMEStateManager.h"
 #include "mozilla/ipc/DocumentRendererChild.h"
 #include "mozilla/ipc/URIUtils.h"
 #include "mozilla/layers/APZChild.h"
 #include "mozilla/layers/APZCCallbackHelper.h"
 #include "mozilla/layers/APZCTreeManager.h"
 #include "mozilla/layers/APZCTreeManagerChild.h"
@@ -3203,16 +3204,29 @@ TabChild::CreatePluginWidget(nsIWidget* 
   if (NS_FAILED(rv)) {
     NS_WARNING("Creating native plugin widget on the chrome side failed.");
   }
   pluginWidget.forget(aOut);
   return rv;
 }
 #endif // XP_WIN
 
+PPaymentRequestChild*
+TabChild::AllocPPaymentRequestChild()
+{
+  MOZ_CRASH("We should never be manually allocating PPaymentRequestChild actors");
+  return nullptr;
+}
+
+bool
+TabChild::DeallocPPaymentRequestChild(PPaymentRequestChild* actor)
+{
+  return true;
+}
+
 ScreenIntSize
 TabChild::GetInnerSize()
 {
   LayoutDeviceIntSize innerSize =
     RoundedToInt(mUnscaledInnerSize * mPuppetWidget->GetDefaultScale());
   return ViewAs<ScreenPixel>(innerSize, PixelCastJustification::LayoutDeviceIsScreenForTabDims);
 };
 
--- a/dom/ipc/TabChild.h
+++ b/dom/ipc/TabChild.h
@@ -615,16 +615,22 @@ public:
   PPluginWidgetChild* AllocPPluginWidgetChild() override;
 
   bool DeallocPPluginWidgetChild(PPluginWidgetChild* aActor) override;
 
 #ifdef XP_WIN
   nsresult CreatePluginWidget(nsIWidget* aParent, nsIWidget** aOut);
 #endif
 
+  virtual PPaymentRequestChild*
+  AllocPPaymentRequestChild() override;
+
+  virtual bool
+  DeallocPPaymentRequestChild(PPaymentRequestChild* aActor) override;
+
   LayoutDeviceIntPoint GetClientOffset() const { return mClientOffset; }
   LayoutDeviceIntPoint GetChromeDisplacement() const { return mChromeDisp; };
 
   bool IPCOpen() const { return mIPCOpen; }
 
   bool ParentIsActive() const
   {
     return mParentIsActive;
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -14,16 +14,17 @@
 #endif
 #include "mozilla/BrowserElementParent.h"
 #include "mozilla/dom/ContentBridgeParent.h"
 #include "mozilla/dom/ContentParent.h"
 #include "mozilla/dom/DataTransfer.h"
 #include "mozilla/dom/Event.h"
 #include "mozilla/dom/indexedDB/ActorsParent.h"
 #include "mozilla/dom/IPCBlobUtils.h"
+#include "mozilla/dom/PaymentRequestParent.h"
 #include "mozilla/EventStateManager.h"
 #include "mozilla/gfx/2D.h"
 #include "mozilla/gfx/DataSurfaceHelpers.h"
 #include "mozilla/gfx/GPUProcessManager.h"
 #include "mozilla/Hal.h"
 #include "mozilla/IMEStateManager.h"
 #include "mozilla/ipc/DocumentRendererParent.h"
 #include "mozilla/jsipc/CrossProcessObjectWrappers.h"
@@ -2854,16 +2855,31 @@ TabParent::AllocPPluginWidgetParent()
 
 bool
 TabParent::DeallocPPluginWidgetParent(mozilla::plugins::PPluginWidgetParent* aActor)
 {
   delete aActor;
   return true;
 }
 
+PPaymentRequestParent*
+TabParent::AllocPPaymentRequestParent()
+{
+  RefPtr<PaymentRequestParent> actor = new PaymentRequestParent(GetTabId());
+  return actor.forget().take();
+}
+
+bool
+TabParent::DeallocPPaymentRequestParent(PPaymentRequestParent* aActor)
+{
+  RefPtr<PaymentRequestParent> actor =
+    dont_AddRef(static_cast<PaymentRequestParent*>(aActor));
+  return true;
+}
+
 nsresult
 TabParent::HandleEvent(nsIDOMEvent* aEvent)
 {
   nsAutoString eventType;
   aEvent->GetType(eventType);
 
   if (eventType.EqualsLiteral("MozUpdateWindowPos") && !mIsDestroyed) {
     // This event is sent when the widget moved.  Therefore we only update
--- a/dom/ipc/TabParent.h
+++ b/dom/ipc/TabParent.h
@@ -548,16 +548,22 @@ public:
   /**
    * Native widget remoting protocol for use with windowed plugins with e10s.
    */
   virtual PPluginWidgetParent* AllocPPluginWidgetParent() override;
 
   virtual bool
   DeallocPPluginWidgetParent(PPluginWidgetParent* aActor) override;
 
+  virtual PPaymentRequestParent*
+  AllocPPaymentRequestParent() override;
+
+  virtual bool
+  DeallocPPaymentRequestParent(PPaymentRequestParent* aActor) override;
+
   void SetInitedByParent() { mInitedByParent = true; }
 
   bool IsInitedByParent() const { return mInitedByParent; }
 
   bool SendLoadRemoteScript(const nsString& aURL,
                             const bool& aRunInGlobalScope);
 
   void LayerTreeUpdate(uint64_t aEpoch, bool aActive);
--- a/dom/moz.build
+++ b/dom/moz.build
@@ -31,16 +31,17 @@ interfaces = [
     'storage',
     'json',
     'offline',
     'geolocation',
     'notification',
     'svg',
     'smil',
     'push',
+    'payments',
 ]
 
 DIRS += ['interfaces/' + i for i in interfaces]
 
 DIRS += [
     'animation',
     'base',
     'bindings',
@@ -100,16 +101,17 @@ DIRS += [
     'vr',
     'u2f',
     'console',
     'performance',
     'webbrowserpersist',
     'xhr',
     'worklet',
     'script',
+    'payments',
 ]
 
 if CONFIG['OS_ARCH'] == 'WINNT':
     DIRS += ['plugins/ipc/hangui']
 
 if CONFIG['MOZ_SECUREELEMENT']:
     DIRS += ['secureelement']
 
new file mode 100644
--- /dev/null
+++ b/dom/payments/PaymentActionRequest.cpp
@@ -0,0 +1,110 @@
+/* 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 "nsArrayUtils.h"
+#include "nsIMutableArray.h"
+#include "PaymentActionRequest.h"
+#include "PaymentRequestData.h"
+
+using namespace mozilla::dom::payments;
+
+namespace mozilla {
+namespace dom {
+
+/* PaymentActionRequest */
+
+NS_IMPL_ISUPPORTS(PaymentActionRequest,
+                  nsIPaymentActionRequest)
+
+NS_IMETHODIMP
+PaymentActionRequest::Init(const nsAString& aRequestId,
+                           const uint32_t aType)
+{
+  mRequestId = aRequestId;
+  mType = aType;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentActionRequest::GetRequestId(nsAString& aRequestId)
+{
+  aRequestId = mRequestId;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentActionRequest::GetType(uint32_t* aType)
+{
+  *aType = mType;
+  return NS_OK;
+}
+
+/* PaymentCreateActionRequest */
+
+NS_IMPL_ISUPPORTS_INHERITED(PaymentCreateActionRequest,
+                            PaymentActionRequest,
+                            nsIPaymentCreateActionRequest)
+
+NS_IMETHODIMP
+PaymentCreateActionRequest::InitRequest(const nsAString& aRequestId,
+                                        const uint64_t aTabId,
+                                        nsIArray* aMethodData,
+                                        nsIPaymentDetails* aDetails,
+                                        nsIPaymentOptions* aOptions)
+{
+  NS_ENSURE_ARG_POINTER(aMethodData);
+  NS_ENSURE_ARG_POINTER(aDetails);
+  NS_ENSURE_ARG_POINTER(aOptions);
+  Init(aRequestId, nsIPaymentActionRequest::CREATE_ACTION);
+  mTabId = aTabId;
+  mMethodData = aMethodData;
+  mDetails = aDetails;
+  mOptions = aOptions;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentCreateActionRequest::GetTabId(uint64_t* aTabId)
+{
+  NS_ENSURE_ARG_POINTER(aTabId);
+  *aTabId = mTabId;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentCreateActionRequest::GetMethodData(nsIArray** aMethodData)
+{
+  NS_ENSURE_ARG_POINTER(aMethodData);
+  *aMethodData = nullptr;
+  MOZ_ASSERT(mMethodData);
+  nsCOMPtr<nsIArray> methodData = mMethodData;
+  methodData.forget(aMethodData);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentCreateActionRequest::GetDetails(nsIPaymentDetails** aDetails)
+{
+  NS_ENSURE_ARG_POINTER(aDetails);
+  *aDetails = nullptr;
+  MOZ_ASSERT(mDetails);
+  nsCOMPtr<nsIPaymentDetails> details = mDetails;
+  details.forget(aDetails);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentCreateActionRequest::GetOptions(nsIPaymentOptions** aOptions)
+{
+  NS_ENSURE_ARG_POINTER(aOptions);
+  *aOptions = nullptr;
+  MOZ_ASSERT(mOptions);
+  nsCOMPtr<nsIPaymentOptions> options = mOptions;
+  options.forget(aOptions);
+  return NS_OK;
+}
+
+} // end of namespace dom
+} // end of namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/payments/PaymentActionRequest.h
@@ -0,0 +1,56 @@
+/* -*- 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_PaymentActionRequest_h
+#define mozilla_dom_PaymentActionRequest_h
+
+#include "nsIPaymentActionRequest.h"
+#include "nsCOMPtr.h"
+#include "nsCOMArray.h"
+#include "nsIArray.h"
+#include "nsString.h"
+
+namespace mozilla {
+namespace dom {
+
+class PaymentActionRequest : public nsIPaymentActionRequest
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIPAYMENTACTIONREQUEST
+
+  PaymentActionRequest() = default;
+
+protected:
+  virtual ~PaymentActionRequest() = default;
+
+  nsString mRequestId;
+  uint32_t mType;
+};
+
+class PaymentCreateActionRequest final : public nsIPaymentCreateActionRequest
+                                       , public PaymentActionRequest
+{
+public:
+  NS_DECL_ISUPPORTS_INHERITED
+  NS_FORWARD_NSIPAYMENTACTIONREQUEST(PaymentActionRequest::)
+  NS_DECL_NSIPAYMENTCREATEACTIONREQUEST
+
+  PaymentCreateActionRequest() = default;
+
+private:
+  ~PaymentCreateActionRequest() = default;
+
+  uint64_t mTabId;
+  nsCOMPtr<nsIArray> mMethodData;
+  nsCOMPtr<nsIPaymentDetails> mDetails;
+  nsCOMPtr<nsIPaymentOptions> mOptions;
+};
+
+} // end of namespace dom
+} // end of namespace mozilla
+
+#endif
new file mode 100644
--- /dev/null
+++ b/dom/payments/PaymentRequest.cpp
@@ -0,0 +1,281 @@
+/* -*- 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/. */
+
+#include "mozilla/dom/PaymentRequest.h"
+#include "nsContentUtils.h"
+#include "PaymentRequestManager.h"
+
+namespace mozilla {
+namespace dom {
+
+NS_IMPL_CYCLE_COLLECTION_CLASS(PaymentRequest)
+
+NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(PaymentRequest,
+                                               DOMEventTargetHelper)
+  // Don't need NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER because
+  // DOMEventTargetHelper does it for us.
+NS_IMPL_CYCLE_COLLECTION_TRACE_END
+
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(PaymentRequest,
+                                                  DOMEventTargetHelper)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(PaymentRequest,
+                                                DOMEventTargetHelper)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(PaymentRequest)
+NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
+
+NS_IMPL_ADDREF_INHERITED(PaymentRequest, DOMEventTargetHelper)
+NS_IMPL_RELEASE_INHERITED(PaymentRequest, DOMEventTargetHelper)
+
+bool
+PaymentRequest::PrefEnabled(JSContext* aCx, JSObject* aObj)
+{
+  return Preferences::GetBool("dom.payments.request.enabled");
+}
+
+bool
+PaymentRequest::IsValidNumber(const nsAString& aItem,
+                              const nsAString& aStr,
+                              nsAString& aErrorMsg)
+{
+  nsAutoString aValue(aStr);
+  nsresult error = NS_OK;
+  aValue.ToFloat(&error);
+  if (NS_FAILED(error)) {
+    aErrorMsg.AssignLiteral("The amount.value of \"");
+    aErrorMsg.Append(aItem);
+    aErrorMsg.AppendLiteral("\"(");
+    aErrorMsg.Append(aValue);
+    aErrorMsg.AppendLiteral(") must be a valid decimal monetary value.");
+    return false;
+  }
+  return true;
+}
+
+bool
+PaymentRequest::IsPositiveNumber(const nsAString& aItem,
+                                 const nsAString& aStr,
+                                 nsAString& aErrorMsg)
+{
+  nsAutoString aValue(aStr);
+  nsresult error = NS_OK;
+  float value = aValue.ToFloat(&error);
+  if (NS_FAILED(error) || value < 0) {
+    aErrorMsg.AssignLiteral("The amount.value of \"");
+    aErrorMsg.Append(aItem);
+    aErrorMsg.AppendLiteral("\"(");
+    aErrorMsg.Append(aValue);
+    aErrorMsg.AppendLiteral(") must be a valid and positive decimal monetary value.");
+    return false;
+  }
+  return true;
+}
+
+bool
+PaymentRequest::IsValidDetailsInit(const PaymentDetailsInit& aDetails, nsAString& aErrorMsg)
+{
+  // Check the amount.value of detail.total
+  if (!IsPositiveNumber(NS_LITERAL_STRING("details.total"),
+                        aDetails.mTotal.mAmount.mValue, aErrorMsg)) {
+    return false;
+  }
+
+  return IsValidDetailsBase(aDetails, aErrorMsg);
+}
+
+bool
+PaymentRequest::IsValidDetailsBase(const PaymentDetailsBase& aDetails, nsAString& aErrorMsg)
+{
+  // Check the amount.value of each item in the display items
+  if (aDetails.mDisplayItems.WasPassed()) {
+    const Sequence<PaymentItem>& displayItems = aDetails.mDisplayItems.Value();
+    for (const PaymentItem& displayItem : displayItems) {
+      if (!IsValidNumber(displayItem.mLabel,
+                         displayItem.mAmount.mValue, aErrorMsg)) {
+        return false;
+      }
+    }
+  }
+
+  // Check the shipping option
+  if (aDetails.mShippingOptions.WasPassed()) {
+    const Sequence<PaymentShippingOption>& shippingOptions = aDetails.mShippingOptions.Value();
+    for (const PaymentShippingOption& shippingOption : shippingOptions) {
+      if (!IsValidNumber(NS_LITERAL_STRING("details.shippingOptions"),
+                         shippingOption.mAmount.mValue, aErrorMsg)) {
+        return false;
+      }
+    }
+  }
+
+  // Check payment details modifiers
+  if (aDetails.mModifiers.WasPassed()) {
+    const Sequence<PaymentDetailsModifier>& modifiers = aDetails.mModifiers.Value();
+    for (const PaymentDetailsModifier& modifier : modifiers) {
+      if (!IsPositiveNumber(NS_LITERAL_STRING("details.modifiers.total"),
+                            modifier.mTotal.mAmount.mValue, aErrorMsg)) {
+        return false;
+      }
+      if (modifier.mAdditionalDisplayItems.WasPassed()) {
+        const Sequence<PaymentItem>& displayItems = modifier.mAdditionalDisplayItems.Value();
+        for (const PaymentItem& displayItem : displayItems) {
+          if (!IsValidNumber(displayItem.mLabel,
+                             displayItem.mAmount.mValue, aErrorMsg)) {
+            return false;
+          }
+        }
+      }
+    }
+  }
+
+  return true;
+}
+
+already_AddRefed<PaymentRequest>
+PaymentRequest::Constructor(const GlobalObject& aGlobal,
+                            const Sequence<PaymentMethodData>& aMethodData,
+                            const PaymentDetailsInit& aDetails,
+                            const PaymentOptions& aOptions,
+                            ErrorResult& aRv)
+{
+  nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(aGlobal.GetAsSupports());
+  if (!window) {
+    aRv.Throw(NS_ERROR_UNEXPECTED);
+    return nullptr;
+  }
+
+  // [TODO] Bug 1318988 - Implement `allowPaymentRequest` on iframe
+
+  // Check payment methods is done by webidl
+
+  // Check payment details
+  nsAutoString message;
+  if (!IsValidDetailsInit(aDetails, message)) {
+    aRv.ThrowTypeError<MSG_ILLEGAL_PR_CONSTRUCTOR>(message);
+    return nullptr;
+  }
+
+  RefPtr<PaymentRequestManager> manager = PaymentRequestManager::GetSingleton();
+  if (NS_WARN_IF(!manager)) {
+    return nullptr;
+  }
+
+  // Create PaymentRequest and set its |mId|
+  RefPtr<PaymentRequest> request;
+  nsresult rv = manager->CreatePayment(window, aMethodData, aDetails,
+                                       aOptions, getter_AddRefs(request));
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return nullptr;
+  }
+
+  return request.forget();
+}
+
+already_AddRefed<PaymentRequest>
+PaymentRequest::CreatePaymentRequest(nsPIDOMWindowInner* aWindow, nsresult& aRv)
+{
+  // Generate a unique id for identification
+  nsID uuid;
+  aRv = nsContentUtils::GenerateUUIDInPlace(uuid);
+  if (NS_WARN_IF(NS_FAILED(aRv))) {
+    return nullptr;
+  }
+  char buffer[NSID_LENGTH];
+  uuid.ToProvidedString(buffer);
+  nsAutoString id;
+  CopyASCIItoUTF16(buffer, id);
+
+  RefPtr<PaymentRequest> request = new PaymentRequest(aWindow, id);
+  return request.forget();
+}
+
+PaymentRequest::PaymentRequest(nsPIDOMWindowInner* aWindow, const nsAString& aInternalId)
+  : DOMEventTargetHelper(aWindow)
+  , mInternalId(aInternalId)
+  , mUpdating(false)
+  , mState(eCreated)
+{
+  MOZ_ASSERT(aWindow);
+}
+
+already_AddRefed<Promise>
+PaymentRequest::Show(ErrorResult& aRv)
+{
+  aRv.Throw(NS_ERROR_FAILURE);
+  return nullptr;
+}
+
+already_AddRefed<Promise>
+PaymentRequest::CanMakePayment(ErrorResult& aRv)
+{
+  aRv.Throw(NS_ERROR_FAILURE);
+  return nullptr;
+}
+
+already_AddRefed<Promise>
+PaymentRequest::Abort(ErrorResult& aRv)
+{
+  aRv.Throw(NS_ERROR_FAILURE);
+  return nullptr;
+}
+
+void
+PaymentRequest::GetId(nsAString& aRetVal) const
+{
+  aRetVal = mId;
+}
+
+void
+PaymentRequest::GetInternalId(nsAString& aRetVal)
+{
+  aRetVal = mInternalId;
+}
+
+void
+PaymentRequest::SetId(const nsAString& aId)
+{
+  mId = aId;
+}
+
+bool
+PaymentRequest::Equals(const nsAString& aInternalId) const
+{
+  return mInternalId.Equals(aInternalId);
+}
+
+void
+PaymentRequest::SetUpdating(bool aUpdating)
+{
+  mUpdating = aUpdating;
+}
+
+void
+PaymentRequest::GetShippingOption(nsAString& aRetVal) const
+{
+  aRetVal = mShippingOption;
+}
+
+Nullable<PaymentShippingType>
+PaymentRequest::GetShippingType() const
+{
+  return nullptr;
+}
+
+PaymentRequest::~PaymentRequest()
+{
+}
+
+JSObject*
+PaymentRequest::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
+{
+  return PaymentRequestBinding::Wrap(aCx, this, aGivenProto);
+}
+
+} // namespace dom
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/payments/PaymentRequest.h
@@ -0,0 +1,110 @@
+/* -*- 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_PaymentRequest_h
+#define mozilla_dom_PaymentRequest_h
+
+#include "mozilla/DOMEventTargetHelper.h"
+#include "mozilla/dom/PaymentRequestBinding.h"
+#include "mozilla/dom/Promise.h"
+#include "mozilla/ErrorResult.h"
+#include "nsWrapperCache.h"
+
+namespace mozilla {
+namespace dom {
+
+class EventHandlerNonNull;
+class PaymentResponse;
+
+class PaymentRequest final : public DOMEventTargetHelper
+{
+public:
+  NS_DECL_ISUPPORTS_INHERITED
+
+  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(PaymentRequest, DOMEventTargetHelper)
+
+  virtual JSObject* WrapObject(JSContext* aCx,
+                               JS::Handle<JSObject*> aGivenProto) override;
+
+  static already_AddRefed<PaymentRequest>
+  CreatePaymentRequest(nsPIDOMWindowInner* aWindow, nsresult& aRv);
+
+  static bool PrefEnabled(JSContext* aCx, JSObject* aObj);
+
+  static bool
+  IsValidNumber(const nsAString& aItem,
+                const nsAString& aStr,
+                nsAString& aErrorMsg);
+  static bool
+  IsPositiveNumber(const nsAString& aItem,
+                   const nsAString& aStr,
+                   nsAString& aErrorMsg);
+
+  static bool
+  IsValidDetailsInit(const PaymentDetailsInit& aDetails,
+                     nsAString& aErrorMsg);
+  static bool
+  IsValidDetailsBase(const PaymentDetailsBase& aDetails,
+                     nsAString& aErrorMsg);
+
+  static already_AddRefed<PaymentRequest>
+  Constructor(const GlobalObject& aGlobal,
+              const Sequence<PaymentMethodData>& aMethodData,
+              const PaymentDetailsInit& aDetails,
+              const PaymentOptions& aOptions,
+              ErrorResult& aRv);
+
+  already_AddRefed<Promise> Show(ErrorResult& aRv);
+  already_AddRefed<Promise> Abort(ErrorResult& aRv);
+  already_AddRefed<Promise> CanMakePayment(ErrorResult& aRv);
+
+  void GetId(nsAString& aRetVal) const;
+  void GetInternalId(nsAString& aRetVal);
+  void SetId(const nsAString& aId);
+
+  bool Equals(const nsAString& aInternalId) const;
+
+  void SetUpdating(bool aUpdating);
+
+  void GetShippingOption(nsAString& aRetVal) const;
+
+  Nullable<PaymentShippingType> GetShippingType() const;
+
+  IMPL_EVENT_HANDLER(shippingaddresschange);
+  IMPL_EVENT_HANDLER(shippingoptionchange);
+
+protected:
+  ~PaymentRequest();
+
+  PaymentRequest(nsPIDOMWindowInner* aWindow, const nsAString& aInternalId);
+
+  // Id for internal identification
+  nsString mInternalId;
+  // Id for communicating with merchant side
+  // mId is initialized to details.id if it exists
+  // otherwise, mId has the same value as mInternalId.
+  nsString mId;
+  // It is populated when the user chooses a shipping option.
+  nsString mShippingOption;
+
+  // "true" when there is a pending updateWith() call to update the payment request
+  // and "false" otherwise.
+  bool mUpdating;
+  // The error is set in AbortUpdate(). The value is NS_OK by default.
+  //nsresult mUpdateError;
+
+  enum {
+    eUnknown,
+    eCreated,
+    eInteractive,
+    eClosed
+  } mState;
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#endif // mozilla_dom_PaymentRequest_h
new file mode 100644
--- /dev/null
+++ b/dom/payments/PaymentRequestData.cpp
@@ -0,0 +1,660 @@
+/* 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 "nsArrayUtils.h"
+#include "nsIMutableArray.h"
+#include "nsISupportsPrimitives.h"
+#include "PaymentRequestData.h"
+#include "PaymentRequestUtils.h"
+
+namespace mozilla {
+namespace dom {
+namespace payments {
+
+/* PaymentMethodData */
+
+NS_IMPL_ISUPPORTS(PaymentMethodData,
+                  nsIPaymentMethodData)
+
+PaymentMethodData::PaymentMethodData(nsIArray* 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());
+  methodData.forget(aMethodData);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentMethodData::GetSupportedMethods(nsIArray** aSupportedMethods)
+{
+  NS_ENSURE_ARG_POINTER(aSupportedMethods);
+  MOZ_ASSERT(mSupportedMethods);
+  nsCOMPtr<nsIArray> supportedMethods = mSupportedMethods;
+  supportedMethods.forget(aSupportedMethods);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentMethodData::GetData(nsAString& aData)
+{
+  aData = mData;
+  return NS_OK;
+}
+
+/* PaymentCurrencyAmount */
+
+NS_IMPL_ISUPPORTS(PaymentCurrencyAmount,
+                  nsIPaymentCurrencyAmount)
+
+PaymentCurrencyAmount::PaymentCurrencyAmount(const nsAString& aCurrency,
+                                             const nsAString& aValue)
+  : mCurrency(aCurrency)
+  , mValue(aValue)
+{
+}
+
+nsresult
+PaymentCurrencyAmount::Create(const IPCPaymentCurrencyAmount& aIPCAmount,
+                              nsIPaymentCurrencyAmount** aAmount)
+{
+  NS_ENSURE_ARG_POINTER(aAmount);
+  nsCOMPtr<nsIPaymentCurrencyAmount> amount =
+    new PaymentCurrencyAmount(aIPCAmount.currency(), aIPCAmount.value());
+  amount.forget(aAmount);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentCurrencyAmount::GetCurrency(nsAString& aCurrency)
+{
+  aCurrency = mCurrency;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentCurrencyAmount::GetValue(nsAString& aValue)
+{
+  aValue = mValue;
+  return NS_OK;
+}
+
+/* PaymentItem */
+
+NS_IMPL_ISUPPORTS(PaymentItem,
+                  nsIPaymentItem)
+
+PaymentItem::PaymentItem(const nsAString& aLabel,
+                         nsIPaymentCurrencyAmount* aAmount,
+                         const bool aPending)
+  : mLabel(aLabel)
+  , mAmount(aAmount)
+  , mPending(aPending)
+{
+}
+
+nsresult
+PaymentItem::Create(const IPCPaymentItem& aIPCItem, nsIPaymentItem** aItem)
+{
+  NS_ENSURE_ARG_POINTER(aItem);
+  nsCOMPtr<nsIPaymentCurrencyAmount> amount;
+  nsresult rv = PaymentCurrencyAmount::Create(aIPCItem.amount(),
+                                              getter_AddRefs(amount));
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+  nsCOMPtr<nsIPaymentItem> item =
+    new PaymentItem(aIPCItem.label(), amount, aIPCItem.pending());
+  item.forget(aItem);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentItem::GetLabel(nsAString& aLabel)
+{
+  aLabel = mLabel;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentItem::GetAmount(nsIPaymentCurrencyAmount** aAmount)
+{
+  NS_ENSURE_ARG_POINTER(aAmount);
+  MOZ_ASSERT(mAmount);
+  nsCOMPtr<nsIPaymentCurrencyAmount> amount = mAmount;
+  amount.forget(aAmount);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentItem::GetPending(bool* aPending)
+{
+  NS_ENSURE_ARG_POINTER(aPending);
+  *aPending = mPending;
+  return NS_OK;
+}
+
+/* PaymentDetailsModifier */
+
+NS_IMPL_ISUPPORTS(PaymentDetailsModifier,
+                  nsIPaymentDetailsModifier)
+
+PaymentDetailsModifier::PaymentDetailsModifier(nsIArray* aSupportedMethods,
+                                               nsIPaymentItem* aTotal,
+                                               nsIArray* aAdditionalDisplayItems,
+                                               const nsAString& aData)
+  : mSupportedMethods(aSupportedMethods)
+  , mTotal(aTotal)
+  , mAdditionalDisplayItems(aAdditionalDisplayItems)
+  , mData(aData)
+{
+}
+
+nsresult
+PaymentDetailsModifier::Create(const IPCPaymentDetailsModifier& aIPCModifier,
+                               nsIPaymentDetailsModifier** aModifier)
+{
+  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))) {
+        return rv;
+      }
+      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());
+  modifier.forget(aModifier);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentDetailsModifier::GetSupportedMethods(nsIArray** aSupportedMethods)
+{
+  NS_ENSURE_ARG_POINTER(aSupportedMethods);
+  MOZ_ASSERT(mSupportedMethods);
+  nsCOMPtr<nsIArray> supportedMethods = mSupportedMethods;
+  supportedMethods.forget(aSupportedMethods);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentDetailsModifier::GetTotal(nsIPaymentItem** aTotal)
+{
+  NS_ENSURE_ARG_POINTER(aTotal);
+  MOZ_ASSERT(mTotal);
+  nsCOMPtr<nsIPaymentItem> total = mTotal;
+  total.forget(aTotal);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentDetailsModifier::GetAdditionalDisplayItems(nsIArray** aAdditionalDisplayItems)
+{
+  NS_ENSURE_ARG_POINTER(aAdditionalDisplayItems);
+  nsCOMPtr<nsIArray> additionalItems = mAdditionalDisplayItems;
+  additionalItems.forget(aAdditionalDisplayItems);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentDetailsModifier::GetData(nsAString& aData)
+{
+  aData = mData;
+  return NS_OK;
+}
+
+/* PaymentShippingOption */
+
+NS_IMPL_ISUPPORTS(PaymentShippingOption,
+                  nsIPaymentShippingOption)
+
+PaymentShippingOption::PaymentShippingOption(const nsAString& aId,
+                                             const nsAString& aLabel,
+                                             nsIPaymentCurrencyAmount* aAmount,
+                                             const bool aSelected)
+  : mId(aId)
+  , mLabel(aLabel)
+  , mAmount(aAmount)
+  , mSelected(aSelected)
+{
+}
+
+nsresult
+PaymentShippingOption::Create(const IPCPaymentShippingOption& aIPCOption,
+                              nsIPaymentShippingOption** aOption)
+{
+  NS_ENSURE_ARG_POINTER(aOption);
+  nsCOMPtr<nsIPaymentCurrencyAmount> amount;
+  nsresult rv = PaymentCurrencyAmount::Create(aIPCOption.amount(), getter_AddRefs(amount));
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+  nsCOMPtr<nsIPaymentShippingOption> option =
+    new PaymentShippingOption(aIPCOption.id(), aIPCOption.label(), amount, aIPCOption.selected());
+  option.forget(aOption);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentShippingOption::GetId(nsAString& aId)
+{
+  aId = mId;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentShippingOption::GetLabel(nsAString& aLabel)
+{
+  aLabel = mLabel;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentShippingOption::GetAmount(nsIPaymentCurrencyAmount** aAmount)
+{
+  NS_ENSURE_ARG_POINTER(aAmount);
+  MOZ_ASSERT(mAmount);
+  nsCOMPtr<nsIPaymentCurrencyAmount> amount = mAmount;
+  amount.forget(aAmount);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentShippingOption::GetSelected(bool* aSelected)
+{
+  NS_ENSURE_ARG_POINTER(aSelected);
+  *aSelected = mSelected;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentShippingOption::SetSelected(bool aSelected)
+{
+  mSelected = aSelected;
+  return NS_OK;
+}
+
+/* PaymentDetails */
+
+NS_IMPL_ISUPPORTS(PaymentDetails,
+                  nsIPaymentDetails)
+
+PaymentDetails::PaymentDetails(const nsAString& aId,
+                               nsIPaymentItem* aTotalItem,
+                               nsIArray* aDisplayItems,
+                               nsIArray* aShippingOptions,
+                               nsIArray* aModifiers,
+                               const nsAString& aError)
+  : mId(aId)
+  , mTotalItem(aTotalItem)
+  , mDisplayItems(aDisplayItems)
+  , mShippingOptions(aShippingOptions)
+  , mModifiers(aModifiers)
+  , mError(aError)
+{
+}
+
+nsresult
+PaymentDetails::Create(const IPCPaymentDetails& aIPCDetails,
+                       nsIPaymentDetails** aDetails)
+{
+  NS_ENSURE_ARG_POINTER(aDetails);
+
+  nsCOMPtr<nsIPaymentItem> total;
+  nsresult rv = PaymentItem::Create(aIPCDetails.total(), getter_AddRefs(total));
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  nsCOMPtr<nsIArray> displayItems;
+  if (aIPCDetails.displayItemsPassed()) {
+    nsCOMPtr<nsIMutableArray> items = do_CreateInstance(NS_ARRAY_CONTRACTID);
+    MOZ_ASSERT(items);
+    for (const IPCPaymentItem& displayItem : aIPCDetails.displayItems()) {
+      nsCOMPtr<nsIPaymentItem> item;
+      rv = PaymentItem::Create(displayItem, getter_AddRefs(item));
+      if (NS_WARN_IF(NS_FAILED(rv))) {
+        return rv;
+      }
+      rv = items->AppendElement(item, false);
+      if (NS_WARN_IF(NS_FAILED(rv))) {
+        return rv;
+      }
+    }
+    displayItems = items.forget();
+  }
+
+  nsCOMPtr<nsIArray> shippingOptions;
+  if (aIPCDetails.shippingOptionsPassed()) {
+    nsCOMPtr<nsIMutableArray> options = do_CreateInstance(NS_ARRAY_CONTRACTID);
+    MOZ_ASSERT(options);
+    for (const IPCPaymentShippingOption& shippingOption : aIPCDetails.shippingOptions()) {
+      nsCOMPtr<nsIPaymentShippingOption> option;
+      rv = PaymentShippingOption::Create(shippingOption, getter_AddRefs(option));
+      if (NS_WARN_IF(NS_FAILED(rv))) {
+        return rv;
+      }
+      rv = options->AppendElement(option, false);
+      if (NS_WARN_IF(NS_FAILED(rv))) {
+        return rv;
+      }
+    }
+    shippingOptions = options.forget();
+  }
+
+  nsCOMPtr<nsIArray> modifiers;
+  if (aIPCDetails.modifiersPassed()) {
+    nsCOMPtr<nsIMutableArray> detailsModifiers = do_CreateInstance(NS_ARRAY_CONTRACTID);
+    MOZ_ASSERT(detailsModifiers);
+    for (const IPCPaymentDetailsModifier& modifier : aIPCDetails.modifiers()) {
+      nsCOMPtr<nsIPaymentDetailsModifier> detailsModifier;
+      rv = PaymentDetailsModifier::Create(modifier, getter_AddRefs(detailsModifier));
+      if (NS_WARN_IF(NS_FAILED(rv))) {
+        return rv;
+      }
+      rv = detailsModifiers->AppendElement(detailsModifier, false);
+      if (NS_WARN_IF(NS_FAILED(rv))) {
+        return rv;
+      }
+    }
+    modifiers = detailsModifiers.forget();
+  }
+
+  nsCOMPtr<nsIPaymentDetails> details =
+    new PaymentDetails(aIPCDetails.id(), total, displayItems, shippingOptions,
+                       modifiers, aIPCDetails.error());
+
+  details.forget(aDetails);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentDetails::GetId(nsAString& aId)
+{
+  aId = mId;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentDetails::GetTotalItem(nsIPaymentItem** aTotalItem)
+{
+  NS_ENSURE_ARG_POINTER(aTotalItem);
+  MOZ_ASSERT(mTotalItem);
+  nsCOMPtr<nsIPaymentItem> total = mTotalItem;
+  total.forget(aTotalItem);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentDetails::GetDisplayItems(nsIArray** aDisplayItems)
+{
+  NS_ENSURE_ARG_POINTER(aDisplayItems);
+  nsCOMPtr<nsIArray> displayItems = mDisplayItems;
+  displayItems.forget(aDisplayItems);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentDetails::GetShippingOptions(nsIArray** aShippingOptions)
+{
+  NS_ENSURE_ARG_POINTER(aShippingOptions);
+  nsCOMPtr<nsIArray> options = mShippingOptions;
+  options.forget(aShippingOptions);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentDetails::GetModifiers(nsIArray** aModifiers)
+{
+  NS_ENSURE_ARG_POINTER(aModifiers);
+  nsCOMPtr<nsIArray> modifiers = mModifiers;
+  modifiers.forget(aModifiers);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentDetails::GetError(nsAString& aError)
+{
+  aError = mError;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentDetails::Update(nsIPaymentDetails* aDetails)
+{
+  MOZ_ASSERT(aDetails);
+  /*
+   * According to the spec [1], update the attributes if they present in new
+   * details (i.e., PaymentDetailsUpdate); otherwise, keep original value.
+   * Note |id| comes only from initial details (i.e., PaymentDetailsInit) and
+   * |error| only from new details.
+   *
+   *   [1] https://www.w3.org/TR/payment-request/#updatewith-method
+   */
+
+  nsresult rv = aDetails->GetTotalItem(getter_AddRefs(mTotalItem));
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  nsCOMPtr<nsIArray> displayItems;
+  rv = aDetails->GetDisplayItems(getter_AddRefs(displayItems));
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+  if (displayItems) {
+    mDisplayItems = displayItems;
+  }
+
+  nsCOMPtr<nsIArray> shippingOptions;
+  rv = aDetails->GetShippingOptions(getter_AddRefs(shippingOptions));
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+  if (shippingOptions) {
+    mShippingOptions = shippingOptions;
+  }
+
+  nsCOMPtr<nsIArray> modifiers;
+  rv = aDetails->GetModifiers(getter_AddRefs(modifiers));
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+  if (modifiers) {
+    mModifiers = modifiers;
+  }
+
+  rv = aDetails->GetError(mError);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+  return NS_OK;
+
+}
+/* PaymentOptions */
+
+NS_IMPL_ISUPPORTS(PaymentOptions,
+                  nsIPaymentOptions)
+
+PaymentOptions::PaymentOptions(const bool aRequestPayerName,
+                               const bool aRequestPayerEmail,
+                               const bool aRequestPayerPhone,
+                               const bool aRequestShipping,
+                               const nsAString& aShippingType)
+  : mRequestPayerName(aRequestPayerName)
+  , mRequestPayerEmail(aRequestPayerEmail)
+  , mRequestPayerPhone(aRequestPayerPhone)
+  , mRequestShipping(aRequestShipping)
+  , mShippingType(aShippingType)
+{
+}
+
+nsresult
+PaymentOptions::Create(const IPCPaymentOptions& aIPCOptions,
+                       nsIPaymentOptions** aOptions)
+{
+  NS_ENSURE_ARG_POINTER(aOptions);
+
+  nsCOMPtr<nsIPaymentOptions> options =
+    new PaymentOptions(aIPCOptions.requestPayerName(),
+                       aIPCOptions.requestPayerEmail(),
+                       aIPCOptions.requestPayerPhone(),
+                       aIPCOptions.requestShipping(),
+                       aIPCOptions.shippingType());
+  options.forget(aOptions);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentOptions::GetRequestPayerName(bool* aRequestPayerName)
+{
+  NS_ENSURE_ARG_POINTER(aRequestPayerName);
+  *aRequestPayerName = mRequestPayerName;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentOptions::GetRequestPayerEmail(bool* aRequestPayerEmail)
+{
+  NS_ENSURE_ARG_POINTER(aRequestPayerEmail);
+  *aRequestPayerEmail = mRequestPayerEmail;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentOptions::GetRequestPayerPhone(bool* aRequestPayerPhone)
+{
+  NS_ENSURE_ARG_POINTER(aRequestPayerPhone);
+  *aRequestPayerPhone = mRequestPayerPhone;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentOptions::GetRequestShipping(bool* aRequestShipping)
+{
+  NS_ENSURE_ARG_POINTER(aRequestShipping);
+  *aRequestShipping = mRequestShipping;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentOptions::GetShippingType(nsAString& aShippingType)
+{
+  aShippingType = mShippingType;
+  return NS_OK;
+}
+
+/* PaymentReqeust */
+
+NS_IMPL_ISUPPORTS(PaymentRequest,
+                  nsIPaymentRequest)
+
+PaymentRequest::PaymentRequest(const uint64_t aTabId,
+                               const nsAString& aRequestId,
+                               nsIArray* aPaymentMethods,
+                               nsIPaymentDetails* aPaymentDetails,
+                               nsIPaymentOptions* aPaymentOptions)
+  : mTabId(aTabId)
+  , mRequestId(aRequestId)
+  , mPaymentMethods(aPaymentMethods)
+  , mPaymentDetails(aPaymentDetails)
+  , mPaymentOptions(aPaymentOptions)
+{
+}
+
+NS_IMETHODIMP
+PaymentRequest::GetTabId(uint64_t* aTabId)
+{
+  NS_ENSURE_ARG_POINTER(aTabId);
+  *aTabId = mTabId;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentRequest::GetRequestId(nsAString& aRequestId)
+{
+  aRequestId = mRequestId;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentRequest::GetPaymentMethods(nsIArray** aPaymentMethods)
+{
+  NS_ENSURE_ARG_POINTER(aPaymentMethods);
+  MOZ_ASSERT(mPaymentMethods);
+  nsCOMPtr<nsIArray> methods = mPaymentMethods;
+  methods.forget(aPaymentMethods);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentRequest::GetPaymentDetails(nsIPaymentDetails** aPaymentDetails)
+{
+  NS_ENSURE_ARG_POINTER(aPaymentDetails);
+  MOZ_ASSERT(mPaymentDetails);
+  nsCOMPtr<nsIPaymentDetails> details = mPaymentDetails;
+  details.forget(aPaymentDetails);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentRequest::GetPaymentOptions(nsIPaymentOptions** aPaymentOptions)
+{
+  NS_ENSURE_ARG_POINTER(aPaymentOptions);
+  MOZ_ASSERT(mPaymentOptions);
+  nsCOMPtr<nsIPaymentOptions> options = mPaymentOptions;
+  options.forget(aPaymentOptions);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentRequest::UpdatePaymentDetails(nsIPaymentDetails* aPaymentDetails)
+{
+  MOZ_ASSERT(aPaymentDetails);
+  return mPaymentDetails->Update(aPaymentDetails);
+}
+
+} // end of namespace payment
+} // end of namespace dom
+} // end of namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/payments/PaymentRequestData.h
@@ -0,0 +1,199 @@
+/* -*- 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_PaymentRequestData_h
+#define mozilla_dom_PaymentRequestData_h
+
+#include "nsIPaymentRequest.h"
+#include "nsCOMPtr.h"
+#include "mozilla/dom/PPaymentRequest.h"
+
+namespace mozilla {
+namespace dom {
+namespace payments {
+
+class PaymentMethodData final : public nsIPaymentMethodData
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIPAYMENTMETHODDATA
+
+  static nsresult Create(const IPCPaymentMethodData& aIPCMethodData,
+                         nsIPaymentMethodData** aMethodData);
+
+private:
+  PaymentMethodData(nsIArray* aSupportedMethods,
+                    const nsAString& aData);
+
+  ~PaymentMethodData() = default;
+
+  nsCOMPtr<nsIArray> mSupportedMethods;
+  nsString mData;
+};
+
+class PaymentCurrencyAmount final : public nsIPaymentCurrencyAmount
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIPAYMENTCURRENCYAMOUNT
+
+  static nsresult Create(const IPCPaymentCurrencyAmount& aIPCAmount,
+                         nsIPaymentCurrencyAmount** aAmount);
+
+private:
+  PaymentCurrencyAmount(const nsAString& aCurrency,
+                        const nsAString& aValue);
+
+  ~PaymentCurrencyAmount() = default;
+
+  nsString mCurrency;
+  nsString mValue;
+};
+
+class PaymentItem final : public nsIPaymentItem
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIPAYMENTITEM
+
+  static nsresult Create(const IPCPaymentItem& aIPCItem, nsIPaymentItem** aItem);
+
+private:
+  PaymentItem(const nsAString& aLabel,
+              nsIPaymentCurrencyAmount* aAmount,
+              const bool aPending);
+
+  ~PaymentItem() = default;
+
+  nsString mLabel;
+  nsCOMPtr<nsIPaymentCurrencyAmount> mAmount;
+  bool mPending;
+};
+
+class PaymentDetailsModifier final : public nsIPaymentDetailsModifier
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIPAYMENTDETAILSMODIFIER
+
+  static nsresult Create(const IPCPaymentDetailsModifier& aIPCModifier,
+                         nsIPaymentDetailsModifier** aModifier);
+
+private:
+  PaymentDetailsModifier(nsIArray* aSupportedMethods,
+                         nsIPaymentItem* aTotal,
+                         nsIArray* aAdditionalDisplayItems,
+                         const nsAString& aData);
+
+  ~PaymentDetailsModifier() = default;
+
+  nsCOMPtr<nsIArray> mSupportedMethods;
+  nsCOMPtr<nsIPaymentItem> mTotal;
+  nsCOMPtr<nsIArray> mAdditionalDisplayItems;
+  nsString mData;
+};
+
+class PaymentShippingOption final : public nsIPaymentShippingOption
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIPAYMENTSHIPPINGOPTION
+
+  static nsresult Create(const IPCPaymentShippingOption& aIPCOption,
+                         nsIPaymentShippingOption** aOption);
+
+private:
+  PaymentShippingOption(const nsAString& aId,
+                        const nsAString& aLabel,
+                        nsIPaymentCurrencyAmount* aAmount,
+                        const bool aSelected=false);
+
+  ~PaymentShippingOption() = default;
+
+  nsString mId;
+  nsString mLabel;
+  nsCOMPtr<nsIPaymentCurrencyAmount> mAmount;
+  bool mSelected;
+};
+
+class PaymentDetails final : public nsIPaymentDetails
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIPAYMENTDETAILS
+
+
+  static nsresult Create(const IPCPaymentDetails& aIPCDetails,
+                         nsIPaymentDetails** aDetails);
+private:
+  PaymentDetails(const nsAString& aId,
+                 nsIPaymentItem* aTotalItem,
+                 nsIArray* aDisplayItems,
+                 nsIArray* aShippingOptions,
+                 nsIArray* aModifiers,
+                 const nsAString& aError);
+
+  ~PaymentDetails() = default;
+
+  nsString mId;
+  nsCOMPtr<nsIPaymentItem> mTotalItem;
+  nsCOMPtr<nsIArray> mDisplayItems;
+  nsCOMPtr<nsIArray> mShippingOptions;
+  nsCOMPtr<nsIArray> mModifiers;
+  nsString mError;
+};
+
+class PaymentOptions final : public nsIPaymentOptions
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIPAYMENTOPTIONS
+
+  static nsresult Create(const IPCPaymentOptions& aIPCOptions,
+                         nsIPaymentOptions** aOptions);
+
+private:
+  PaymentOptions(const bool aRequestPayerName,
+                 const bool aRequestPayerEmail,
+                 const bool aRequestPayerPhone,
+                 const bool aRequestShipping,
+                 const nsAString& aShippintType);
+  ~PaymentOptions() = default;
+
+  bool mRequestPayerName;
+  bool mRequestPayerEmail;
+  bool mRequestPayerPhone;
+  bool mRequestShipping;
+  nsString mShippingType;
+};
+
+class PaymentRequest final : public nsIPaymentRequest
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIPAYMENTREQUEST
+
+  PaymentRequest(const uint64_t aTabId,
+                 const nsAString& aRequestId,
+                 nsIArray* aPaymentMethods,
+                 nsIPaymentDetails* aPaymentDetails,
+                 nsIPaymentOptions* aPaymentOptions);
+
+private:
+  ~PaymentRequest() = default;
+
+  uint64_t mTabId;
+  nsString mRequestId;
+  nsCOMPtr<nsIArray> mPaymentMethods;
+  nsCOMPtr<nsIPaymentDetails> mPaymentDetails;
+  nsCOMPtr<nsIPaymentOptions> mPaymentOptions;
+};
+
+} // end of namespace payment
+} // end of namespace dom
+} // end of namespace mozilla
+
+#endif
new file mode 100644
--- /dev/null
+++ b/dom/payments/PaymentRequestManager.cpp
@@ -0,0 +1,394 @@
+/* -*- 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/. */
+
+#include "PaymentRequestManager.h"
+#include "mozilla/ClearOnShutdown.h"
+#include "mozilla/dom/ContentChild.h"
+#include "mozilla/dom/TabChild.h"
+#include "mozilla/dom/PaymentRequestChild.h"
+#include "nsContentUtils.h"
+#include "nsIJSON.h"
+#include "nsString.h"
+
+namespace mozilla {
+namespace dom {
+namespace {
+
+/*
+ *  Following Convert* functions are used for convert PaymentRequest structs
+ *  to transferable structs for IPC.
+ */
+nsresult
+SerializeFromJSObject(JSContext* aCx, JS::HandleObject aObject, nsAString& aSerializedObject){
+  nsCOMPtr<nsIJSON> serializer = do_CreateInstance("@mozilla.org/dom/json;1");
+  if (NS_WARN_IF(!serializer)) {
+    return NS_ERROR_FAILURE;
+  }
+  JS::RootedValue value(aCx, JS::ObjectValue(*aObject));
+  //JS::Value value = JS::ObjectValue(*aObject);
+  return serializer->EncodeFromJSVal(value.address(), aCx, aSerializedObject);
+}
+
+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);
+  return NS_OK;
+}
+
+void
+ConvertCurrencyAmount(const PaymentCurrencyAmount& aAmount,
+                      IPCPaymentCurrencyAmount& aIPCCurrencyAmount)
+{
+  aIPCCurrencyAmount = IPCPaymentCurrencyAmount(aAmount.mCurrency, aAmount.mValue);
+}
+
+void
+ConvertItem(const PaymentItem& aItem, IPCPaymentItem& aIPCItem)
+{
+  IPCPaymentCurrencyAmount amount;
+  ConvertCurrencyAmount(aItem.mAmount, amount);
+  aIPCItem = IPCPaymentItem(aItem.mLabel, amount, aItem.mPending);
+}
+
+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))) {
+      return rv;
+    }
+  }
+
+  IPCPaymentItem total;
+  ConvertItem(aModifier.mTotal, total);
+
+  nsTArray<IPCPaymentItem> additionalDisplayItems;
+  if (aModifier.mAdditionalDisplayItems.WasPassed()) {
+    for (const PaymentItem& item : aModifier.mAdditionalDisplayItems.Value()) {
+      IPCPaymentItem displayItem;
+      ConvertItem(item, displayItem);
+      additionalDisplayItems.AppendElement(displayItem);
+    }
+  }
+  aIPCModifier = IPCPaymentDetailsModifier(supportedMethods,
+                                          total,
+                                          additionalDisplayItems,
+                                          serializedData,
+                                          aModifier.mAdditionalDisplayItems.WasPassed());
+  return NS_OK;
+}
+
+void
+ConvertShippingOption(const PaymentShippingOption& aOption,
+                      IPCPaymentShippingOption& aIPCOption)
+{
+  IPCPaymentCurrencyAmount amount;
+  ConvertCurrencyAmount(aOption.mAmount, amount);
+  aIPCOption = IPCPaymentShippingOption(aOption.mId, aOption.mLabel, amount, aOption.mSelected);
+}
+
+nsresult
+ConvertDetailsBase(const PaymentDetailsBase& aDetails,
+                   nsTArray<IPCPaymentItem>& aDisplayItems,
+                   nsTArray<IPCPaymentShippingOption>& aShippingOptions,
+                   nsTArray<IPCPaymentDetailsModifier>& aModifiers)
+{
+  if (aDetails.mDisplayItems.WasPassed()) {
+    for (const PaymentItem& item : aDetails.mDisplayItems.Value()) {
+      IPCPaymentItem displayItem;
+      ConvertItem(item, displayItem);
+      aDisplayItems.AppendElement(displayItem);
+    }
+  }
+  if (aDetails.mShippingOptions.WasPassed()) {
+    for (const PaymentShippingOption& option : aDetails.mShippingOptions.Value()) {
+      IPCPaymentShippingOption shippingOption;
+      ConvertShippingOption(option, shippingOption);
+      aShippingOptions.AppendElement(shippingOption);
+    }
+  }
+  if (aDetails.mModifiers.WasPassed()) {
+    for (const PaymentDetailsModifier& modifier : aDetails.mModifiers.Value()) {
+      IPCPaymentDetailsModifier detailsModifier;
+      nsresult rv = ConvertModifier(modifier, detailsModifier);
+      if (NS_WARN_IF(NS_FAILED(rv))) {
+        return rv;
+      }
+      aModifiers.AppendElement(detailsModifier);
+    }
+  }
+  return NS_OK;
+}
+
+nsresult
+ConvertDetailsInit(const PaymentDetailsInit& aDetails,
+                   IPCPaymentDetails& aIPCDetails)
+{
+  // Convert PaymentDetailsBase members
+  nsTArray<IPCPaymentItem> displayItems;
+  nsTArray<IPCPaymentShippingOption> shippingOptions;
+  nsTArray<IPCPaymentDetailsModifier> modifiers;
+  nsresult rv = ConvertDetailsBase(aDetails, displayItems, shippingOptions, modifiers);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  // Convert |id|
+  nsString id(EmptyString());
+  if (aDetails.mId.WasPassed()) {
+    id = aDetails.mId.Value();
+  }
+
+  // Convert required |total|
+  IPCPaymentItem total;
+  ConvertItem(aDetails.mTotal, total);
+
+  aIPCDetails = IPCPaymentDetails(id,
+                                  total,
+                                  displayItems,
+                                  shippingOptions,
+                                  modifiers,
+                                  EmptyString(), // error message
+                                  aDetails.mDisplayItems.WasPassed(),
+                                  aDetails.mShippingOptions.WasPassed(),
+                                  aDetails.mModifiers.WasPassed());
+  return NS_OK;
+}
+
+void
+ConvertOptions(const PaymentOptions& aOptions,
+               IPCPaymentOptions& aIPCOption)
+{
+  uint8_t shippingTypeIndex = static_cast<uint8_t>(aOptions.mShippingType);
+  nsString shippingType(NS_LITERAL_STRING("shipping"));
+  if (shippingTypeIndex < ArrayLength(PaymentShippingTypeValues::strings)) {
+    shippingType.AssignASCII(
+      PaymentShippingTypeValues::strings[shippingTypeIndex].value);
+  }
+  aIPCOption = IPCPaymentOptions(aOptions.mRequestPayerName,
+                                 aOptions.mRequestPayerEmail,
+                                 aOptions.mRequestPayerPhone,
+                                 aOptions.mRequestShipping,
+                                 shippingType);
+}
+} // end of namespace
+
+/* PaymentRequestManager */
+
+StaticRefPtr<PaymentRequestManager> gPaymentManager;
+
+nsresult
+PaymentRequestManager::GetPaymentChild(PaymentRequest* aRequest,
+                                       PaymentRequestChild** aChild)
+{
+  NS_ENSURE_ARG_POINTER(aRequest);
+  NS_ENSURE_ARG_POINTER(aChild);
+  *aChild = nullptr;
+
+  RefPtr<PaymentRequestChild> paymentChild;
+  if (mPaymentChildHash.Get(aRequest, getter_AddRefs(paymentChild))) {
+    paymentChild.forget(aChild);
+    return NS_OK;
+  }
+
+  nsPIDOMWindowInner* win = aRequest->GetOwner();
+  NS_ENSURE_TRUE(win, NS_ERROR_FAILURE);
+  TabChild* tabChild = TabChild::GetFrom(win->GetDocShell());
+  NS_ENSURE_TRUE(tabChild, NS_ERROR_FAILURE);
+  nsAutoString requestId;
+  aRequest->GetInternalId(requestId);
+
+  // Only one payment request can interact with user at the same time.
+  // Before we create a new PaymentRequestChild, make sure there is no other
+  // payment request are interacting on the same tab.
+  for (auto iter = mPaymentChildHash.ConstIter(); !iter.Done(); iter.Next()) {
+    RefPtr<PaymentRequest> request = iter.Key();
+    if (request->Equals(requestId)) {
+      continue;
+    }
+    nsPIDOMWindowInner* requestOwner = request->GetOwner();
+    NS_ENSURE_TRUE(requestOwner, NS_ERROR_FAILURE);
+    TabChild* tmpChild = TabChild::GetFrom(requestOwner->GetDocShell());
+    NS_ENSURE_TRUE(tmpChild, NS_ERROR_FAILURE);
+    if (tmpChild->GetTabId() == tabChild->GetTabId()) {
+      return NS_ERROR_FAILURE;
+    }
+  }
+
+  paymentChild = new PaymentRequestChild();
+  tabChild->SendPPaymentRequestConstructor(paymentChild);
+  if (!mPaymentChildHash.Put(aRequest, paymentChild, mozilla::fallible) ) {
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
+  paymentChild.forget(aChild);
+  return NS_OK;
+}
+
+nsresult
+PaymentRequestManager::ReleasePaymentChild(PaymentRequestChild* aPaymentChild)
+{
+  NS_ENSURE_ARG_POINTER(aPaymentChild);
+  for (auto iter = mPaymentChildHash.Iter(); !iter.Done(); iter.Next()) {
+    RefPtr<PaymentRequestChild> child = iter.Data();
+    if (NS_WARN_IF(!child)) {
+      return NS_ERROR_FAILURE;
+    }
+    if (child == aPaymentChild) {
+      iter.Remove();
+      return NS_OK;
+    }
+  }
+  return NS_OK;
+}
+
+nsresult
+PaymentRequestManager::ReleasePaymentChild(PaymentRequest* aRequest)
+{
+  NS_ENSURE_ARG_POINTER(aRequest);
+
+  RefPtr<PaymentRequestChild> paymentChild;
+  if(!mPaymentChildHash.Remove(aRequest, getter_AddRefs(paymentChild))) {
+    return NS_ERROR_FAILURE;
+  }
+  if (NS_WARN_IF(!paymentChild)) {
+    return NS_ERROR_FAILURE;
+  }
+  paymentChild->MaybeDelete();
+  return NS_OK;
+}
+
+already_AddRefed<PaymentRequestManager>
+PaymentRequestManager::GetSingleton()
+{
+  if (!gPaymentManager) {
+    gPaymentManager = new PaymentRequestManager();
+    ClearOnShutdown(&gPaymentManager);
+  }
+  RefPtr<PaymentRequestManager> manager = gPaymentManager;
+  return manager.forget();
+}
+
+already_AddRefed<PaymentRequest>
+PaymentRequestManager::GetPaymentRequestById(const nsAString& aRequestId)
+{
+  for (const RefPtr<PaymentRequest>& request : mRequestQueue) {
+    if (request->Equals(aRequestId)) {
+      RefPtr<PaymentRequest> paymentRequest = request;
+      return paymentRequest.forget();
+    }
+  }
+  return nullptr;
+}
+
+nsresult
+PaymentRequestManager::CreatePayment(nsPIDOMWindowInner* aWindow,
+                                     const Sequence<PaymentMethodData>& aMethodData,
+                                     const PaymentDetailsInit& aDetails,
+                                     const PaymentOptions& aOptions,
+                                     PaymentRequest** aRequest)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  NS_ENSURE_ARG_POINTER(aRequest);
+  *aRequest = nullptr;
+
+  nsresult rv;
+  nsTArray<IPCPaymentMethodData> methodData;
+  for (const PaymentMethodData& data : aMethodData) {
+    IPCPaymentMethodData ipcMethodData;
+    rv = ConvertMethodData(data, ipcMethodData);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
+    methodData.AppendElement(ipcMethodData);
+  }
+
+  IPCPaymentDetails details;
+  rv = ConvertDetailsInit(aDetails, details);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  IPCPaymentOptions options;
+  ConvertOptions(aOptions, options);
+
+  RefPtr<PaymentRequest> paymentRequest = PaymentRequest::CreatePaymentRequest(aWindow, rv);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  /*
+   *  Set request's |mId| to details.id if details.id exists.
+   *  Otherwise, set |mId| to internal id.
+   */
+  nsAutoString requestId;
+  if (aDetails.mId.WasPassed() && !aDetails.mId.Value().IsEmpty()) {
+    requestId = aDetails.mId.Value();
+  } else {
+    paymentRequest->GetInternalId(requestId);
+  }
+  paymentRequest->SetId(requestId);
+
+  RefPtr<PaymentRequestChild> requestChild;
+  rv = GetPaymentChild(paymentRequest, getter_AddRefs(requestChild));
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  nsAutoString internalId;
+  paymentRequest->GetInternalId(internalId);
+  IPCPaymentCreateActionRequest request(internalId,
+                                        methodData,
+                                        details,
+                                        options);
+  rv = requestChild->RequestPayment(request);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  rv = ReleasePaymentChild(paymentRequest);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  mRequestQueue.AppendElement(paymentRequest);
+  paymentRequest.forget(aRequest);
+  return NS_OK;
+}
+
+} // end of namespace dom
+} // end of namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/payments/PaymentRequestManager.h
@@ -0,0 +1,65 @@
+/* -*- 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_PaymentRequestManager_h
+#define mozilla_dom_PaymentRequestManager_h
+
+#include "nsISupports.h"
+#include "PaymentRequest.h"
+#include "mozilla/dom/PaymentRequestBinding.h"
+#include "nsCOMPtr.h"
+#include "nsTArray.h"
+
+namespace mozilla {
+namespace dom {
+
+class PaymentRequestChild;
+
+/*
+ *  PaymentRequestManager is a singleton used to manage the created PaymentRequests.
+ *  It is also the communication agent to chrome proces.
+ */
+class PaymentRequestManager final
+{
+public:
+  NS_INLINE_DECL_REFCOUNTING(PaymentRequestManager)
+
+  static already_AddRefed<PaymentRequestManager> GetSingleton();
+
+  already_AddRefed<PaymentRequest>
+  GetPaymentRequestById(const nsAString& aRequestId);
+
+  /*
+   *  This method is used to create PaymentRequest object and send corresponding
+   *  data to chrome process for internal payment creation, such that content
+   *  process can ask specific task by sending requestId only.
+   */
+  nsresult
+  CreatePayment(nsPIDOMWindowInner* aWindow,
+                const Sequence<PaymentMethodData>& aMethodData,
+                const PaymentDetailsInit& aDetails,
+                const PaymentOptions& aOptions,
+                PaymentRequest** aRequest);
+
+  nsresult
+  ReleasePaymentChild(PaymentRequestChild* aPaymentChild);
+protected:
+  PaymentRequestManager() = default;
+  ~PaymentRequestManager() = default;
+
+  nsresult GetPaymentChild(PaymentRequest* aRequest,
+                           PaymentRequestChild** aPaymentChild);
+  nsresult ReleasePaymentChild(PaymentRequest* aRequest);
+
+  // The container for the created PaymentRequests
+  nsTArray<RefPtr<PaymentRequest>> mRequestQueue;
+  nsRefPtrHashtable<nsRefPtrHashKey<PaymentRequest>, PaymentRequestChild> mPaymentChildHash;
+};
+
+} // end of namespace dom
+} // end of namespace mozilla
+
+#endif
new file mode 100644
--- /dev/null
+++ b/dom/payments/PaymentRequestModule.cpp
@@ -0,0 +1,52 @@
+/* -*- 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/. */
+
+#include "mozilla/ModuleUtils.h"
+#include "PaymentActionRequest.h"
+#include "PaymentRequestService.h"
+
+using mozilla::dom::PaymentActionRequest;
+using mozilla::dom::PaymentCreateActionRequest;
+using mozilla::dom::PaymentRequestService;
+
+NS_GENERIC_FACTORY_CONSTRUCTOR(PaymentActionRequest)
+NS_GENERIC_FACTORY_CONSTRUCTOR(PaymentCreateActionRequest)
+NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(PaymentRequestService,
+                                         PaymentRequestService::GetSingleton)
+
+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_REQUEST_SERVICE_CID);
+
+static const mozilla::Module::CIDEntry kPaymentRequestCIDs[] = {
+  { &kNS_PAYMENT_ACTION_REQUEST_CID, false, nullptr, PaymentActionRequestConstructor},
+  { &kNS_PAYMENT_CREATE_ACTION_REQUEST_CID, false, nullptr, PaymentCreateActionRequestConstructor},
+  { &kNS_PAYMENT_REQUEST_SERVICE_CID, true, nullptr, PaymentRequestServiceConstructor },
+  { nullptr }
+};
+
+static const mozilla::Module::ContractIDEntry kPaymentRequestContracts[] = {
+  { 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_REQUEST_SERVICE_CONTRACT_ID, &kNS_PAYMENT_REQUEST_SERVICE_CID },
+  { nullptr }
+};
+
+static const mozilla::Module::CategoryEntry kPaymentRequestCategories[] = {
+  { "payment-request", "PaymentActionRequest", NS_PAYMENT_ACTION_REQUEST_CONTRACT_ID },
+  { "payment-request", "PaymentCreateActionRequest", NS_PAYMENT_CREATE_ACTION_REQUEST_CONTRACT_ID },
+  { "payment-request", "PaymentRequestService", NS_PAYMENT_REQUEST_SERVICE_CONTRACT_ID },
+  { nullptr }
+};
+
+static const mozilla::Module kPaymentRequestModule = {
+  mozilla::Module::kVersion,
+  kPaymentRequestCIDs,
+  kPaymentRequestContracts,
+  kPaymentRequestCategories
+};
+
+NSMODULE_DEFN(PaymentRequestModule) = &kPaymentRequestModule;
new file mode 100644
--- /dev/null
+++ b/dom/payments/PaymentRequestService.cpp
@@ -0,0 +1,201 @@
+/* -*- 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/. */
+
+#include "mozilla/ClearOnShutdown.h"
+#include "PaymentRequestData.h"
+#include "PaymentRequestService.h"
+
+namespace mozilla {
+namespace dom {
+
+StaticRefPtr<PaymentRequestService> gPaymentService;
+
+namespace {
+
+class PaymentRequestEnumerator final : public nsISimpleEnumerator
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSISIMPLEENUMERATOR
+
+  PaymentRequestEnumerator()
+    : mIndex(0)
+  {}
+private:
+  ~PaymentRequestEnumerator() = default;
+  uint32_t mIndex;
+};
+
+NS_IMPL_ISUPPORTS(PaymentRequestEnumerator, nsISimpleEnumerator)
+
+NS_IMETHODIMP
+PaymentRequestEnumerator::HasMoreElements(bool* aReturn)
+{
+  NS_ENSURE_ARG_POINTER(aReturn);
+  *aReturn = false;
+  if (NS_WARN_IF(!gPaymentService)) {
+    return NS_ERROR_FAILURE;
+  }
+  RefPtr<PaymentRequestService> service = gPaymentService;
+  *aReturn = mIndex < service->NumPayments();
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentRequestEnumerator::GetNext(nsISupports** aItem)
+{
+  NS_ENSURE_ARG_POINTER(aItem);
+  if (NS_WARN_IF(!gPaymentService)) {
+    return NS_ERROR_FAILURE;
+  }
+  nsCOMPtr<nsIPaymentRequest> request =
+    gPaymentService->GetPaymentRequestByIndex(mIndex);
+  if (NS_WARN_IF(!request)) {
+    return NS_ERROR_FAILURE;
+  }
+  nsCOMPtr<nsISupports> item = do_QueryInterface(request);
+  if (NS_WARN_IF(!item)) {
+    return NS_ERROR_FAILURE;
+  }
+  mIndex++;
+  item.forget(aItem);
+  return NS_OK;
+}
+
+} // end of anonymous namespace
+
+/* PaymentRequestService */
+
+NS_IMPL_ISUPPORTS(PaymentRequestService,
+                  nsIPaymentRequestService)
+
+already_AddRefed<PaymentRequestService>
+PaymentRequestService::GetSingleton()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  if (!gPaymentService) {
+    gPaymentService = new PaymentRequestService();
+    ClearOnShutdown(&gPaymentService);
+  }
+  RefPtr<PaymentRequestService> service = gPaymentService;
+  return service.forget();
+}
+
+uint32_t
+PaymentRequestService::NumPayments() const
+{
+  return mRequestQueue.Length();
+}
+
+already_AddRefed<nsIPaymentRequest>
+PaymentRequestService::GetPaymentRequestByIndex(const uint32_t aIndex)
+{
+  if (aIndex >= mRequestQueue.Length()) {
+    return nullptr;
+  }
+  nsCOMPtr<nsIPaymentRequest> request = mRequestQueue[aIndex];
+  MOZ_ASSERT(request);
+  return request.forget();
+}
+
+NS_IMETHODIMP
+PaymentRequestService::GetPaymentRequestById(const nsAString& aRequestId,
+                                             nsIPaymentRequest** aRequest)
+{
+  NS_ENSURE_ARG_POINTER(aRequest);
+  *aRequest = nullptr;
+  uint32_t numRequests = mRequestQueue.Length();
+  for (uint32_t index = 0; index < numRequests; ++index) {
+    nsCOMPtr<nsIPaymentRequest> request = mRequestQueue[index];
+    MOZ_ASSERT(request);
+    nsAutoString requestId;
+    nsresult rv = request->GetRequestId(requestId);
+    NS_ENSURE_SUCCESS(rv, rv);
+    if (requestId == aRequestId) {
+      request.forget(aRequest);
+      break;
+    }
+  }
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentRequestService::Enumerate(nsISimpleEnumerator** aEnumerator)
+{
+  NS_ENSURE_ARG_POINTER(aEnumerator);
+  nsCOMPtr<nsISimpleEnumerator> enumerator = new PaymentRequestEnumerator();
+  enumerator.forget(aEnumerator);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentRequestService::Cleanup()
+{
+  mRequestQueue.Clear();
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentRequestService::RequestPayment(nsIPaymentActionRequest* aRequest)
+{
+  NS_ENSURE_ARG_POINTER(aRequest);
+  uint32_t type;
+  nsresult rv = aRequest->GetType(&type);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+  switch (type) {
+    case nsIPaymentActionRequest::CREATE_ACTION: {
+      nsCOMPtr<nsIPaymentCreateActionRequest> request =
+        do_QueryInterface(aRequest);
+      MOZ_ASSERT(request);
+      uint64_t tabId;
+      rv = request->GetTabId(&tabId);
+      if (NS_WARN_IF(NS_FAILED(rv))) {
+        return rv;
+      }
+
+      nsString requestId;
+      rv = request->GetRequestId(requestId);
+      if (NS_WARN_IF(NS_FAILED(rv))) {
+        return rv;
+      }
+
+      nsCOMPtr<nsIArray> methodData;
+      rv = request->GetMethodData(getter_AddRefs(methodData));
+      if (NS_WARN_IF(NS_FAILED(rv) || !methodData)) {
+        return NS_ERROR_FAILURE;
+      }
+
+      nsCOMPtr<nsIPaymentDetails> details;
+      rv = request->GetDetails(getter_AddRefs(details));
+      if (NS_WARN_IF(NS_FAILED(rv) || !details)) {
+        return NS_ERROR_FAILURE;
+      }
+
+      nsCOMPtr<nsIPaymentOptions> options;
+      rv = request->GetOptions(getter_AddRefs(options));
+      if (NS_WARN_IF(NS_FAILED(rv) || !options)) {
+        return NS_ERROR_FAILURE;
+      }
+
+      nsCOMPtr<nsIPaymentRequest> payment =
+         new payments::PaymentRequest(tabId, requestId, methodData, details, options);
+
+      if (!mRequestQueue.AppendElement(payment, mozilla::fallible)) {
+        return NS_ERROR_OUT_OF_MEMORY;
+      }
+      break;
+    }
+    default: {
+      return NS_ERROR_FAILURE;
+    }
+  }
+  return NS_OK;
+}
+
+} // end of namespace dom
+} // end of namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/payments/PaymentRequestService.h
@@ -0,0 +1,45 @@
+/* -*- 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_PaymentRequestService_h
+#define mozilla_dom_PaymentRequestService_h
+
+#include "nsIPaymentRequest.h"
+#include "nsIPaymentRequestService.h"
+#include "nsISimpleEnumerator.h"
+#include "nsCOMPtr.h"
+#include "nsTArray.h"
+
+namespace mozilla {
+namespace dom {
+
+// The implmentation of nsIPaymentRequestService
+
+class PaymentRequestService final : public nsIPaymentRequestService
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIPAYMENTREQUESTSERVICE
+
+  PaymentRequestService() = default;
+
+  static already_AddRefed<PaymentRequestService> GetSingleton();
+
+  already_AddRefed<nsIPaymentRequest>
+  GetPaymentRequestByIndex(const uint32_t index);
+
+  uint32_t NumPayments() const;
+
+private:
+  ~PaymentRequestService() = default;
+
+  FallibleTArray<nsCOMPtr<nsIPaymentRequest>> mRequestQueue;
+};
+
+} // end of namespace dom
+} // end of namespace mozilla
+
+#endif
new file mode 100644
--- /dev/null
+++ b/dom/payments/PaymentRequestUtils.cpp
@@ -0,0 +1,90 @@
+/* -*- 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/. */
+
+#include "nsArrayUtils.h"
+#include "PaymentRequestUtils.h"
+#include "nsIMutableArray.h"
+#include "nsISupportsPrimitives.h"
+
+namespace mozilla {
+namespace dom {
+
+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;
+}
+
+nsresult
+ConvertISupportsStringstoStrings(nsIArray* aIStrings,
+                                 nsTArray<nsString>& aStrings)
+{
+  NS_ENSURE_ARG_POINTER(aIStrings);
+  uint32_t length;
+  aStrings.Clear();
+  nsresult rv = aIStrings->GetLength(&length);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+  for (uint32_t index = 0; index < length; ++index) {
+    nsCOMPtr<nsISupportsString> iString = do_QueryElementAt(aIStrings, index);
+    if (NS_WARN_IF(!iString)) {
+      return NS_ERROR_FAILURE;
+    }
+    nsString string;
+    rv = iString->GetData(string);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
+    aStrings.AppendElement(string);
+  }
+  return NS_OK;
+}
+
+nsresult
+CopyISupportsStrings(nsIArray* aSourceStrings, nsIArray** aTargetStrings)
+{
+  NS_ENSURE_ARG_POINTER(aTargetStrings);
+  *aTargetStrings = nullptr;
+  nsCOMPtr<nsIMutableArray> strings = do_CreateInstance(NS_ARRAY_CONTRACTID);
+  uint32_t length;
+  nsresult rv = aSourceStrings->GetLength(&length);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+  for (uint32_t index = 0; index < length; ++index) {
+    nsCOMPtr<nsISupportsString> string = do_QueryElementAt(aSourceStrings, index);
+    if (NS_WARN_IF(!string)) {
+      return NS_ERROR_FAILURE;
+    }
+    strings->AppendElement(string, false);
+  }
+  strings.forget(aTargetStrings);
+  return NS_OK;
+}
+
+} // end of namespace dom
+} // end of namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/payments/PaymentRequestUtils.h
@@ -0,0 +1,30 @@
+/* -*- 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_PaymentRequestUtils_h
+#define mozilla_dom_PaymentRequestUtils_h
+
+#include "nsIArray.h"
+#include "nsTArray.h"
+
+namespace mozilla {
+namespace dom {
+
+nsresult
+ConvertStringstoISupportsStrings(const nsTArray<nsString>& aStrings,
+                                 nsIArray** aIStrings);
+
+nsresult
+ConvertISupportsStringstoStrings(nsIArray* aIStrings,
+                                 nsTArray<nsString>& aStrings);
+
+nsresult
+CopyISupportsStrings(nsIArray* aSourceStrings, nsIArray** aTargetStrings);
+
+} // end of namespace dom
+} // end of namespace mozilla
+
+#endif
new file mode 100644
--- /dev/null
+++ b/dom/payments/ipc/PPaymentRequest.ipdl
@@ -0,0 +1,94 @@
+/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */
+/* vim: set sw=4 ts=8 et tw=80 ft=cpp : */
+/* 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 protocol PBrowser;
+
+namespace mozilla {
+namespace dom {
+
+struct IPCPaymentMethodData
+{
+  nsString[] supportedMethods;
+  nsString data;
+};
+
+struct IPCPaymentCurrencyAmount
+{
+  nsString currency;
+  nsString value;
+};
+
+struct IPCPaymentItem
+{
+  nsString label;
+  IPCPaymentCurrencyAmount amount;
+  bool pending;
+};
+
+struct IPCPaymentDetailsModifier
+{
+  nsString[] supportedMethods;
+  IPCPaymentItem total;
+  IPCPaymentItem[] additionalDisplayItems;
+  nsString data;
+  bool additionalDisplayItemsPassed;
+};
+
+struct IPCPaymentShippingOption
+{
+  nsString id;
+  nsString label;
+  IPCPaymentCurrencyAmount amount;
+  bool selected;
+};
+
+struct IPCPaymentDetails
+{
+  nsString id;
+  IPCPaymentItem total;
+  IPCPaymentItem[] displayItems;
+  IPCPaymentShippingOption[] shippingOptions;
+  IPCPaymentDetailsModifier[] modifiers;
+  nsString error;
+  bool displayItemsPassed;
+  bool shippingOptionsPassed;
+  bool modifiersPassed;
+};
+
+struct IPCPaymentOptions
+{
+  bool requestPayerName;
+  bool requestPayerEmail;
+  bool requestPayerPhone;
+  bool requestShipping;
+  nsString shippingType;
+};
+
+struct IPCPaymentCreateActionRequest
+{
+  nsString requestId;
+  IPCPaymentMethodData[] methodData;
+  IPCPaymentDetails details;
+  IPCPaymentOptions options;
+};
+
+union IPCPaymentActionRequest
+{
+  IPCPaymentCreateActionRequest;
+};
+
+sync protocol PPaymentRequest
+{
+  manager PBrowser;
+
+parent:
+  async __delete__();
+
+  async RequestPayment(IPCPaymentActionRequest aAction);
+};
+
+} // end of namespace dom
+} // end of namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/payments/ipc/PaymentRequestChild.cpp
@@ -0,0 +1,53 @@
+/* -*- 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/. */
+
+#include "PaymentRequestChild.h"
+#include "mozilla/dom/PaymentRequestManager.h"
+
+namespace mozilla {
+namespace dom {
+
+PaymentRequestChild::PaymentRequestChild()
+  : mActorAlive(true)
+{
+}
+
+nsresult
+PaymentRequestChild::RequestPayment(const IPCPaymentActionRequest& aAction)
+{
+  if (!mActorAlive) {
+    return NS_ERROR_FAILURE;
+  }
+  SendRequestPayment(aAction);
+  return NS_OK;
+}
+
+void
+PaymentRequestChild::ActorDestroy(ActorDestroyReason aWhy)
+{
+  mActorAlive = false;
+  RefPtr<PaymentRequestManager> manager = PaymentRequestManager::GetSingleton();
+  MOZ_ASSERT(manager);
+  manager->ReleasePaymentChild(this);
+}
+
+void
+PaymentRequestChild::MaybeDelete()
+{
+  if (mActorAlive) {
+    mActorAlive = false;
+    Send__delete__(this);
+  }
+}
+
+bool
+PaymentRequestChild::SendRequestPayment(const IPCPaymentActionRequest& aAction)
+{
+  return PPaymentRequestChild::SendRequestPayment(aAction);
+}
+
+} // end of namespace dom
+} // end of namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/payments/ipc/PaymentRequestChild.h
@@ -0,0 +1,37 @@
+/* -*- 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_PaymentRequestChild_h
+#define mozilla_dom_PaymentRequestChild_h
+
+#include "mozilla/dom/PPaymentRequestChild.h"
+
+namespace mozilla {
+namespace dom {
+
+class PaymentRequestChild final : public PPaymentRequestChild
+{
+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(PaymentRequestChild);
+public:
+  PaymentRequestChild();
+
+  void ActorDestroy(ActorDestroyReason aWhy) override;
+
+  void MaybeDelete();
+
+  nsresult RequestPayment(const IPCPaymentActionRequest& aAction);
+private:
+  ~PaymentRequestChild() = default;
+
+  bool SendRequestPayment(const IPCPaymentActionRequest& aAction);
+
+  bool mActorAlive;
+};
+
+} // end of namespace dom
+} // end of namespace mozilla
+
+#endif
new file mode 100644
--- /dev/null
+++ b/dom/payments/ipc/PaymentRequestParent.cpp
@@ -0,0 +1,109 @@
+/* -*- 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/. */
+
+#include "mozilla/ipc/InputStreamUtils.h"
+#include "nsArrayUtils.h"
+#include "nsCOMPtr.h"
+#include "nsIMutableArray.h"
+#include "nsIPaymentActionRequest.h"
+#include "nsIPaymentRequestService.h"
+#include "nsISupportsPrimitives.h"
+#include "nsServiceManagerUtils.h"
+#include "PaymentRequestData.h"
+#include "PaymentRequestParent.h"
+
+namespace mozilla {
+namespace dom {
+
+PaymentRequestParent::PaymentRequestParent(uint64_t aTabId)
+  : mActorAlived(true)
+  , mTabId(aTabId)
+{
+}
+
+mozilla::ipc::IPCResult
+PaymentRequestParent::RecvRequestPayment(const IPCPaymentActionRequest& aRequest)
+{
+  MOZ_ASSERT(mActorAlived);
+  nsCOMPtr<nsIPaymentActionRequest> actionRequest;
+  nsresult rv;
+  switch (aRequest.type()) {
+    case IPCPaymentActionRequest::TIPCPaymentCreateActionRequest: {
+      IPCPaymentCreateActionRequest request = aRequest;
+
+      nsCOMPtr<nsIMutableArray> methodData = do_CreateInstance(NS_ARRAY_CONTRACTID);
+      MOZ_ASSERT(methodData);
+      for (IPCPaymentMethodData data : request.methodData()) {
+        nsCOMPtr<nsIPaymentMethodData> method;
+        rv = payments::PaymentMethodData::Create(data, getter_AddRefs(method));
+        if (NS_WARN_IF(NS_FAILED(rv))) {
+          return IPC_FAIL_NO_REASON(this);
+        }
+        rv = methodData->AppendElement(method, false);
+        if (NS_WARN_IF(NS_FAILED(rv))) {
+          return IPC_FAIL_NO_REASON(this);
+        }
+      }
+
+      nsCOMPtr<nsIPaymentDetails> details;
+      rv = payments::PaymentDetails::Create(request.details(), getter_AddRefs(details));
+      if (NS_WARN_IF(NS_FAILED(rv))) {
+        return IPC_FAIL_NO_REASON(this);
+      }
+
+      nsCOMPtr<nsIPaymentOptions> options;
+      rv = payments::PaymentOptions::Create(request.options(), getter_AddRefs(options));
+      if (NS_WARN_IF(NS_FAILED(rv))) {
+        return IPC_FAIL_NO_REASON(this);
+      }
+
+      nsCOMPtr<nsIPaymentCreateActionRequest> createRequest =
+        do_CreateInstance(NS_PAYMENT_CREATE_ACTION_REQUEST_CONTRACT_ID);
+      if (NS_WARN_IF(!createRequest)) {
+        return IPC_FAIL_NO_REASON(this);
+      }
+      rv = createRequest->InitRequest(request.requestId(),
+                                      mTabId,
+                                      methodData,
+                                      details,
+                                      options);
+      if (NS_WARN_IF(NS_FAILED(rv))) {
+        return IPC_FAIL_NO_REASON(this);
+      }
+
+      actionRequest = do_QueryInterface(createRequest);
+      MOZ_ASSERT(actionRequest);
+      break;
+    }
+    default: {
+      return IPC_FAIL(this, "Unexpected request type");
+    }
+  }
+  nsCOMPtr<nsIPaymentRequestService> service =
+    do_GetService(NS_PAYMENT_REQUEST_SERVICE_CONTRACT_ID);
+  MOZ_ASSERT(service);
+  rv = service->RequestPayment(actionRequest);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return IPC_FAIL_NO_REASON(this);
+  }
+  return IPC_OK();
+}
+
+mozilla::ipc::IPCResult
+PaymentRequestParent::Recv__delete__()
+{
+  mActorAlived = false;
+  return IPC_OK();
+}
+
+void
+PaymentRequestParent::ActorDestroy(ActorDestroyReason aWhy)
+{
+  mActorAlived = false;
+}
+
+} // end of namespace dom
+} // end of namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/payments/ipc/PaymentRequestParent.h
@@ -0,0 +1,40 @@
+/* -*- 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_PaymentRequestParent_h
+#define mozilla_dom_PaymentRequestParent_h
+
+#include "mozilla/dom/PPaymentRequestParent.h"
+#include "nsISupports.h"
+
+namespace mozilla {
+namespace dom {
+
+class PaymentRequestParent final : public PPaymentRequestParent
+{
+public:
+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(PaymentRequestParent)
+
+  explicit PaymentRequestParent(uint64_t aTabId);
+
+protected:
+  mozilla::ipc::IPCResult
+  RecvRequestPayment(const IPCPaymentActionRequest& aRequest) override;
+
+  mozilla::ipc::IPCResult Recv__delete__() override;
+
+  void ActorDestroy(ActorDestroyReason aWhy) override;
+private:
+  ~PaymentRequestParent() = default;
+
+  bool mActorAlived;
+  uint64_t mTabId;
+};
+
+} // end of namespace dom
+} // end of namespace mozilla
+
+#endif
new file mode 100644
--- /dev/null
+++ b/dom/payments/ipc/moz.build
@@ -0,0 +1,23 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# 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/.
+
+EXPORTS.mozilla.dom += [
+    'PaymentRequestChild.h',
+    'PaymentRequestParent.h',
+]
+
+UNIFIED_SOURCES += [
+    'PaymentRequestChild.cpp',
+    'PaymentRequestParent.cpp',
+]
+
+IPDL_SOURCES += [
+    'PPaymentRequest.ipdl',
+]
+
+include('/ipc/chromium/chromium-config.mozbuild')
+
+FINAL_LIBRARY = 'xul'
new file mode 100644
--- /dev/null
+++ b/dom/payments/moz.build
@@ -0,0 +1,35 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# 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/.
+
+DIRS += [
+    'ipc',
+]
+
+EXPORTS += [
+    'PaymentRequestData.h',
+    'PaymentRequestService.h',
+]
+
+EXPORTS.mozilla.dom += [
+    'PaymentRequest.h',
+    'PaymentRequestManager.h',
+]
+
+UNIFIED_SOURCES += [
+    'PaymentActionRequest.cpp',
+    'PaymentRequest.cpp',
+    'PaymentRequestData.cpp',
+    'PaymentRequestManager.cpp',
+    'PaymentRequestModule.cpp',
+    'PaymentRequestService.cpp',
+    'PaymentRequestUtils.cpp',
+]
+
+include('/ipc/chromium/chromium-config.mozbuild')
+
+FINAL_LIBRARY = 'xul'
+
+BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
new file mode 100644
--- /dev/null
+++ b/dom/payments/test/browser.ini
@@ -0,0 +1,11 @@
+[DEFAULT]
+# skip-if !e10s will be removed once non-e10s is supported
+skip-if = !e10s
+support-files =
+  head.js
+  simple_payment_request.html
+  multiple_payment_request.html
+
+[browser_payment_construction.js]
+[browser_multiple_construction.js]
+[browser_payment_in_different_tabs.js]
new file mode 100644
--- /dev/null
+++ b/dom/payments/test/browser_multiple_construction.js
@@ -0,0 +1,32 @@
+"use strict";
+
+// kTestRoot is from head.js
+const kTestPage = kTestRoot + "multiple_payment_request.html";
+
+registerCleanupFunction(cleanup);
+
+add_task(function*() {
+  Services.prefs.setBoolPref("dom.payments.request.enabled", true);
+  yield BrowserTestUtils.withNewTab(kTestPage,
+    function*(browser) {
+
+      const paymentSrv = Cc["@mozilla.org/dom/payments/payment-request-service;1"].getService(Ci.nsIPaymentRequestService);
+      ok(paymentSrv, "Fail to get PaymentRequestService.");
+
+      const paymentEnum = paymentSrv.enumerate();
+      ok(paymentEnum.hasMoreElements(), "PaymentRequestService should have at least one payment request.");
+      while (paymentEnum.hasMoreElements()) {
+        let payment = paymentEnum.getNext().QueryInterface(Ci.nsIPaymentRequest);
+        ok(payment, "Fail to get existing payment request.");
+        if (payment.paymentDetails.id == "complex details") {
+          checkComplexPayment(payment);
+        } else if (payment.paymentDetails.id == "simple details") {
+          checkSimplePayment(payment);
+        } else {
+          ok(false, "Unknown payment.");
+        }
+      }
+      Services.prefs.setBoolPref("dom.payments.request.enabled", false);
+    }
+  );
+});
new file mode 100644
--- /dev/null
+++ b/dom/payments/test/browser_payment_construction.js
@@ -0,0 +1,26 @@
+"use strict";
+
+// kTestRoot is from head.js
+const kTestPage = kTestRoot + "simple_payment_request.html";
+
+registerCleanupFunction(cleanup);
+
+add_task(function*() {
+  Services.prefs.setBoolPref("dom.payments.request.enabled", true);
+  yield BrowserTestUtils.withNewTab(kTestPage,
+    function*(browser) {
+
+      const paymentSrv = Cc["@mozilla.org/dom/payments/payment-request-service;1"].getService(Ci.nsIPaymentRequestService);
+      ok(paymentSrv, "Fail to get PaymentRequestService.");
+
+      const paymentEnum = paymentSrv.enumerate();
+      ok(paymentEnum.hasMoreElements(), "PaymentRequestService should have at least one payment request.");
+      while (paymentEnum.hasMoreElements()) {
+        let payment = paymentEnum.getNext().QueryInterface(Ci.nsIPaymentRequest);
+        ok(payment, "Fail to get existing payment request.");
+        checkSimplePayment(payment);
+      }
+      Services.prefs.setBoolPref("dom.payments.request.enabled", false);
+    }
+  );
+});
new file mode 100644
--- /dev/null
+++ b/dom/payments/test/browser_payment_in_different_tabs.js
@@ -0,0 +1,33 @@
+"use strict";
+
+// kTestRoot is from head.js
+const kTestPage = kTestRoot + "simple_payment_request.html";
+
+registerCleanupFunction(cleanup);
+
+add_task(function*() {
+  Services.prefs.setBoolPref("dom.payments.request.enabled", true);
+  yield BrowserTestUtils.withNewTab(kTestPage,
+    function*(browser) {
+      yield BrowserTestUtils.withNewTab(kTestPage,
+        function*(browser) {
+          const paymentSrv = Cc["@mozilla.org/dom/payments/payment-request-service;1"].getService(Ci.nsIPaymentRequestService);
+          ok(paymentSrv, "Fail to get PaymentRequestService.");
+
+          const paymentEnum = paymentSrv.enumerate();
+          ok(paymentEnum.hasMoreElements(), "PaymentRequestService should have at least one payment request.");
+          let tabIds = [];
+          while (paymentEnum.hasMoreElements()) {
+            let payment = paymentEnum.getNext().QueryInterface(Ci.nsIPaymentRequest);
+            ok(payment, "Fail to get existing payment request.");
+            checkSimplePayment(payment);
+            tabIds.push(payment.tabId);
+          }
+          is(tabIds.length, 2, "TabId array length should be 2.");
+          ok(tabIds[0] != tabIds[1], "TabIds should be different.");
+          Services.prefs.setBoolPref("dom.payments.request.enabled", false);
+        }
+      );
+    }
+  );
+});
new file mode 100644
--- /dev/null
+++ b/dom/payments/test/head.js
@@ -0,0 +1,120 @@
+const kTestRoot = getRootDirectory(gTestPath).replace("chrome://mochitests/content",
+                                                      "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.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'.");
+
+  ok(!details.displayItems, "details.displayItems should be undefined.");
+  ok(!details.modifiers, "details.modifiers should be undefined.");
+  ok(!details.shippingOptions, "details.shippingOptions should be undefined.");
+
+  // checking the default generated PaymentOptions parameter
+  const paymentOptions = aSimplePayment.paymentOptions;
+  ok(!paymentOptions.requestPayerName, "payerName option should be false");
+  ok(!paymentOptions.requestPayerEmail, "payerEmail option should be false");
+  ok(!paymentOptions.requestPayerPhone, "payerPhone option should be false");
+  ok(!paymentOptions.requestShipping, "requestShipping option should be false");
+  is(paymentOptions.shippingType, "shipping", "shippingType option should be 'shipping'");
+}
+
+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.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'.");
+
+  const displayItems = details.displayItems;
+  is(displayItems.length, 2, "displayItems' length should be 2.");
+  let item = displayItems.queryElementAt(0, Ci.nsIPaymentItem);
+  is(item.label, "Original donation amount", "1st display item's label should be 'Original donation amount'.");
+  is(item.amount.currency, "USD", "1st display item's currency should be 'USD'.");
+  is(item.amount.value, "-65.00", "1st display item's value should be '-65.00'.");
+  item = displayItems.queryElementAt(1, Ci.nsIPaymentItem);
+  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.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'.");
+  is(additionalItem.amount.currency, "USD", "additional item's currency should be 'USD'.");
+  is(additionalItem.amount.value, "-10.00", "additional item's value should be '-10.00'.");
+  is(modifier.data, "{\"discountProgramParticipantId\":\"86328764873265\"}",
+     "modifier's data should be '{\"discountProgramParticipantId\":\"86328764873265\"}'.");
+
+  const shippingOptions = details.shippingOptions;
+  is(shippingOptions.length, 2, "shippingOptions' length should be 2.");
+
+  let shippingOption = shippingOptions.queryElementAt(0, Ci.nsIPaymentShippingOption);
+  is(shippingOption.id, "NormalShipping", "1st shippingOption's id should be 'NoramlShpping'.");
+  is(shippingOption.label, "NormalShipping", "1st shippingOption's lable should be 'NormalShipping'.");
+  is(shippingOption.amount.currency, "USD", "1st shippingOption's amount currency should be 'USD'.");
+  is(shippingOption.amount.value, "10.00", "1st shippingOption's amount value should be '10.00'.");
+  ok(shippingOption.selected, "1st shippingOption should be selected.");
+
+  shippingOption = shippingOptions.queryElementAt(1, Ci.nsIPaymentShippingOption);
+  is(shippingOption.id, "FastShipping", "2nd shippingOption's id should be 'FastShpping'.");
+  is(shippingOption.label, "FastShipping", "2nd shippingOption's lable should be 'FastShipping'.");
+  is(shippingOption.amount.currency, "USD", "2nd shippingOption's amount currency should be 'USD'.");
+  is(shippingOption.amount.value, "30.00", "2nd shippingOption's amount value should be '30.00'.");
+  ok(!shippingOption.selected, "2nd shippingOption should not be selected.");
+
+  // checking the passed PaymentOptions parameter
+  const paymentOptions = aPayment.paymentOptions;
+  ok(paymentOptions.requestPayerName, "payerName option should be true");
+  ok(paymentOptions.requestPayerEmail, "payerEmail option should be true");
+  ok(paymentOptions.requestPayerPhone, "payerPhone option should be true");
+  ok(paymentOptions.requestShipping, "requestShipping option should be true");
+  is(paymentOptions.shippingType, "shipping", "shippingType option should be 'shipping'");
+}
+
+function cleanup() {
+  const paymentSrv = Cc["@mozilla.org/dom/payments/payment-request-service;1"].getService(Ci.nsIPaymentRequestService);
+  if (paymentSrv) {
+    paymentSrv.cleanup();
+  }
+}
new file mode 100644
--- /dev/null
+++ b/dom/payments/test/multiple_payment_request.html
@@ -0,0 +1,84 @@
+<!DOCTYPE html>
+<html>
+  <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" ]
+    }];
+    const complexDetails = {
+      id: "complex details",
+      total: {
+        label: "Donation",
+        amount: { currency: "USD", value: "55.00" }
+      },
+      displayItems: [
+        {
+          label: "Original donation amount",
+          amount: { currency: "USD", value: "-65.00", }
+        },
+        {
+          label: "Friends and family discount",
+          amount: { currency: "USD", value: "10.00", }
+        }
+      ],
+      modifiers: [
+        {
+          supportedMethods: ["MyPay"],
+          total: {
+            label: "Discounted donation",
+            amount: { currency: "USD", value: "45.00", }
+          },
+          additionalDisplayItems: [
+            {
+              label: "MyPay discount",
+              amount: { currency: "USD", value: "-10.00", }
+            }
+          ],
+          data: { discountProgramParticipantId: "86328764873265", }
+        },
+      ],
+      shippingOptions: [
+        {
+          id: "NormalShipping",
+          label: "NormalShipping",
+          amount: { currency: "USD", value: "10.00", },
+          selected: true,
+        },
+        {
+          id: "FastShipping",
+          label: "FastShipping",
+          amount: { currency: "USD", value: "30.00", },
+          selected: false,
+        },
+      ],
+    };
+
+    const simpleDetails = {
+      id: "simple details",
+      total: {
+        label: "Donation",
+        amount: { currency: "USD", value: "55.00" }
+      },
+    };
+
+    const options = {
+      requestPayerName: true,
+      requestPayerEmail: true,
+      requestPayerPhone: true,
+      requestShipping: true,
+      shippingType: "shipping",
+    };
+
+    const paymentRequest1 = new PaymentRequest(supportedInstruments,
+                                               complexDetails,
+                                               options);
+    const paymentRequest2 = new PaymentRequest(supportedInstruments,
+                                               simpleDetails);
+    </script>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/payments/test/simple_payment_request.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+  <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" ]
+    }];
+    const details = {
+      id: "simple details",
+      total: {
+        label: "Donation",
+        amount: { currency: "USD", value: "55.00" }
+      },
+    };
+    const payRequest = new PaymentRequest(supportedInstruments, details);
+    </script>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/webidl/PaymentRequest.webidl
@@ -0,0 +1,89 @@
+/* -*- 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
+ */
+
+dictionary PaymentMethodData {
+  required sequence<DOMString> supportedMethods;
+           object              data;
+};
+
+dictionary PaymentCurrencyAmount {
+  required DOMString currency;
+  required DOMString value;
+           DOMString currencySystem = "urn:iso:std:iso:4217";
+};
+
+dictionary PaymentItem {
+  required DOMString             label;
+  required PaymentCurrencyAmount amount;
+           boolean               pending = false;
+};
+
+dictionary PaymentShippingOption {
+  required DOMString             id;
+  required DOMString             label;
+  required PaymentCurrencyAmount amount;
+           boolean               selected = false;
+};
+
+dictionary PaymentDetailsModifier {
+  required sequence<DOMString>   supportedMethods;
+           PaymentItem           total;
+           sequence<PaymentItem> additionalDisplayItems;
+           object                data;
+};
+
+dictionary PaymentDetailsBase {
+  sequence<PaymentItem>            displayItems;
+  sequence<PaymentShippingOption>  shippingOptions;
+  sequence<PaymentDetailsModifier> modifiers;
+};
+
+dictionary PaymentDetailsInit : PaymentDetailsBase {
+           DOMString   id;
+  required PaymentItem total;
+};
+
+enum PaymentShippingType {
+  "shipping",
+  "delivery",
+  "pickup"
+};
+
+dictionary PaymentOptions {
+  boolean             requestPayerName = false;
+  boolean             requestPayerEmail = false;
+  boolean             requestPayerPhone = false;
+  boolean             requestShipping = false;
+  PaymentShippingType shippingType = "shipping";
+};
+
+[Constructor(sequence<PaymentMethodData> methodData, PaymentDetailsInit details,
+             optional PaymentOptions options),
+ SecureContext,
+ Func="mozilla::dom::PaymentRequest::PrefEnabled"]
+interface PaymentRequest : EventTarget {
+  /* TODO : Add show() support in Bug 1345366
+  [NewObject]
+  Promise<PaymentResponse> show();
+   */
+  [NewObject]
+  Promise<void>            abort();
+  [NewObject]
+  Promise<boolean>         canMakePayment();
+
+  readonly attribute DOMString            id;
+  /* TODO : Add PaymentAddress support in Bug 1345369
+  readonly attribute PaymentAddress?      shippingAddress;
+   */
+  readonly attribute DOMString?           shippingOption;
+  readonly attribute PaymentShippingType? shippingType;
+
+           attribute EventHandler         onshippingaddresschange;
+           attribute EventHandler         onshippingoptionchange;
+};
--- a/dom/webidl/moz.build
+++ b/dom/webidl/moz.build
@@ -716,16 +716,17 @@ WEBIDL_FILES = [
     'OfflineResourceList.webidl',
     'OffscreenCanvas.webidl',
     'OscillatorNode.webidl',
     'PaintRequest.webidl',
     'PaintRequestList.webidl',
     'PaintWorkletGlobalScope.webidl',
     'PannerNode.webidl',
     'ParentNode.webidl',
+    'PaymentRequest.webidl',
     'Performance.webidl',
     'PerformanceEntry.webidl',
     'PerformanceMark.webidl',
     'PerformanceMeasure.webidl',
     'PerformanceNavigation.webidl',
     'PerformanceObserver.webidl',
     'PerformanceObserverEntryList.webidl',
     'PerformanceResourceTiming.webidl',
--- a/mobile/android/installer/package-manifest.in
+++ b/mobile/android/installer/package-manifest.in
@@ -121,16 +121,17 @@
 @BINPATH@/components/dom_file.xpt
 @BINPATH@/components/dom_geolocation.xpt
 @BINPATH@/components/dom_media.xpt
 @BINPATH@/components/dom_network.xpt
 @BINPATH@/components/dom_notification.xpt
 @BINPATH@/components/dom_html.xpt
 @BINPATH@/components/dom_offline.xpt
 @BINPATH@/components/dom_json.xpt
+@BINPATH@/components/dom_payments.xpt
 @BINPATH@/components/dom_power.xpt
 #ifdef MOZ_ANDROID_GCM
 @BINPATH@/components/dom_push.xpt
 #endif
 @BINPATH@/components/dom_quota.xpt
 @BINPATH@/components/dom_range.xpt
 @BINPATH@/components/dom_security.xpt
 @BINPATH@/components/dom_sidebar.xpt
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -5709,16 +5709,19 @@ pref("dom.IntersectionObserver.enabled",
 
 // Whether module scripts (<script type="module">) are enabled for content.
 pref("dom.moduleScripts.enabled", false);
 
 // Maximum amount of time in milliseconds consecutive setTimeout()/setInterval()
 // callback are allowed to run before yielding the event loop.
 pref("dom.timeout.max_consecutive_callbacks_ms", 4);
 
+// Use this preference to house "Payment Request API" during development
+pref("dom.payments.request.enabled", false);
+
 #ifdef FUZZING
 pref("fuzzing.enabled", false);
 #endif
 
 // Set advanced layers preferences here to have them show up in about:config or
 // to be overridable in reftest.list files. They should pretty much all be set
 // to a value of 2, and the conditional-pref code in gfxPrefs.h will convert
 // it to a boolean as appropriate. In particular, do NOT add ifdefs here to