Bug 1421806 - Use a custom element for the payment request dialog contents. r=jaws
authorMatthew Noorenberghe <mozilla@noorenberghe.ca>
Fri, 01 Dec 2017 14:15:04 -0800
changeset 394966 bd96153b3e7c4503b60cd9eeda847a12492d0b87
parent 394965 562dbac7f65ce1a567c715981541fab3e56c9d52
child 394967 facb23d70335db103f23fe988345f4b3d00aa8c9
push id97987
push usernerli@mozilla.com
push dateTue, 05 Dec 2017 13:52:50 +0000
treeherdermozilla-inbound@8842dba7396b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjaws
bugs1421806
milestone59.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 1421806 - Use a custom element for the payment request dialog contents. r=jaws The payment-dialog contents are already tested via browser-chrome tests MozReview-Commit-ID: IsFH2FteBpf
toolkit/components/payments/res/components/currency-amount.js
toolkit/components/payments/res/containers/payment-dialog.js
toolkit/components/payments/res/debugging.html
toolkit/components/payments/res/debugging.js
toolkit/components/payments/res/paymentRequest.js
toolkit/components/payments/res/paymentRequest.xhtml
--- a/toolkit/components/payments/res/components/currency-amount.js
+++ b/toolkit/components/payments/res/components/currency-amount.js
@@ -1,12 +1,14 @@
 /* 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/. */
 
+"use strict";
+
 /**
  * <currency-amount value="7.5" currency="USD"></currency-amount>
  */
 
 /* global ObservedPropertiesMixin */
 
 class CurrencyAmount extends ObservedPropertiesMixin(HTMLElement) {
   static get observedAttributes() {
new file mode 100644
--- /dev/null
+++ b/toolkit/components/payments/res/containers/payment-dialog.js
@@ -0,0 +1,55 @@
+/* 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/. */
+
+/* global PaymentStateSubscriberMixin, PaymentRequest */
+
+"use strict";
+
+/**
+ * <payment-dialog></payment-dialog>
+ */
+
+class PaymentDialog extends PaymentStateSubscriberMixin(HTMLElement) {
+  constructor() {
+    super();
+    this._template = document.getElementById("payment-dialog-template");
+  }
+
+  connectedCallback() {
+    let contents = document.importNode(this._template.content, true);
+    this._hostNameEl = contents.querySelector("#host-name");
+
+    this._cancelButton = contents.querySelector("#cancel");
+    this._cancelButton.addEventListener("click", this.cancelRequest);
+
+    this.appendChild(contents);
+
+    super.connectedCallback();
+  }
+
+  disconnectedCallback() {
+    this._cancelButtonEl.removeEventListener("click", this.cancelRequest);
+    super.disconnectedCallback();
+  }
+
+  cancelRequest() {
+    PaymentRequest.cancel();
+  }
+
+  setLoadingState(state) {
+    this.requestStore.setState(state);
+  }
+
+  render(state) {
+    let request = state.request;
+    this._hostNameEl.textContent = request.topLevelPrincipal.URI.displayHost;
+
+    let totalItem = request.paymentDetails.totalItem;
+    let totalAmountEl = this.querySelector("#total > currency-amount");
+    totalAmountEl.value = totalItem.amount.value;
+    totalAmountEl.currency = totalItem.amount.currency;
+  }
+}
+
+customElements.define("payment-dialog", PaymentDialog);
--- a/toolkit/components/payments/res/debugging.html
+++ b/toolkit/components/payments/res/debugging.html
@@ -6,11 +6,14 @@
   <head>
     <meta charset="utf-8">
     <meta http-equiv="Content-Security-Policy" content="default-src 'self'">
     <script src="debugging.js"></script>
   </head>
   <body>
     <div>
       <button id="refresh">Refresh</button>
+      <button id="logState">Log state</button>
+      <button id="setRequest1">Set Request 1</button>
+      <button id="setRequest2">Set Request 2</button>
     </div>
   </body>
 </html>
--- a/toolkit/components/payments/res/debugging.js
+++ b/toolkit/components/payments/res/debugging.js
@@ -1,16 +1,139 @@
 /* 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/. */
 
+const requestStore = window.parent.document.querySelector("payment-dialog").requestStore;
+
+let REQUEST_1 = {
+  tabId: 9,
+  topLevelPrincipal: {URI: {displayHost: "tschaeff.github.io"}},
+  requestId: "3797081f-a96b-c34b-a58b-1083c6e66e25",
+  paymentMethods: [],
+  paymentDetails: {
+    id: "",
+    totalItem: {label: "Demo total", amount: {currency: "EUR", value: "1.00"}, pending: false},
+    displayItems: [
+      {
+        label: "Square",
+        amount: {
+          currency: "USD",
+          value: "5",
+        },
+      },
+    ],
+    shippingOptions: [
+      {
+        id: "123",
+        label: "Fast",
+        amount: {
+          currency: "USD",
+          value: 10,
+        },
+        selected: false,
+      },
+      {
+        id: "456",
+        label: "Faster (default)",
+        amount: {
+          currency: "USD",
+          value: 20,
+        },
+        selected: true,
+      },
+    ],
+    modifiers: null,
+    error: "",
+  },
+  paymentOptions: {
+    requestPayerName: false,
+    requestPayerEmail: false,
+    requestPayerPhone: false,
+    requestShipping: false,
+    shippingType: "shipping",
+  },
+};
+
+let REQUEST_2 = {
+  tabId: 9,
+  topLevelPrincipal: {URI: {displayHost: "example.com"}},
+  requestId: "3797081f-a96b-c34b-a58b-1083c6e66e25",
+  paymentMethods: [],
+  paymentDetails: {
+    id: "",
+    totalItem: {label: "Demo total", amount: {currency: "CAD", value: "25.75"}, pending: false},
+    displayItems: [
+      {
+        label: "Triangle",
+        amount: {
+          currency: "CAD",
+          value: "3",
+        },
+      },
+      {
+        label: "Circle",
+        amount: {
+          currency: "EUR",
+          value: "10.50",
+        },
+      },
+    ],
+    shippingOptions: [
+      {
+        id: "123",
+        label: "Fast (default)",
+        amount: {
+          currency: "USD",
+          value: 10,
+        },
+        selected: true,
+      },
+      {
+        id: "947",
+        label: "Slow",
+        amount: {
+          currency: "USD",
+          value: 10,
+        },
+        selected: false,
+      },
+    ],
+    modifiers: null,
+    error: "",
+  },
+  paymentOptions: {
+    requestPayerName: false,
+    requestPayerEmail: false,
+    requestPayerPhone: false,
+    requestShipping: false,
+    shippingType: "shipping",
+  },
+};
+
+
 let buttonActions = {
+  logState() {
+    let state = requestStore.getState();
+    // eslint-disable-next-line no-console
+    console.log(state);
+    dump(`${JSON.stringify(state, null, 2)}\n`);
+  },
+
   refresh() {
     window.parent.location.reload(true);
   },
+
+  setRequest1() {
+    requestStore.setState({request: REQUEST_1});
+  },
+
+  setRequest2() {
+    requestStore.setState({request: REQUEST_2});
+  },
 };
 
 window.addEventListener("click", function onButtonClick(evt) {
   let id = evt.target.id;
   if (!id || typeof(buttonActions[id]) != "function") {
     return;
   }
 
--- a/toolkit/components/payments/res/paymentRequest.js
+++ b/toolkit/components/payments/res/paymentRequest.js
@@ -6,17 +6,16 @@
  * Loaded in the unprivileged frame of each payment dialog.
  *
  * Communicates with privileged code via DOM Events.
  */
 
 "use strict";
 
 let PaymentRequest = {
-  request: null,
   domReadyPromise: null,
 
   init() {
     // listen to content
     window.addEventListener("paymentChromeToContent", this);
 
     window.addEventListener("keypress", this);
 
@@ -29,25 +28,16 @@ let PaymentRequest = {
   },
 
   handleEvent(event) {
     switch (event.type) {
       case "DOMContentLoaded": {
         this.onPaymentRequestLoad();
         break;
       }
-      case "click": {
-        switch (event.target.id) {
-          case "cancel": {
-            this.onCancel();
-            break;
-          }
-        }
-        break;
-      }
       case "keypress": {
         if (event.code != "KeyD" || !event.altKey || !event.ctrlKey) {
           break;
         }
         let debuggingConsole = document.getElementById("debugging-console");
         debuggingConsole.hidden = !debuggingConsole.hidden;
         break;
       }
@@ -75,47 +65,39 @@ let PaymentRequest = {
     document.dispatchEvent(event);
   },
 
   onChromeToContent({detail}) {
     let {messageType} = detail;
 
     switch (messageType) {
       case "showPaymentRequest": {
-        this.request = detail.request;
-        this.onShowPaymentRequest();
+        this.onShowPaymentRequest(detail);
         break;
       }
     }
   },
 
   onPaymentRequestLoad(requestId) {
-    let cancelBtn = document.getElementById("cancel");
-    cancelBtn.addEventListener("click", this, {once: true});
-
     window.addEventListener("unload", this, {once: true});
     this.sendMessageToChrome("paymentDialogReady");
   },
 
-  async onShowPaymentRequest() {
+  async onShowPaymentRequest(detail) {
     // Handle getting called before the DOM is ready.
     await this.domReadyPromise;
 
-    let hostNameEl = document.getElementById("host-name");
-    hostNameEl.textContent = this.request.topLevelPrincipal.URI.displayHost;
-
-    let totalItem = this.request.paymentDetails.totalItem;
-    let totalEl = document.getElementById("total");
-    let currencyEl = totalEl.querySelector("currency-amount");
-    currencyEl.value = totalItem.amount.value;
-    currencyEl.currency = totalItem.amount.currency;
-    totalEl.querySelector(".label").textContent = totalItem.label;
+    document.querySelector("payment-dialog").setLoadingState({
+      request: detail.request,
+      savedAddresses: detail.savedAddresses,
+      savedBasicCards: detail.savedBasicCards,
+    });
   },
 
-  onCancel() {
+  cancel() {
     this.sendMessageToChrome("paymentCancel");
   },
 
   onPaymentRequestUnload() {
     // remove listeners that may be used multiple times here
     window.removeEventListener("paymentChromeToContent", this);
   },
 };
--- a/toolkit/components/payments/res/paymentRequest.xhtml
+++ b/toolkit/components/payments/res/paymentRequest.xhtml
@@ -4,25 +4,38 @@
    - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
 <!DOCTYPE html>
 <html xmlns="http://www.w3.org/1999/xhtml">
 <head>
   <meta http-equiv="Content-Security-Policy" content="default-src 'self'"/>
   <title></title>
   <link rel="stylesheet" href="paymentRequest.css"/>
   <script src="vendor/custom-elements.min.js"></script>
+
+  <script src="PaymentsStore.js"></script>
+
   <script src="mixins/ObservedPropertiesMixin.js"></script>
+  <script src="mixins/PaymentStateSubscriberMixin.js"></script>
+
   <script src="components/currency-amount.js"></script>
+
+  <script src="containers/payment-dialog.js"></script>
+
   <script src="paymentRequest.js"></script>
+
+  <template id="payment-dialog-template">
+    <div id="host-name"></div>
+
+    <div id="total">
+      <h2 class="label"></h2>
+      <currency-amount></currency-amount>
+    </div>
+    <div id="controls-container">
+      <button id="cancel">Cancel payment</button>
+    </div>
+  </template>
 </head>
 <body>
   <iframe id="debugging-console" hidden="hidden" src="debugging.html"></iframe>
-  <div id="host-name"></div>
 
-  <div id="total">
-    <h2 class="label"></h2>
-    <currency-amount></currency-amount>
-  </div>
-  <div id="controls-container">
-    <button id="cancel">Cancel payment</button>
-  </div>
+  <payment-dialog></payment-dialog>
 </body>
 </html>