mirror of
https://github.com/Feodor2/Mypal68.git
synced 2025-06-18 14:55:44 -04:00
357 lines
10 KiB
JavaScript
357 lines
10 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/. */
|
|
|
|
/**
|
|
* Loaded in the unprivileged frame of each payment dialog.
|
|
*
|
|
* Communicates with privileged code via DOM Events.
|
|
*/
|
|
|
|
/* import-globals-from unprivileged-fallbacks.js */
|
|
|
|
var paymentRequest = {
|
|
_nextMessageID: 1,
|
|
domReadyPromise: null,
|
|
|
|
init() {
|
|
// listen to content
|
|
window.addEventListener("paymentChromeToContent", this);
|
|
|
|
window.addEventListener("keydown", this);
|
|
|
|
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");
|
|
},
|
|
|
|
handleEvent(event) {
|
|
switch (event.type) {
|
|
case "DOMContentLoaded": {
|
|
this.onPaymentRequestLoad();
|
|
break;
|
|
}
|
|
case "keydown": {
|
|
if (event.code != "KeyD" || !event.altKey || !event.ctrlKey) {
|
|
break;
|
|
}
|
|
this.toggleDebuggingConsole();
|
|
break;
|
|
}
|
|
case "unload": {
|
|
this.onPaymentRequestUnload();
|
|
break;
|
|
}
|
|
case "paymentChromeToContent": {
|
|
this.onChromeToContent(event);
|
|
break;
|
|
}
|
|
default: {
|
|
throw new Error("Unexpected event type");
|
|
}
|
|
}
|
|
},
|
|
|
|
/**
|
|
* @param {string} messageType
|
|
* @param {[object]} detail
|
|
* @returns {number} message ID to be able to identify a reply (where applicable).
|
|
*/
|
|
sendMessageToChrome(messageType, detail = {}) {
|
|
let messageID = this._nextMessageID++;
|
|
log.debug("sendMessageToChrome:", messageType, messageID, detail);
|
|
let event = new CustomEvent("paymentContentToChrome", {
|
|
bubbles: true,
|
|
detail: Object.assign(
|
|
{
|
|
messageType,
|
|
messageID,
|
|
},
|
|
detail
|
|
),
|
|
});
|
|
document.dispatchEvent(event);
|
|
return messageID;
|
|
},
|
|
|
|
toggleDebuggingConsole() {
|
|
let debuggingConsole = document.getElementById("debugging-console");
|
|
if (debuggingConsole.hidden && !debuggingConsole.src) {
|
|
debuggingConsole.src = "debugging.html";
|
|
}
|
|
debuggingConsole.hidden = !debuggingConsole.hidden;
|
|
},
|
|
|
|
onChromeToContent({ detail }) {
|
|
let { messageType } = detail;
|
|
log.debug("onChromeToContent:", messageType);
|
|
|
|
switch (messageType) {
|
|
case "responseSent": {
|
|
let { request } = document
|
|
.querySelector("payment-dialog")
|
|
.requestStore.getState();
|
|
document.querySelector("payment-dialog").requestStore.setState({
|
|
changesPrevented: true,
|
|
request: Object.assign({}, request, { completeStatus: "processing" }),
|
|
});
|
|
break;
|
|
}
|
|
case "showPaymentRequest": {
|
|
this.onShowPaymentRequest(detail);
|
|
break;
|
|
}
|
|
case "updateState": {
|
|
document.querySelector("payment-dialog").setStateFromParent(detail);
|
|
break;
|
|
}
|
|
}
|
|
},
|
|
|
|
onPaymentRequestLoad() {
|
|
log.debug("onPaymentRequestLoad");
|
|
window.addEventListener("unload", this, { once: true });
|
|
|
|
// Automatically show the debugging console if loaded with a truthy `debug` query parameter.
|
|
if (new URLSearchParams(location.search).get("debug")) {
|
|
this.toggleDebuggingConsole();
|
|
}
|
|
},
|
|
|
|
async onShowPaymentRequest(detail) {
|
|
// Handle getting called before the DOM is ready.
|
|
log.debug("onShowPaymentRequest:", detail);
|
|
await this.domReadyPromise;
|
|
|
|
log.debug("onShowPaymentRequest: domReadyPromise resolved");
|
|
log.debug("onShowPaymentRequest, isPrivate?", detail.isPrivate);
|
|
|
|
let paymentDialog = document.querySelector("payment-dialog");
|
|
let state = {
|
|
request: detail.request,
|
|
savedAddresses: detail.savedAddresses,
|
|
savedBasicCards: detail.savedBasicCards,
|
|
// Temp records can exist upon a reload during development.
|
|
tempAddresses: detail.tempAddresses,
|
|
tempBasicCards: detail.tempBasicCards,
|
|
isPrivate: detail.isPrivate,
|
|
page: {
|
|
id: "payment-summary",
|
|
},
|
|
};
|
|
|
|
let hasSavedAddresses = Object.keys(this.getAddresses(state)).length != 0;
|
|
let hasSavedCards = Object.keys(this.getBasicCards(state)).length != 0;
|
|
let shippingRequested = state.request.paymentOptions.requestShipping;
|
|
|
|
// Onboarding wizard flow.
|
|
if (!hasSavedAddresses && shippingRequested) {
|
|
state.page = {
|
|
id: "shipping-address-page",
|
|
onboardingWizard: true,
|
|
};
|
|
|
|
state["shipping-address-page"] = {
|
|
guid: null,
|
|
};
|
|
} else if (!hasSavedAddresses && !hasSavedCards) {
|
|
state.page = {
|
|
id: "billing-address-page",
|
|
onboardingWizard: true,
|
|
};
|
|
|
|
state["billing-address-page"] = {
|
|
guid: null,
|
|
};
|
|
} else if (!hasSavedCards) {
|
|
state.page = {
|
|
id: "basic-card-page",
|
|
onboardingWizard: true,
|
|
};
|
|
state["basic-card-page"] = {
|
|
selectedStateKey: "selectedPaymentCard",
|
|
};
|
|
}
|
|
|
|
await paymentDialog.setStateFromParent(state);
|
|
|
|
this.sendMessageToChrome("paymentDialogReady");
|
|
},
|
|
|
|
openPreferences() {
|
|
this.sendMessageToChrome("openPreferences");
|
|
},
|
|
|
|
cancel() {
|
|
this.sendMessageToChrome("paymentCancel");
|
|
},
|
|
|
|
pay(data) {
|
|
this.sendMessageToChrome("pay", data);
|
|
},
|
|
|
|
closeDialog() {
|
|
this.sendMessageToChrome("closeDialog");
|
|
},
|
|
|
|
changePaymentMethod(data) {
|
|
this.sendMessageToChrome("changePaymentMethod", data);
|
|
},
|
|
|
|
changeShippingAddress(data) {
|
|
this.sendMessageToChrome("changeShippingAddress", data);
|
|
},
|
|
|
|
changeShippingOption(data) {
|
|
this.sendMessageToChrome("changeShippingOption", data);
|
|
},
|
|
|
|
changePayerAddress(data) {
|
|
this.sendMessageToChrome("changePayerAddress", data);
|
|
},
|
|
|
|
/**
|
|
* Add/update an autofill storage record.
|
|
*
|
|
* If the the `guid` argument is provided update the record; otherwise, add it.
|
|
* @param {string} collectionName The autofill collection that record belongs to.
|
|
* @param {object} record The autofill record to add/update
|
|
* @param {string} [guid] The guid of the autofill record to update
|
|
* @returns {Promise} when the update response is received
|
|
*/
|
|
updateAutofillRecord(collectionName, record, guid) {
|
|
return new Promise((resolve, reject) => {
|
|
let messageID = this.sendMessageToChrome("updateAutofillRecord", {
|
|
collectionName,
|
|
guid,
|
|
record,
|
|
});
|
|
|
|
window.addEventListener("paymentChromeToContent", function onMsg({
|
|
detail,
|
|
}) {
|
|
if (
|
|
detail.messageType != "updateAutofillRecord:Response" ||
|
|
detail.messageID != messageID
|
|
) {
|
|
return;
|
|
}
|
|
log.debug("updateAutofillRecord: response:", detail);
|
|
window.removeEventListener("paymentChromeToContent", onMsg);
|
|
document
|
|
.querySelector("payment-dialog")
|
|
.setStateFromParent(detail.stateChange);
|
|
if (detail.error) {
|
|
reject(detail);
|
|
} else {
|
|
resolve(detail);
|
|
}
|
|
});
|
|
});
|
|
},
|
|
|
|
/**
|
|
* @param {object} state object representing the UI state
|
|
* @param {string} selectedMethodID (GUID) uniquely identifying the selected payment method
|
|
* @returns {object?} the applicable modifier for the payment method
|
|
*/
|
|
getModifierForPaymentMethod(state, selectedMethodID) {
|
|
let basicCards = this.getBasicCards(state);
|
|
let selectedMethod = basicCards[selectedMethodID] || null;
|
|
if (selectedMethod && selectedMethod.methodName !== "basic-card") {
|
|
throw new Error(
|
|
`${selectedMethod.methodName} (${selectedMethodID}) ` +
|
|
`is not a supported payment method`
|
|
);
|
|
}
|
|
let modifiers = state.request.paymentDetails.modifiers;
|
|
if (!selectedMethod || !modifiers || !modifiers.length) {
|
|
return null;
|
|
}
|
|
let appliedModifier = modifiers.find(modifier => {
|
|
// take the first matching modifier
|
|
if (
|
|
modifier.supportedMethods &&
|
|
modifier.supportedMethods != selectedMethod.methodName
|
|
) {
|
|
return false;
|
|
}
|
|
let supportedNetworks =
|
|
(modifier.data && modifier.data.supportedNetworks) || [];
|
|
return (
|
|
supportedNetworks.length == 0 ||
|
|
supportedNetworks.includes(selectedMethod["cc-type"])
|
|
);
|
|
});
|
|
return appliedModifier || null;
|
|
},
|
|
|
|
/**
|
|
* @param {object} state object representing the UI state
|
|
* @returns {object} in the shape of `nsIPaymentItem` representing the total
|
|
* that applies to the selected payment method.
|
|
*/
|
|
getTotalItem(state) {
|
|
let methodID = state.selectedPaymentCard;
|
|
if (methodID) {
|
|
let modifier = paymentRequest.getModifierForPaymentMethod(
|
|
state,
|
|
methodID
|
|
);
|
|
if (modifier && modifier.hasOwnProperty("total")) {
|
|
return modifier.total;
|
|
}
|
|
}
|
|
return state.request.paymentDetails.totalItem;
|
|
},
|
|
|
|
onPaymentRequestUnload() {
|
|
// remove listeners that may be used multiple times here
|
|
window.removeEventListener("paymentChromeToContent", this);
|
|
},
|
|
|
|
_sortObjectsByTimeLastUsed(objects) {
|
|
let sortedValues = Object.values(objects).sort((a, b) => {
|
|
let aLastUsed = a.timeLastUsed || a.timeLastModified;
|
|
let bLastUsed = b.timeLastUsed || b.timeLastModified;
|
|
return bLastUsed - aLastUsed;
|
|
});
|
|
let sortedObjects = {};
|
|
for (let obj of sortedValues) {
|
|
sortedObjects[obj.guid] = obj;
|
|
}
|
|
return sortedObjects;
|
|
},
|
|
|
|
getAddresses(state) {
|
|
let addresses = Object.assign(
|
|
{},
|
|
state.savedAddresses,
|
|
state.tempAddresses
|
|
);
|
|
return this._sortObjectsByTimeLastUsed(addresses);
|
|
},
|
|
|
|
getBasicCards(state) {
|
|
let cards = Object.assign({}, state.savedBasicCards, state.tempBasicCards);
|
|
return this._sortObjectsByTimeLastUsed(cards);
|
|
},
|
|
|
|
maybeCreateFieldErrorElement(container) {
|
|
let span = container.querySelector(".error-text");
|
|
if (!span) {
|
|
span = document.createElement("span");
|
|
span.className = "error-text";
|
|
container.appendChild(span);
|
|
}
|
|
return span;
|
|
},
|
|
};
|
|
|
|
paymentRequest.init();
|
|
|
|
export default paymentRequest;
|