forked from mozilla/gecko-dev
-
Notifications
You must be signed in to change notification settings - Fork 1
/
PaymentGlue.js
174 lines (146 loc) · 5.82 KB
/
PaymentGlue.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
/* 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";
const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
// JS shim that contains the callback functions to be triggered from the
// payment provider's code in order to fire DOMRequest events.
const kPaymentShimFile = "chrome://browser/content/payment.js";
// Type of MozChromEvents to handle payment dialogs.
const kOpenPaymentConfirmationEvent = "open-payment-confirmation-dialog";
const kOpenPaymentFlowEvent = "open-payment-flow-dialog";
XPCOMUtils.defineLazyServiceGetter(this, "uuidgen",
"@mozilla.org/uuid-generator;1",
"nsIUUIDGenerator");
function debug (s) {
//dump("-*- PaymentGlue: " + s + "\n");
};
function PaymentUI() {
}
PaymentUI.prototype = {
confirmPaymentRequest: function confirmPaymentRequest(aRequestId,
aRequests,
aSuccessCb,
aErrorCb) {
let _error = function _error(errorMsg) {
if (aErrorCb) {
aErrorCb.onresult(aRequestId, errorMsg);
}
};
let browser = Services.wm.getMostRecentWindow("navigator:browser");
let content = browser.getContentWindow();
if (!content) {
_error("NO_CONTENT_WINDOW");
return;
}
// The UI should listen for mozChromeEvent 'open-payment-confirmation-dialog'
// type in order to create and show the payment request confirmation frame
// embeded within a trusted dialog.
let id = kOpenPaymentConfirmationEvent + "-" + this.getRandomId();
let detail = {
type: kOpenPaymentConfirmationEvent,
id: id,
paymentRequests: aRequests
};
// Once the user confirm the payment request and makes his choice, we get
// back to the DOM part to get the appropriate payment flow information
// based on the selected payment provider.
content.addEventListener("mozContentEvent", function handleSelection(evt) {
let msg = evt.detail;
if (msg.id != id) {
return;
}
if (msg.userSelection && aSuccessCb) {
aSuccessCb.onresult(aRequestId, msg.userSelection);
} else if (msg.errorMsg) {
_error(msg.errorMsg);
}
content.removeEventListener("mozContentEvent", handleSelection);
});
browser.shell.sendChromeEvent(detail);
},
showPaymentFlow: function showPaymentFlow(aRequestId,
aPaymentFlowInfo,
aErrorCb) {
let _error = function _error(errorMsg) {
if (aErrorCb) {
aErrorCb.onresult(aRequestId, errorMsg);
}
};
// We ask the UI to browse to the selected payment flow.
let browser = Services.wm.getMostRecentWindow("navigator:browser");
let content = browser.getContentWindow();
if (!content) {
_error("NO_CONTENT_WINDOW");
return;
}
let id = kOpenPaymentFlowEvent + "-" + this.getRandomId();
let detail = {
type: kOpenPaymentFlowEvent,
id: id,
uri: aPaymentFlowInfo.uri,
method: aPaymentFlowInfo.requestMethod,
jwt: aPaymentFlowInfo.jwt
};
// At some point the UI would send the created iframe back so the
// callbacks for firing DOMRequest events can be loaded on its
// content.
content.addEventListener("mozContentEvent", (function loadPaymentShim(evt) {
if (evt.detail.id != id) {
content.removeEventListener("mozContentEvent", loadPaymentShim);
return;
}
// Try to load the payment shim file containing the payment callbacks
// in the content script.
if (!evt.detail.frame && !evt.detail.errorMsg) {
_error("ERROR_LOADING_PAYMENT_SHIM");
return;
}
let frame = evt.detail.frame;
let frameLoader = frame.QueryInterface(Ci.nsIFrameLoaderOwner)
.frameLoader;
let mm = frameLoader.messageManager;
try {
mm.loadFrameScript(kPaymentShimFile, true);
mm.sendAsyncMessage("Payment:LoadShim", { requestId: aRequestId });
} catch (e) {
debug("Error loading " + kPaymentShimFile + " as a frame script: " + e);
_error("ERROR_LOADING_PAYMENT_SHIM");
} finally {
content.removeEventListener("mozContentEvent", loadPaymentShim);
}
}).bind(this));
// We also listen for UI notifications about a closed payment flow. The UI
// should provide the reason of the closure within the 'errorMsg' parameter
this._notifyPayFlowClosed = function _notifyPayFlowClosed (evt) {
if (evt.detail.id != id) {
return;
}
if (evt.detail.errorMsg) {
_error(evt.detail.errorMsg);
content.removeEventListener("mozContentEvent",
this._notifyPayFlowClosed);
return;
}
};
content.addEventListener("mozContentEvent",
this._notifyPayFlowClosed.bind(this));
browser.shell.sendChromeEvent(detail);
},
cleanup: function cleanup() {
let browser = Services.wm.getMostRecentWindow("navigator:browser");
let content = browser.getContentWindow();
if (!content) {
return;
}
content.removeEventListener("mozContentEvent", this._notifyPayFlowClosed);
},
getRandomId: function getRandomId() {
return uuidgen.generateUUID().toString();
},
classID: Components.ID("{8b83eabc-7929-47f4-8b48-4dea8d887e4b}"),
QueryInterface: XPCOMUtils.generateQI([Ci.nsIPaymentUIGlue])
}
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([PaymentUI]);