mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-17 23:35:34 +00:00
Bug 1383300 - Show payment request total and origin in the dialog. r=MattN
MozReview-Commit-ID: 9taFJYmQnBP --HG-- extra : rebase_source : 5c522845fa7b436a6dda1b7c873cd209fbaf798d
This commit is contained in:
parent
1bf7198d39
commit
ec9fa2ac68
11
toolkit/components/payments/content/paymentDialog.css
Normal file
11
toolkit/components/payments/content/paymentDialog.css
Normal file
@ -0,0 +1,11 @@
|
||||
/* 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/. */
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#paymentRequestFrame {
|
||||
border: none;
|
||||
}
|
@ -13,24 +13,37 @@ const { classes: Cc, interfaces: Ci, results: Cr, utils: Cu } = Components;
|
||||
const paymentSrv = Cc["@mozilla.org/dom/payments/payment-request-service;1"]
|
||||
.getService(Ci.nsIPaymentRequestService);
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
let PaymentDialog = {
|
||||
componentsLoaded: new Map(),
|
||||
frame: null,
|
||||
mm: null,
|
||||
request: null,
|
||||
|
||||
init(requestId, frame) {
|
||||
if (!requestId || typeof(requestId) != "string") {
|
||||
throw new Error("Invalid PaymentRequest ID");
|
||||
}
|
||||
this.request = paymentSrv.getPaymentRequestById(requestId);
|
||||
|
||||
if (!this.request) {
|
||||
throw new Error(`PaymentRequest not found: ${requestId}`);
|
||||
}
|
||||
|
||||
init(frame) {
|
||||
this.frame = frame;
|
||||
this.mm = frame.frameLoader.messageManager;
|
||||
this.mm.addMessageListener("paymentContentToChrome", this);
|
||||
this.mm.loadFrameScript("chrome://payments/content/paymentDialogFrameScript.js", true);
|
||||
this.frame.src = "resource://payments/paymentRequest.xhtml";
|
||||
},
|
||||
|
||||
createShowResponse({requestId, acceptStatus, methodName = "", data = null,
|
||||
createShowResponse({acceptStatus, methodName = "", data = null,
|
||||
payerName = "", payerEmail = "", payerPhone = ""}) {
|
||||
let showResponse = this.createComponentInstance(Ci.nsIPaymentShowActionResponse);
|
||||
let methodData = this.createComponentInstance(Ci.nsIGeneralResponseData);
|
||||
|
||||
showResponse.init(requestId,
|
||||
showResponse.init(this.request.requestId,
|
||||
acceptStatus,
|
||||
methodName,
|
||||
methodData,
|
||||
@ -62,9 +75,8 @@ let PaymentDialog = {
|
||||
return component.createInstance(componentInterface);
|
||||
},
|
||||
|
||||
onPaymentCancel(requestId) {
|
||||
onPaymentCancel() {
|
||||
const showResponse = this.createShowResponse({
|
||||
requestId,
|
||||
acceptStatus: Ci.nsIPaymentActionResponse.PAYMENT_REJECTED,
|
||||
});
|
||||
paymentSrv.respondPayment(showResponse);
|
||||
@ -72,18 +84,30 @@ let PaymentDialog = {
|
||||
},
|
||||
|
||||
receiveMessage({data}) {
|
||||
let {messageType, requestId} = data;
|
||||
let {messageType} = data;
|
||||
|
||||
switch (messageType) {
|
||||
case "initializeRequest": {
|
||||
let requestSerialized = JSON.parse(JSON.stringify(this.request));
|
||||
|
||||
// Manually serialize the nsIPrincipal.
|
||||
let displayHost = this.request.topLevelPrincipal.URI.displayHost;
|
||||
requestSerialized.topLevelPrincipal = {
|
||||
URI: {
|
||||
displayHost,
|
||||
},
|
||||
};
|
||||
|
||||
this.mm.sendAsyncMessage("paymentChromeToContent", {
|
||||
messageType: "showPaymentRequest",
|
||||
data: window.arguments[0],
|
||||
data: {
|
||||
request: requestSerialized,
|
||||
},
|
||||
});
|
||||
break;
|
||||
}
|
||||
case "paymentCancel": {
|
||||
this.onPaymentCancel(requestId);
|
||||
this.onPaymentCancel();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -91,4 +115,5 @@ let PaymentDialog = {
|
||||
};
|
||||
|
||||
let frame = document.getElementById("paymentRequestFrame");
|
||||
PaymentDialog.init(frame);
|
||||
let requestId = (new URLSearchParams(window.location.search)).get("requestId");
|
||||
PaymentDialog.init(requestId, frame);
|
||||
|
@ -6,14 +6,15 @@
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title></title>
|
||||
<link rel="stylesheet" href="chrome://payments/content/paymentDialog.css"/>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<iframe type="content"
|
||||
id="paymentRequestFrame"
|
||||
mozbrowser="true"
|
||||
remote="true"
|
||||
name="paymentRequestFrame"
|
||||
src="resource://payments/paymentRequest.xhtml"></iframe>
|
||||
name="paymentRequestFrame"></iframe>
|
||||
<script src="chrome://payments/content/paymentDialog.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -24,7 +24,14 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
let PaymentFrameScript = {
|
||||
init() {
|
||||
this.defineLazyLogGetter(this, "frameScript");
|
||||
XPCOMUtils.defineLazyGetter(this, "log", () => {
|
||||
let {ConsoleAPI} = Cu.import("resource://gre/modules/Console.jsm", {});
|
||||
return new ConsoleAPI({
|
||||
maxLogLevelPref: "dom.payments.loglevel",
|
||||
prefix: "paymentDialogFrameScript",
|
||||
});
|
||||
});
|
||||
|
||||
addEventListener("paymentContentToChrome", this, false, true);
|
||||
|
||||
addMessageListener("paymentChromeToContent", this);
|
||||
@ -39,35 +46,22 @@ let PaymentFrameScript = {
|
||||
},
|
||||
|
||||
sendToChrome({detail}) {
|
||||
let {messageType, requestId} = detail;
|
||||
this.log.debug(`received message from content: ${messageType} ... ${requestId}`);
|
||||
this.sendMessageToChrome(messageType, {
|
||||
requestId,
|
||||
});
|
||||
},
|
||||
|
||||
defineLazyLogGetter(scope, logPrefix) {
|
||||
XPCOMUtils.defineLazyGetter(scope, "log", () => {
|
||||
let {ConsoleAPI} = Cu.import("resource://gre/modules/Console.jsm", {});
|
||||
return new ConsoleAPI({
|
||||
maxLogLevelPref: "dom.payments.loglevel",
|
||||
prefix: logPrefix,
|
||||
});
|
||||
});
|
||||
let {messageType} = detail;
|
||||
this.log.debug("sendToChrome:", messageType, detail);
|
||||
this.sendMessageToChrome(messageType, detail);
|
||||
},
|
||||
|
||||
sendToContent(messageType, detail = {}) {
|
||||
this.log.debug(`sendToContent (${messageType})`);
|
||||
this.log.debug("sendToContent", messageType, detail);
|
||||
let response = Object.assign({messageType}, detail);
|
||||
let event = new content.document.defaultView.CustomEvent("paymentChromeToContent", {
|
||||
bubbles: true,
|
||||
detail: Cu.cloneInto(response, content.document.defaultView),
|
||||
let event = new content.CustomEvent("paymentChromeToContent", {
|
||||
detail: Cu.cloneInto(response, content),
|
||||
});
|
||||
content.document.dispatchEvent(event);
|
||||
content.dispatchEvent(event);
|
||||
},
|
||||
|
||||
sendMessageToChrome(messageType, detail = {}) {
|
||||
sendAsyncMessage("paymentContentToChrome", Object.assign(detail, {messageType}));
|
||||
sendMessageToChrome(messageType, data = {}) {
|
||||
sendAsyncMessage("paymentContentToChrome", Object.assign(data, {messageType}));
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -14,6 +14,13 @@ Debugging
|
||||
|
||||
Set the pref ``dom.payments.loglevel`` to "Debug".
|
||||
|
||||
To open a debugger in the context of the remote payment frame, run the following while the dialog is the most recent window:
|
||||
``
|
||||
gDevToolsBrowser.openContentProcessToolbox({
|
||||
selectedBrowser: Services.wm.getMostRecentWindow(null).document.getElementById("paymentRequestFrame").frameLoader,
|
||||
})
|
||||
``
|
||||
|
||||
|
||||
Communication with the DOM
|
||||
==========================
|
||||
@ -32,7 +39,7 @@ This is because the unprivileged document cannot access message managers.
|
||||
Instead, all communication across the privileged/unprivileged boundary is done via custom DOM events:
|
||||
|
||||
* A ``paymentContentToChrome`` event is dispatched when the dialog contents want to communicate with the privileged dialog wrapper.
|
||||
* A ``paymentChromeToContent`` event is dispatched on the ``document`` with the ``detail`` property populated when the privileged dialog wrapper communicates with the unprivileged dialog.
|
||||
* A ``paymentChromeToContent`` event is dispatched on the ``window`` with the ``detail`` property populated when the privileged dialog wrapper communicates with the unprivileged dialog.
|
||||
|
||||
These events are converted to/from message manager messages of the same name to communicate to the other process.
|
||||
The purpose of `paymentDialogFrameScript.js` is to simply convert unprivileged DOM events to/from messages from the other process.
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
toolkit.jar:
|
||||
% content payments %content/payments/
|
||||
content/payments/paymentDialog.css (content/paymentDialog.css)
|
||||
content/payments/paymentDialog.js (content/paymentDialog.js)
|
||||
content/payments/paymentDialogFrameScript.js (content/paymentDialogFrameScript.js)
|
||||
content/payments/paymentDialog.xhtml (content/paymentDialog.xhtml)
|
||||
|
@ -25,19 +25,15 @@ XPCOMUtils.defineLazyServiceGetter(this,
|
||||
"@mozilla.org/dom/payments/payment-request-service;1",
|
||||
"nsIPaymentRequestService");
|
||||
|
||||
function defineLazyLogGetter(scope, logPrefix) {
|
||||
XPCOMUtils.defineLazyGetter(scope, "log", () => {
|
||||
function PaymentUIService() {
|
||||
this.wrappedJSObject = this;
|
||||
XPCOMUtils.defineLazyGetter(this, "log", () => {
|
||||
let {ConsoleAPI} = Cu.import("resource://gre/modules/Console.jsm", {});
|
||||
return new ConsoleAPI({
|
||||
maxLogLevelPref: "dom.payments.loglevel",
|
||||
prefix: logPrefix,
|
||||
prefix: "Payment UI Service",
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function PaymentUIService() {
|
||||
this.wrappedJSObject = this;
|
||||
defineLazyLogGetter(this, "Payment UI Service");
|
||||
this.log.debug("constructor");
|
||||
}
|
||||
|
||||
@ -50,16 +46,15 @@ PaymentUIService.prototype = {
|
||||
// nsIPaymentUIService implementation:
|
||||
|
||||
showPayment(requestId) {
|
||||
this.log.debug(`showPayment: ${requestId}`);
|
||||
this.log.debug("showPayment:", requestId);
|
||||
let chromeWindow = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
chromeWindow.openDialog(this.DIALOG_URL,
|
||||
chromeWindow.openDialog(`${this.DIALOG_URL}?requestId=${requestId}`,
|
||||
`${this.REQUEST_ID_PREFIX}${requestId}`,
|
||||
"modal,dialog,centerscreen",
|
||||
{requestId});
|
||||
"modal,dialog,centerscreen,resizable=no");
|
||||
},
|
||||
|
||||
abortPayment(requestId) {
|
||||
this.log.debug(`abortPayment: ${requestId}`);
|
||||
this.log.debug("abortPayment:", requestId);
|
||||
let abortResponse = Cc["@mozilla.org/dom/payments/payment-abort-action-response;1"]
|
||||
.createInstance(Ci.nsIPaymentAbortActionResponse);
|
||||
|
||||
@ -84,7 +79,7 @@ PaymentUIService.prototype = {
|
||||
},
|
||||
|
||||
completePayment(requestId) {
|
||||
this.log.debug(`completePayment: ${requestId}`);
|
||||
this.log.debug("completePayment:", requestId);
|
||||
let completeResponse = Cc["@mozilla.org/dom/payments/payment-complete-action-response;1"]
|
||||
.createInstance(Ci.nsIPaymentCompleteActionResponse);
|
||||
completeResponse.init(requestId, Ci.nsIPaymentActionResponse.COMPLTETE_SUCCEEDED);
|
||||
@ -92,7 +87,7 @@ PaymentUIService.prototype = {
|
||||
},
|
||||
|
||||
updatePayment(requestId) {
|
||||
this.log.debug(`updatePayment: ${requestId}`);
|
||||
this.log.debug("updatePayment:", requestId);
|
||||
},
|
||||
|
||||
// other helper methods
|
||||
|
@ -2,3 +2,23 @@
|
||||
* 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/. */
|
||||
|
||||
html {
|
||||
background: -moz-dialog;
|
||||
}
|
||||
|
||||
#total {
|
||||
border: 1px solid black;
|
||||
margin: 5px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#total .label {
|
||||
font-size: 15px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#cancel {
|
||||
position: absolute;
|
||||
bottom: 10px;
|
||||
left: 10px;
|
||||
}
|
||||
|
@ -11,14 +11,16 @@
|
||||
"use strict";
|
||||
|
||||
let PaymentRequest = {
|
||||
requestId: null,
|
||||
request: null,
|
||||
domReadyPromise: null,
|
||||
|
||||
init() {
|
||||
// listen to content
|
||||
window.addEventListener("paymentChromeToContent", this);
|
||||
|
||||
// listen to user events
|
||||
window.addEventListener("DOMContentLoaded", this, {once: true});
|
||||
this.domReadyPromise = new Promise(function dcl(resolve) {
|
||||
window.addEventListener("DOMContentLoaded", resolve, {once: true});
|
||||
}).then(this.handleEvent.bind(this));
|
||||
|
||||
// This scope is now ready to listen to the initialization data
|
||||
this.sendMessageToChrome("initializeRequest");
|
||||
@ -57,7 +59,6 @@ let PaymentRequest = {
|
||||
let event = new CustomEvent("paymentContentToChrome", {
|
||||
bubbles: true,
|
||||
detail: Object.assign({
|
||||
requestId: this.requestId,
|
||||
messageType,
|
||||
}, detail),
|
||||
});
|
||||
@ -65,11 +66,12 @@ let PaymentRequest = {
|
||||
},
|
||||
|
||||
onChromeToContent({detail}) {
|
||||
let {messageType, requestId} = detail;
|
||||
let {messageType} = detail;
|
||||
|
||||
switch (messageType) {
|
||||
case "showPaymentRequest": {
|
||||
this.requestId = requestId;
|
||||
this.request = detail.request;
|
||||
this.onShowPaymentRequest();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -83,6 +85,20 @@ let PaymentRequest = {
|
||||
this.sendMessageToChrome("paymentDialogReady");
|
||||
},
|
||||
|
||||
async onShowPaymentRequest() {
|
||||
// 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");
|
||||
totalEl.querySelector(".value").textContent = totalItem.amount.value;
|
||||
totalEl.querySelector(".currency").textContent = totalItem.amount.currency;
|
||||
totalEl.querySelector(".label").textContent = totalItem.label;
|
||||
},
|
||||
|
||||
onCancel() {
|
||||
this.sendMessageToChrome("paymentCancel");
|
||||
},
|
||||
|
@ -10,6 +10,13 @@
|
||||
<script src="resource://payments/paymentRequest.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="host-name"></div>
|
||||
|
||||
<div id="total">
|
||||
<h2 class="label"></h2>
|
||||
<span class="value"></span>
|
||||
<span class="currency"></span>
|
||||
</div>
|
||||
<div id="controls-container">
|
||||
<button id="cancel">Cancel payment</button>
|
||||
</div>
|
||||
|
Loading…
Reference in New Issue
Block a user