forked from mirrors/gecko-dev
MozReview-Commit-ID: LjrRXr1thc8 --HG-- rename : toolkit/components/payments/.eslintrc.js => browser/components/payments/.eslintrc.js rename : toolkit/components/payments/content/paymentDialogFrameScript.js => browser/components/payments/content/paymentDialogFrameScript.js rename : toolkit/components/payments/content/paymentDialogWrapper.css => browser/components/payments/content/paymentDialogWrapper.css rename : toolkit/components/payments/content/paymentDialogWrapper.js => browser/components/payments/content/paymentDialogWrapper.js rename : toolkit/components/payments/content/paymentDialogWrapper.xhtml => browser/components/payments/content/paymentDialogWrapper.xhtml rename : toolkit/components/payments/docs/index.rst => browser/components/payments/docs/index.rst rename : toolkit/components/payments/jar.mn => browser/components/payments/jar.mn rename : toolkit/components/payments/moz.build => browser/components/payments/moz.build rename : toolkit/components/payments/paymentUIService.js => browser/components/payments/paymentUIService.js rename : toolkit/components/payments/payments.manifest => browser/components/payments/payments.manifest rename : toolkit/components/payments/res/PaymentsStore.js => browser/components/payments/res/PaymentsStore.js rename : toolkit/components/payments/res/components/address-option.css => browser/components/payments/res/components/address-option.css rename : toolkit/components/payments/res/components/address-option.js => browser/components/payments/res/components/address-option.js rename : toolkit/components/payments/res/components/basic-card-option.css => browser/components/payments/res/components/basic-card-option.css rename : toolkit/components/payments/res/components/basic-card-option.js => browser/components/payments/res/components/basic-card-option.js rename : toolkit/components/payments/res/components/currency-amount.js => browser/components/payments/res/components/currency-amount.js rename : toolkit/components/payments/res/components/labelled-checkbox.js => browser/components/payments/res/components/labelled-checkbox.js rename : toolkit/components/payments/res/components/payment-details-item.css => browser/components/payments/res/components/payment-details-item.css rename : toolkit/components/payments/res/components/payment-details-item.js => browser/components/payments/res/components/payment-details-item.js rename : toolkit/components/payments/res/components/rich-option.js => browser/components/payments/res/components/rich-option.js rename : toolkit/components/payments/res/components/rich-select.css => browser/components/payments/res/components/rich-select.css rename : toolkit/components/payments/res/components/rich-select.js => browser/components/payments/res/components/rich-select.js rename : toolkit/components/payments/res/components/shipping-option.css => browser/components/payments/res/components/shipping-option.css rename : toolkit/components/payments/res/components/shipping-option.js => browser/components/payments/res/components/shipping-option.js rename : toolkit/components/payments/res/containers/address-picker.js => browser/components/payments/res/containers/address-picker.js rename : toolkit/components/payments/res/containers/basic-card-form.js => browser/components/payments/res/containers/basic-card-form.js rename : toolkit/components/payments/res/containers/order-details.css => browser/components/payments/res/containers/order-details.css rename : toolkit/components/payments/res/containers/order-details.js => browser/components/payments/res/containers/order-details.js rename : toolkit/components/payments/res/containers/payment-dialog.js => browser/components/payments/res/containers/payment-dialog.js rename : toolkit/components/payments/res/containers/payment-method-picker.js => browser/components/payments/res/containers/payment-method-picker.js rename : toolkit/components/payments/res/containers/shipping-option-picker.js => browser/components/payments/res/containers/shipping-option-picker.js rename : toolkit/components/payments/res/debugging.css => browser/components/payments/res/debugging.css rename : toolkit/components/payments/res/debugging.html => browser/components/payments/res/debugging.html rename : toolkit/components/payments/res/debugging.js => browser/components/payments/res/debugging.js rename : toolkit/components/payments/res/mixins/ObservedPropertiesMixin.js => browser/components/payments/res/mixins/ObservedPropertiesMixin.js rename : toolkit/components/payments/res/mixins/PaymentStateSubscriberMixin.js => browser/components/payments/res/mixins/PaymentStateSubscriberMixin.js rename : toolkit/components/payments/res/paymentRequest.css => browser/components/payments/res/paymentRequest.css rename : toolkit/components/payments/res/paymentRequest.js => browser/components/payments/res/paymentRequest.js rename : toolkit/components/payments/res/paymentRequest.xhtml => browser/components/payments/res/paymentRequest.xhtml rename : toolkit/components/payments/res/unprivileged-fallbacks.js => browser/components/payments/res/unprivileged-fallbacks.js rename : toolkit/components/payments/res/vendor/custom-elements.min.js => browser/components/payments/res/vendor/custom-elements.min.js rename : toolkit/components/payments/res/vendor/custom-elements.min.js.map => browser/components/payments/res/vendor/custom-elements.min.js.map rename : toolkit/components/payments/server.py => browser/components/payments/server.py rename : toolkit/components/payments/test/PaymentTestUtils.jsm => browser/components/payments/test/PaymentTestUtils.jsm rename : toolkit/components/payments/test/browser/.eslintrc.js => browser/components/payments/test/browser/.eslintrc.js rename : toolkit/components/payments/test/browser/blank_page.html => browser/components/payments/test/browser/blank_page.html rename : toolkit/components/payments/test/browser/browser.ini => browser/components/payments/test/browser/browser.ini rename : toolkit/components/payments/test/browser/browser_card_edit.js => browser/components/payments/test/browser/browser_card_edit.js rename : toolkit/components/payments/test/browser/browser_change_shipping.js => browser/components/payments/test/browser/browser_change_shipping.js rename : toolkit/components/payments/test/browser/browser_host_name.js => browser/components/payments/test/browser/browser_host_name.js rename : toolkit/components/payments/test/browser/browser_profile_storage.js => browser/components/payments/test/browser/browser_profile_storage.js rename : toolkit/components/payments/test/browser/browser_request_serialization.js => browser/components/payments/test/browser/browser_request_serialization.js rename : toolkit/components/payments/test/browser/browser_request_shipping.js => browser/components/payments/test/browser/browser_request_shipping.js rename : toolkit/components/payments/test/browser/browser_request_summary.js => browser/components/payments/test/browser/browser_request_summary.js rename : toolkit/components/payments/test/browser/browser_shippingaddresschange_error.js => browser/components/payments/test/browser/browser_shippingaddresschange_error.js rename : toolkit/components/payments/test/browser/browser_show_dialog.js => browser/components/payments/test/browser/browser_show_dialog.js rename : toolkit/components/payments/test/browser/browser_total.js => browser/components/payments/test/browser/browser_total.js rename : toolkit/components/payments/test/browser/head.js => browser/components/payments/test/browser/head.js rename : toolkit/components/payments/test/mochitest/.eslintrc.js => browser/components/payments/test/mochitest/.eslintrc.js rename : toolkit/components/payments/test/mochitest/formautofill/mochitest.ini => browser/components/payments/test/mochitest/formautofill/mochitest.ini rename : toolkit/components/payments/test/mochitest/formautofill/test_editCreditCard.html => browser/components/payments/test/mochitest/formautofill/test_editCreditCard.html rename : toolkit/components/payments/test/mochitest/mochitest.ini => browser/components/payments/test/mochitest/mochitest.ini rename : toolkit/components/payments/test/mochitest/payments_common.js => browser/components/payments/test/mochitest/payments_common.js rename : toolkit/components/payments/test/mochitest/test_ObservedPropertiesMixin.html => browser/components/payments/test/mochitest/test_ObservedPropertiesMixin.html rename : toolkit/components/payments/test/mochitest/test_PaymentStateSubscriberMixin.html => browser/components/payments/test/mochitest/test_PaymentStateSubscriberMixin.html rename : toolkit/components/payments/test/mochitest/test_PaymentsStore.html => browser/components/payments/test/mochitest/test_PaymentsStore.html rename : toolkit/components/payments/test/mochitest/test_address_picker.html => browser/components/payments/test/mochitest/test_address_picker.html rename : toolkit/components/payments/test/mochitest/test_basic_card_form.html => browser/components/payments/test/mochitest/test_basic_card_form.html rename : toolkit/components/payments/test/mochitest/test_currency_amount.html => browser/components/payments/test/mochitest/test_currency_amount.html rename : toolkit/components/payments/test/mochitest/test_labelled_checkbox.html => browser/components/payments/test/mochitest/test_labelled_checkbox.html rename : toolkit/components/payments/test/mochitest/test_order_details.html => browser/components/payments/test/mochitest/test_order_details.html rename : toolkit/components/payments/test/mochitest/test_payer_address_picker.html => browser/components/payments/test/mochitest/test_payer_address_picker.html rename : toolkit/components/payments/test/mochitest/test_payment_details_item.html => browser/components/payments/test/mochitest/test_payment_details_item.html rename : toolkit/components/payments/test/mochitest/test_payment_dialog.html => browser/components/payments/test/mochitest/test_payment_dialog.html rename : toolkit/components/payments/test/mochitest/test_payment_method_picker.html => browser/components/payments/test/mochitest/test_payment_method_picker.html rename : toolkit/components/payments/test/mochitest/test_rich_select.html => browser/components/payments/test/mochitest/test_rich_select.html rename : toolkit/components/payments/test/mochitest/test_shipping_option_picker.html => browser/components/payments/test/mochitest/test_shipping_option_picker.html rename : toolkit/components/payments/test/unit/.eslintrc.js => browser/components/payments/test/unit/.eslintrc.js rename : toolkit/components/payments/test/unit/head.js => browser/components/payments/test/unit/head.js rename : toolkit/components/payments/test/unit/test_response_creation.js => browser/components/payments/test/unit/test_response_creation.js rename : toolkit/components/payments/test/unit/xpcshell.ini => browser/components/payments/test/unit/xpcshell.ini
587 lines
18 KiB
JavaScript
587 lines
18 KiB
JavaScript
/* 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/. */
|
|
|
|
/**
|
|
* Runs in the privileged outer dialog. Each dialog loads this script in its
|
|
* own scope.
|
|
*/
|
|
|
|
"use strict";
|
|
|
|
const paymentSrv = Cc["@mozilla.org/dom/payments/payment-request-service;1"]
|
|
.getService(Ci.nsIPaymentRequestService);
|
|
|
|
ChromeUtils.import("resource://gre/modules/Services.jsm");
|
|
ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
|
|
|
|
ChromeUtils.defineModuleGetter(this, "MasterPassword",
|
|
"resource://formautofill/MasterPassword.jsm");
|
|
ChromeUtils.defineModuleGetter(this, "PrivateBrowsingUtils",
|
|
"resource://gre/modules/PrivateBrowsingUtils.jsm");
|
|
|
|
XPCOMUtils.defineLazyGetter(this, "formAutofillStorage", () => {
|
|
let storage;
|
|
try {
|
|
storage = ChromeUtils.import("resource://formautofill/FormAutofillStorage.jsm", {})
|
|
.formAutofillStorage;
|
|
storage.initialize();
|
|
} catch (ex) {
|
|
storage = null;
|
|
Cu.reportError(ex);
|
|
}
|
|
|
|
return storage;
|
|
});
|
|
|
|
var paymentDialogWrapper = {
|
|
componentsLoaded: new Map(),
|
|
frame: null,
|
|
mm: null,
|
|
request: null,
|
|
|
|
QueryInterface: XPCOMUtils.generateQI([
|
|
Ci.nsIObserver,
|
|
Ci.nsISupportsWeakReference,
|
|
]),
|
|
|
|
/**
|
|
* Note: This method is async because formAutofillStorage plans to become async.
|
|
*
|
|
* @param {string} guid
|
|
* @returns {object} containing only the requested payer values.
|
|
*/
|
|
async _convertProfileAddressToPayerData(guid) {
|
|
let addressData = formAutofillStorage.addresses.get(guid);
|
|
if (!addressData) {
|
|
throw new Error(`Payer address not found: ${guid}`);
|
|
}
|
|
|
|
let {
|
|
requestPayerName,
|
|
requestPayerEmail,
|
|
requestPayerPhone,
|
|
} = this.request.paymentOptions;
|
|
|
|
let payerData = {
|
|
payerName: requestPayerName ? addressData.name : "",
|
|
payerEmail: requestPayerEmail ? addressData.email : "",
|
|
payerPhone: requestPayerPhone ? addressData.tel : "",
|
|
};
|
|
|
|
return payerData;
|
|
},
|
|
|
|
/**
|
|
* Note: This method is async because formAutofillStorage plans to become async.
|
|
*
|
|
* @param {string} guid
|
|
* @returns {nsIPaymentAddress}
|
|
*/
|
|
async _convertProfileAddressToPaymentAddress(guid) {
|
|
let addressData = formAutofillStorage.addresses.get(guid);
|
|
if (!addressData) {
|
|
throw new Error(`Shipping address not found: ${guid}`);
|
|
}
|
|
|
|
let address = this.createPaymentAddress({
|
|
country: addressData.country,
|
|
addressLines: addressData["street-address"].split("\n"),
|
|
region: addressData["address-level1"],
|
|
city: addressData["address-level2"],
|
|
postalCode: addressData["postal-code"],
|
|
organization: addressData.organization,
|
|
recipient: addressData.name,
|
|
phone: addressData.tel,
|
|
});
|
|
|
|
return address;
|
|
},
|
|
|
|
/**
|
|
* @param {string} guid The GUID of the basic card record from storage.
|
|
* @param {string} cardSecurityCode The associated card security code (CVV/CCV/etc.)
|
|
* @throws if the user cancels entering their master password or an error decrypting
|
|
* @returns {nsIBasicCardResponseData?} returns response data or null (if the
|
|
* master password dialog was cancelled);
|
|
*/
|
|
async _convertProfileBasicCardToPaymentMethodData(guid, cardSecurityCode) {
|
|
let cardData = formAutofillStorage.creditCards.get(guid);
|
|
if (!cardData) {
|
|
throw new Error(`Basic card not found in storage: ${guid}`);
|
|
}
|
|
|
|
let cardNumber;
|
|
try {
|
|
cardNumber = await MasterPassword.decrypt(cardData["cc-number-encrypted"], true);
|
|
} catch (ex) {
|
|
if (ex.result != Cr.NS_ERROR_ABORT) {
|
|
throw ex;
|
|
}
|
|
// User canceled master password entry
|
|
return null;
|
|
}
|
|
|
|
let billingAddressGUID = cardData.billingAddressGUID;
|
|
let billingAddress;
|
|
try {
|
|
billingAddress = await this._convertProfileAddressToPaymentAddress(billingAddressGUID);
|
|
} catch (ex) {
|
|
// The referenced address may not exist if it was deleted or hasn't yet synced to this profile
|
|
Cu.reportError(ex);
|
|
}
|
|
let methodData = this.createBasicCardResponseData({
|
|
cardholderName: cardData["cc-name"],
|
|
cardNumber,
|
|
expiryMonth: cardData["cc-exp-month"].toString().padStart(2, "0"),
|
|
expiryYear: cardData["cc-exp-year"].toString(),
|
|
cardSecurityCode,
|
|
billingAddress,
|
|
});
|
|
|
|
return methodData;
|
|
},
|
|
|
|
init(requestId, frame) {
|
|
if (!requestId || typeof(requestId) != "string") {
|
|
throw new Error("Invalid PaymentRequest ID");
|
|
}
|
|
|
|
// The Request object returned by the Payment Service is live and
|
|
// will automatically get updated if event.updateWith is used.
|
|
this.request = paymentSrv.getPaymentRequestById(requestId);
|
|
|
|
if (!this.request) {
|
|
throw new Error(`PaymentRequest not found: ${requestId}`);
|
|
}
|
|
|
|
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({
|
|
acceptStatus,
|
|
methodName = "",
|
|
methodData = null,
|
|
payerName = "",
|
|
payerEmail = "",
|
|
payerPhone = "",
|
|
}) {
|
|
let showResponse = this.createComponentInstance(Ci.nsIPaymentShowActionResponse);
|
|
|
|
showResponse.init(this.request.requestId,
|
|
acceptStatus,
|
|
methodName,
|
|
methodData,
|
|
payerName,
|
|
payerEmail,
|
|
payerPhone);
|
|
return showResponse;
|
|
},
|
|
|
|
createBasicCardResponseData({
|
|
cardholderName = "",
|
|
cardNumber,
|
|
expiryMonth = "",
|
|
expiryYear = "",
|
|
cardSecurityCode = "",
|
|
billingAddress = null,
|
|
}) {
|
|
const basicCardResponseData = Cc["@mozilla.org/dom/payments/basiccard-response-data;1"]
|
|
.createInstance(Ci.nsIBasicCardResponseData);
|
|
basicCardResponseData.initData(cardholderName,
|
|
cardNumber,
|
|
expiryMonth,
|
|
expiryYear,
|
|
cardSecurityCode,
|
|
billingAddress);
|
|
return basicCardResponseData;
|
|
},
|
|
|
|
createPaymentAddress({
|
|
country = "",
|
|
addressLines = [],
|
|
region = "",
|
|
city = "",
|
|
dependentLocality = "",
|
|
postalCode = "",
|
|
sortingCode = "",
|
|
languageCode = "",
|
|
organization = "",
|
|
recipient = "",
|
|
phone = "",
|
|
}) {
|
|
const paymentAddress = Cc["@mozilla.org/dom/payments/payment-address;1"]
|
|
.createInstance(Ci.nsIPaymentAddress);
|
|
const addressLine = Cc["@mozilla.org/array;1"].createInstance(Ci.nsIMutableArray);
|
|
for (let line of addressLines) {
|
|
const address = Cc["@mozilla.org/supports-string;1"].createInstance(Ci.nsISupportsString);
|
|
address.data = line;
|
|
addressLine.appendElement(address);
|
|
}
|
|
paymentAddress.init(country,
|
|
addressLine,
|
|
region,
|
|
city,
|
|
dependentLocality,
|
|
postalCode,
|
|
sortingCode,
|
|
languageCode,
|
|
organization,
|
|
recipient,
|
|
phone);
|
|
return paymentAddress;
|
|
},
|
|
|
|
createComponentInstance(componentInterface) {
|
|
let componentName;
|
|
switch (componentInterface) {
|
|
case Ci.nsIPaymentShowActionResponse: {
|
|
componentName = "@mozilla.org/dom/payments/payment-show-action-response;1";
|
|
break;
|
|
}
|
|
case Ci.nsIGeneralResponseData: {
|
|
componentName = "@mozilla.org/dom/payments/general-response-data;1";
|
|
break;
|
|
}
|
|
}
|
|
let component = this.componentsLoaded.get(componentName);
|
|
|
|
if (!component) {
|
|
component = Cc[componentName];
|
|
this.componentsLoaded.set(componentName, component);
|
|
}
|
|
|
|
return component.createInstance(componentInterface);
|
|
},
|
|
|
|
fetchSavedAddresses() {
|
|
let savedAddresses = {};
|
|
for (let address of formAutofillStorage.addresses.getAll()) {
|
|
savedAddresses[address.guid] = address;
|
|
}
|
|
return savedAddresses;
|
|
},
|
|
|
|
fetchSavedPaymentCards() {
|
|
let savedBasicCards = {};
|
|
for (let card of formAutofillStorage.creditCards.getAll()) {
|
|
savedBasicCards[card.guid] = card;
|
|
// Filter out the encrypted card number since the dialog content is
|
|
// considered untrusted and runs in a content process.
|
|
delete card["cc-number-encrypted"];
|
|
|
|
// ensure each card has a methodName property
|
|
if (!card.methodName) {
|
|
card.methodName = "basic-card";
|
|
}
|
|
}
|
|
return savedBasicCards;
|
|
},
|
|
|
|
onAutofillStorageChange() {
|
|
this.sendMessageToContent("updateState", {
|
|
savedAddresses: this.fetchSavedAddresses(),
|
|
savedBasicCards: this.fetchSavedPaymentCards(),
|
|
});
|
|
},
|
|
|
|
sendMessageToContent(messageType, data = {}) {
|
|
this.mm.sendAsyncMessage("paymentChromeToContent", {
|
|
data,
|
|
messageType,
|
|
});
|
|
},
|
|
|
|
updateRequest() {
|
|
// There is no need to update this.request since the object is live
|
|
// and will automatically get updated if event.updateWith is used.
|
|
let requestSerialized = this._serializeRequest(this.request);
|
|
|
|
this.sendMessageToContent("updateState", {
|
|
request: requestSerialized,
|
|
});
|
|
},
|
|
|
|
/**
|
|
* Recursively convert and filter input to the subset of data types supported by JSON
|
|
*
|
|
* @param {*} value - any type of input to serialize
|
|
* @param {string?} name - name or key associated with this input.
|
|
* E.g. property name or array index.
|
|
* @returns {*} serialized deep copy of the value
|
|
*/
|
|
_serializeRequest(value, name = null) {
|
|
// Primitives: String, Number, Boolean, null
|
|
let type = typeof value;
|
|
if (value === null ||
|
|
type == "string" ||
|
|
type == "number" ||
|
|
type == "boolean") {
|
|
return value;
|
|
}
|
|
if (name == "topLevelPrincipal") {
|
|
// Manually serialize the nsIPrincipal.
|
|
let displayHost = value.URI.displayHost;
|
|
return {
|
|
URI: {
|
|
displayHost,
|
|
},
|
|
};
|
|
}
|
|
if (type == "function" || type == "undefined") {
|
|
return undefined;
|
|
}
|
|
// Structures: nsIArray
|
|
if (value instanceof Ci.nsIArray) {
|
|
let iface;
|
|
let items = [];
|
|
switch (name) {
|
|
case "displayItems": // falls through
|
|
case "additionalDisplayItems":
|
|
iface = Ci.nsIPaymentItem;
|
|
break;
|
|
case "shippingOptions":
|
|
iface = Ci.nsIPaymentShippingOption;
|
|
break;
|
|
case "paymentMethods":
|
|
iface = Ci.nsIPaymentMethodData;
|
|
break;
|
|
case "modifiers":
|
|
iface = Ci.nsIPaymentDetailsModifier;
|
|
break;
|
|
}
|
|
if (!iface) {
|
|
throw new Error(`No interface associated with the members of the ${name} nsIArray`);
|
|
}
|
|
for (let i = 0; i < value.length; i++) {
|
|
let item = value.queryElementAt(i, iface);
|
|
let result = this._serializeRequest(item, i);
|
|
if (result !== undefined) {
|
|
items.push(result);
|
|
}
|
|
}
|
|
return items;
|
|
}
|
|
// Structures: Arrays
|
|
if (Array.isArray(value)) {
|
|
let items = value.map(item => { this._serializeRequest(item); })
|
|
.filter(item => item !== undefined);
|
|
return items;
|
|
}
|
|
// Structures: Objects
|
|
let obj = {};
|
|
for (let [key, item] of Object.entries(value)) {
|
|
let result = this._serializeRequest(item, key);
|
|
if (result !== undefined) {
|
|
obj[key] = result;
|
|
}
|
|
}
|
|
return obj;
|
|
},
|
|
|
|
initializeFrame() {
|
|
let requestSerialized = this._serializeRequest(this.request);
|
|
let chromeWindow = Services.wm.getMostRecentWindow("navigator:browser");
|
|
let isPrivate = PrivateBrowsingUtils.isWindowPrivate(chromeWindow);
|
|
|
|
this.sendMessageToContent("showPaymentRequest", {
|
|
request: requestSerialized,
|
|
savedAddresses: this.fetchSavedAddresses(),
|
|
savedBasicCards: this.fetchSavedPaymentCards(),
|
|
isPrivate,
|
|
});
|
|
|
|
Services.obs.addObserver(this, "formautofill-storage-changed", true);
|
|
},
|
|
|
|
debugFrame() {
|
|
// To avoid self-XSS-type attacks, ensure that Browser Chrome debugging is enabled.
|
|
if (!Services.prefs.getBoolPref("devtools.chrome.enabled", false)) {
|
|
Cu.reportError("devtools.chrome.enabled must be enabled to debug the frame");
|
|
return;
|
|
}
|
|
let chromeWindow = Services.wm.getMostRecentWindow(null);
|
|
let {
|
|
gDevToolsBrowser,
|
|
} = ChromeUtils.import("resource://devtools/client/framework/gDevTools.jsm", {});
|
|
gDevToolsBrowser.openContentProcessToolbox({
|
|
selectedBrowser: chromeWindow.document.getElementById("paymentRequestFrame").frameLoader,
|
|
});
|
|
},
|
|
|
|
onPaymentCancel() {
|
|
const showResponse = this.createShowResponse({
|
|
acceptStatus: Ci.nsIPaymentActionResponse.PAYMENT_REJECTED,
|
|
});
|
|
paymentSrv.respondPayment(showResponse);
|
|
window.close();
|
|
},
|
|
|
|
async onPay({
|
|
selectedPayerAddressGUID: payerGUID,
|
|
selectedPaymentCardGUID: paymentCardGUID,
|
|
selectedPaymentCardSecurityCode: cardSecurityCode,
|
|
}) {
|
|
let methodData = await this._convertProfileBasicCardToPaymentMethodData(paymentCardGUID,
|
|
cardSecurityCode);
|
|
|
|
if (!methodData) {
|
|
// TODO (Bug 1429265/Bug 1429205): Handle when a user hits cancel on the
|
|
// Master Password dialog.
|
|
Cu.reportError("Bug 1429265/Bug 1429205: User canceled master password entry");
|
|
return;
|
|
}
|
|
|
|
let {
|
|
payerName,
|
|
payerEmail,
|
|
payerPhone,
|
|
} = await this._convertProfileAddressToPayerData(payerGUID);
|
|
|
|
this.pay({
|
|
methodName: "basic-card",
|
|
methodData,
|
|
payerName,
|
|
payerEmail,
|
|
payerPhone,
|
|
});
|
|
},
|
|
|
|
pay({
|
|
payerName,
|
|
payerEmail,
|
|
payerPhone,
|
|
methodName,
|
|
methodData,
|
|
}) {
|
|
const showResponse = this.createShowResponse({
|
|
acceptStatus: Ci.nsIPaymentActionResponse.PAYMENT_ACCEPTED,
|
|
payerName,
|
|
payerEmail,
|
|
payerPhone,
|
|
methodName,
|
|
methodData,
|
|
});
|
|
paymentSrv.respondPayment(showResponse);
|
|
this.sendMessageToContent("responseSent");
|
|
},
|
|
|
|
async onChangeShippingAddress({shippingAddressGUID}) {
|
|
let address = await this._convertProfileAddressToPaymentAddress(shippingAddressGUID);
|
|
paymentSrv.changeShippingAddress(this.request.requestId, address);
|
|
},
|
|
|
|
onChangeShippingOption({optionID}) {
|
|
// Note, failing here on browser_host_name.js because the test closes
|
|
// the dialog before the onChangeShippingOption is called, thus
|
|
// deleting the request and making the requestId invalid. Unclear
|
|
// why we aren't seeing the same issue with onChangeShippingAddress.
|
|
paymentSrv.changeShippingOption(this.request.requestId, optionID);
|
|
},
|
|
|
|
async onUpdateAutofillRecord(collectionName, record, guid, {
|
|
errorStateChange,
|
|
preserveOldProperties,
|
|
selectedStateKey,
|
|
successStateChange,
|
|
}) {
|
|
if (collectionName == "creditCards" && !guid) {
|
|
// We need to be logged in so we can encrypt the credit card number and
|
|
// that's only supported when we're adding a new record.
|
|
// TODO: "MasterPassword.ensureLoggedIn" can be removed after the storage
|
|
// APIs are refactored to be async functions (bug 1399367).
|
|
if (!await MasterPassword.ensureLoggedIn()) {
|
|
Cu.reportError("User canceled master password entry");
|
|
return;
|
|
}
|
|
}
|
|
|
|
try {
|
|
if (guid) {
|
|
await formAutofillStorage[collectionName].update(guid, record, preserveOldProperties);
|
|
} else {
|
|
guid = await formAutofillStorage[collectionName].add(record);
|
|
}
|
|
|
|
// Select the new record
|
|
if (selectedStateKey) {
|
|
Object.assign(successStateChange, {
|
|
[selectedStateKey]: guid,
|
|
});
|
|
}
|
|
|
|
this.sendMessageToContent("updateState", successStateChange);
|
|
} catch (ex) {
|
|
this.sendMessageToContent("updateState", errorStateChange);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* @implements {nsIObserver}
|
|
* @param {nsISupports} subject
|
|
* @param {string} topic
|
|
* @param {string} data
|
|
*/
|
|
observe(subject, topic, data) {
|
|
switch (topic) {
|
|
case "formautofill-storage-changed": {
|
|
if (data == "notifyUsed") {
|
|
break;
|
|
}
|
|
this.onAutofillStorageChange();
|
|
break;
|
|
}
|
|
}
|
|
},
|
|
|
|
receiveMessage({data}) {
|
|
let {messageType} = data;
|
|
|
|
switch (messageType) {
|
|
case "debugFrame": {
|
|
this.debugFrame();
|
|
break;
|
|
}
|
|
case "initializeRequest": {
|
|
this.initializeFrame();
|
|
break;
|
|
}
|
|
case "changeShippingAddress": {
|
|
this.onChangeShippingAddress(data);
|
|
break;
|
|
}
|
|
case "changeShippingOption": {
|
|
this.onChangeShippingOption(data);
|
|
break;
|
|
}
|
|
case "paymentCancel": {
|
|
this.onPaymentCancel();
|
|
break;
|
|
}
|
|
case "pay": {
|
|
this.onPay(data);
|
|
break;
|
|
}
|
|
case "updateAutofillRecord": {
|
|
this.onUpdateAutofillRecord(data.collectionName, data.record, data.guid, {
|
|
errorStateChange: data.errorStateChange,
|
|
preserveOldProperties: data.preserveOldProperties,
|
|
selectedStateKey: data.selectedStateKey,
|
|
successStateChange: data.successStateChange,
|
|
});
|
|
break;
|
|
}
|
|
}
|
|
},
|
|
};
|
|
|
|
if ("document" in this) {
|
|
// Running in a browser, not a unit test
|
|
let frame = document.getElementById("paymentRequestFrame");
|
|
let requestId = (new URLSearchParams(window.location.search)).get("requestId");
|
|
paymentDialogWrapper.init(requestId, frame);
|
|
}
|