1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/webapprt/PaymentUIGlue.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,148 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this file, 1.6 + * You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +"use strict"; 1.9 + 1.10 +const { interfaces: Ci, utils: Cu } = Components; 1.11 + 1.12 +Cu.import("resource://gre/modules/XPCOMUtils.jsm"); 1.13 +Cu.import("resource://gre/modules/Services.jsm"); 1.14 + 1.15 +XPCOMUtils.defineLazyServiceGetter(this, "cpmm", 1.16 + "@mozilla.org/childprocessmessagemanager;1", 1.17 + "nsIMessageSender"); 1.18 + 1.19 +function paymentSuccess(aRequestId) { 1.20 + return function(aResult) { 1.21 + closePaymentWindow(aRequestId, function() { 1.22 + cpmm.sendAsyncMessage("Payment:Success", { requestId: aRequestId, 1.23 + result: aResult }); 1.24 + }); 1.25 + }; 1.26 +} 1.27 + 1.28 +function paymentFailed(aRequestId) { 1.29 + return function(aErrorMsg) { 1.30 + closePaymentWindow(aRequestId, function() { 1.31 + cpmm.sendAsyncMessage("Payment:Failed", { requestId: aRequestId, 1.32 + errorMsg: aErrorMsg }); 1.33 + }); 1.34 + }; 1.35 +} 1.36 + 1.37 +let payments = {}; 1.38 + 1.39 +function closePaymentWindow(aId, aCallback) { 1.40 + if (payments[aId]) { 1.41 + payments[aId].handled = true; 1.42 + payments[aId].win.close(); 1.43 + payments[aId] = null; 1.44 + } 1.45 + 1.46 + aCallback(); 1.47 +} 1.48 + 1.49 +function PaymentUI() {} 1.50 + 1.51 +PaymentUI.prototype = { 1.52 + classID: Components.ID("{ede1124f-72e8-4a31-9567-3270d46f21fb}"), 1.53 + QueryInterface: XPCOMUtils.generateQI([Ci.nsIPaymentUIGlue]), 1.54 + 1.55 + confirmPaymentRequest: function(aRequestId, aRequests, aSuccessCb, aErrorCb) { 1.56 + // If there's only one payment provider that will work, just move on 1.57 + // without prompting the user. 1.58 + if (aRequests.length == 1) { 1.59 + aSuccessCb.onresult(aRequestId, aRequests[0].type); 1.60 + return; 1.61 + } 1.62 + 1.63 + let items = []; 1.64 + 1.65 + // Otherwise, let the user select a payment provider from a list. 1.66 + for (let i = 0; i < aRequests.length; i++) { 1.67 + let request = aRequests[i]; 1.68 + let requestText = request.providerName; 1.69 + if (request.productPrice && Array.isArray(request.productPrice)) { 1.70 + // We should guess the user currency and use that instead. 1.71 + requestText += " (" + request.productPrice[0].amount + " " + 1.72 + request.productPrice[0].currency + ")"; 1.73 + } 1.74 + items.push(requestText); 1.75 + } 1.76 + 1.77 + let selected = {}; 1.78 + 1.79 + let bundle = Services.strings. 1.80 + createBundle("chrome://webapprt/locale/webapp.properties"); 1.81 + let result = Services.prompt. 1.82 + select(null, bundle.GetStringFromName("paymentDialog.title"), 1.83 + bundle.GetStringFromName("paymentDialog.message"), 1.84 + items.length, items, selected); 1.85 + if (result) { 1.86 + aSuccessCb.onresult(aRequestId, 1.87 + aRequests[selected.value].type); 1.88 + } else { 1.89 + aErrorCb.onresult(aRequestId, "USER_CANCELLED"); 1.90 + } 1.91 + }, 1.92 + 1.93 + showPaymentFlow: function(aRequestId, aPaymentFlowInfo, aErrorCb) { 1.94 + let win = Services.ww. 1.95 + openWindow(null, 1.96 + "chrome://webapprt/content/webapp.xul", 1.97 + "_blank", 1.98 + "chrome,dialog=no,resizable,scrollbars,centerscreen", 1.99 + null); 1.100 + 1.101 + // Store a reference to the window so that we can close it when the payment 1.102 + // succeeds or fails. 1.103 + payments[aRequestId] = { win: win, handled: false }; 1.104 + 1.105 + // Inject paymentSuccess and paymentFailed methods into the document after 1.106 + // its loaded. 1.107 + win.addEventListener("DOMContentLoaded", function onDOMContentLoaded() { 1.108 + win.removeEventListener("DOMContentLoaded", onDOMContentLoaded); 1.109 + 1.110 + let browserElement = win.document.getElementById("content"); 1.111 + browserElement. 1.112 + setAttribute("src", aPaymentFlowInfo.uri + aPaymentFlowInfo.jwt); 1.113 + 1.114 + browserElement.addEventListener("DOMWindowCreated", 1.115 + function onDOMWindowCreated() { 1.116 + browserElement.removeEventListener("DOMWindowCreated", 1.117 + onDOMWindowCreated); 1.118 + 1.119 + 1.120 + win.document.getElementById("content").contentDocument.defaultView 1.121 + .wrappedJSObject.mozPaymentProvider = { 1.122 + __exposedProps__: { 1.123 + paymentSuccess: 'r', 1.124 + paymentFailed: 'r' 1.125 + }, 1.126 + paymentSuccess: paymentSuccess(aRequestId), 1.127 + paymentFailed: paymentFailed(aRequestId) 1.128 + }; 1.129 + }, true); 1.130 + }); 1.131 + 1.132 + let winObserver = function(aClosedWin, aTopic) { 1.133 + if (aTopic == "domwindowclosed") { 1.134 + // Fail the payment if the window is closed. 1.135 + if (aClosedWin == win) { 1.136 + Services.ww.unregisterNotification(winObserver); 1.137 + if (payments[aRequestId] && !payments[aRequestId].handled) { 1.138 + aErrorCb.onresult(aRequestId, "USER_CANCELLED"); 1.139 + } 1.140 + } 1.141 + } 1.142 + } 1.143 + 1.144 + Services.ww.registerNotification(winObserver); 1.145 + }, 1.146 + 1.147 + cleanup: function() { 1.148 + }, 1.149 +} 1.150 + 1.151 +this.NSGetFactory = XPCOMUtils.generateNSGetFactory([PaymentUI]);