improve backend / content script messaging
This commit is contained in:
parent
04a7800bc8
commit
87f981d91c
@ -21,7 +21,6 @@
|
|||||||
* to interact with the GNU Taler wallet via DOM Events.
|
* to interact with the GNU Taler wallet via DOM Events.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Imports.
|
* Imports.
|
||||||
*/
|
*/
|
||||||
@ -48,55 +47,6 @@ interface Handler {
|
|||||||
}
|
}
|
||||||
const handlers: Handler[] = [];
|
const handlers: Handler[] = [];
|
||||||
|
|
||||||
function queryPayment(url: string): Promise<any> {
|
|
||||||
const walletMsg = {
|
|
||||||
detail: { url },
|
|
||||||
type: "query-payment",
|
|
||||||
};
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
chrome.runtime.sendMessage(walletMsg, (resp: any) => {
|
|
||||||
resolve(resp);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function putHistory(historyEntry: any): Promise<void> {
|
|
||||||
const walletMsg = {
|
|
||||||
detail: {
|
|
||||||
historyEntry,
|
|
||||||
},
|
|
||||||
type: "put-history-entry",
|
|
||||||
};
|
|
||||||
return new Promise<void>((resolve, reject) => {
|
|
||||||
chrome.runtime.sendMessage(walletMsg, (resp: any) => {
|
|
||||||
resolve();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function saveOffer(offer: any): Promise<number> {
|
|
||||||
const walletMsg = {
|
|
||||||
detail: {
|
|
||||||
offer: {
|
|
||||||
H_contract: offer.hash,
|
|
||||||
contract: offer.data,
|
|
||||||
merchant_sig: offer.sig,
|
|
||||||
offer_time: new Date().getTime() / 1000,
|
|
||||||
},
|
|
||||||
type: "save-offer",
|
|
||||||
},
|
|
||||||
};
|
|
||||||
return new Promise<number>((resolve, reject) => {
|
|
||||||
chrome.runtime.sendMessage(walletMsg, (resp: any) => {
|
|
||||||
if (resp && resp.error) {
|
|
||||||
reject(resp);
|
|
||||||
} else {
|
|
||||||
resolve(resp);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
let sheet: CSSStyleSheet|null;
|
let sheet: CSSStyleSheet|null;
|
||||||
|
|
||||||
@ -153,7 +103,7 @@ function handlePaymentResponse(walletResp: any) {
|
|||||||
* Try to notify the wallet first, before we show a potentially
|
* Try to notify the wallet first, before we show a potentially
|
||||||
* synchronous error message (such as an alert) or leave the page.
|
* synchronous error message (such as an alert) or leave the page.
|
||||||
*/
|
*/
|
||||||
function handleFailedPayment(r: XMLHttpRequest) {
|
async function handleFailedPayment(r: XMLHttpRequest) {
|
||||||
let timeoutHandle: number|null = null;
|
let timeoutHandle: number|null = null;
|
||||||
function err() {
|
function err() {
|
||||||
// FIXME: proper error reporting!
|
// FIXME: proper error reporting!
|
||||||
@ -165,13 +115,12 @@ function handlePaymentResponse(walletResp: any) {
|
|||||||
}
|
}
|
||||||
timeoutHandle = window.setTimeout(onTimeout, 200);
|
timeoutHandle = window.setTimeout(onTimeout, 200);
|
||||||
|
|
||||||
talerPaymentFailed(walletResp.H_contract).then(() => {
|
await wxApi.paymentFailed(walletResp.H_contract);
|
||||||
if (timeoutHandle !== null) {
|
if (timeoutHandle !== null) {
|
||||||
clearTimeout(timeoutHandle);
|
clearTimeout(timeoutHandle);
|
||||||
timeoutHandle = null;
|
timeoutHandle = null;
|
||||||
}
|
}
|
||||||
err();
|
err();
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
logVerbose && console.log("handling taler-notify-payment: ", walletResp);
|
logVerbose && console.log("handling taler-notify-payment: ", walletResp);
|
||||||
@ -185,7 +134,7 @@ function handlePaymentResponse(walletResp: any) {
|
|||||||
r.open("post", walletResp.contract.pay_url);
|
r.open("post", walletResp.contract.pay_url);
|
||||||
r.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
|
r.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
|
||||||
r.send(JSON.stringify(walletResp.payReq));
|
r.send(JSON.stringify(walletResp.payReq));
|
||||||
r.onload = () => {
|
r.onload = async () => {
|
||||||
if (!r) {
|
if (!r) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -193,12 +142,11 @@ function handlePaymentResponse(walletResp: any) {
|
|||||||
case 200:
|
case 200:
|
||||||
const merchantResp = JSON.parse(r.responseText);
|
const merchantResp = JSON.parse(r.responseText);
|
||||||
logVerbose && console.log("got success from pay_url");
|
logVerbose && console.log("got success from pay_url");
|
||||||
talerPaymentSucceeded({H_contract: walletResp.H_contract, merchantSig: merchantResp.sig}).then(() => {
|
await wxApi.paymentSucceeded(walletResp.H_contract, merchantResp.sig);
|
||||||
const nextUrl = walletResp.contract.fulfillment_url;
|
const nextUrl = walletResp.contract.fulfillment_url;
|
||||||
logVerbose && console.log("taler-payment-succeeded done, going to", nextUrl);
|
logVerbose && console.log("taler-payment-succeeded done, going to", nextUrl);
|
||||||
window.location.href = nextUrl;
|
window.location.href = nextUrl;
|
||||||
window.location.reload(true);
|
window.location.reload(true);
|
||||||
});
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
handleFailedPayment(r);
|
handleFailedPayment(r);
|
||||||
@ -226,6 +174,8 @@ function handlePaymentResponse(walletResp: any) {
|
|||||||
|
|
||||||
|
|
||||||
function init() {
|
function init() {
|
||||||
|
// Only place where we don't use the nicer RPC wrapper, since the wallet
|
||||||
|
// backend might not be ready (during install, upgrade, etc.)
|
||||||
chrome.runtime.sendMessage({type: "get-tab-cookie"}, (resp) => {
|
chrome.runtime.sendMessage({type: "get-tab-cookie"}, (resp) => {
|
||||||
if (chrome.runtime.lastError) {
|
if (chrome.runtime.lastError) {
|
||||||
logVerbose && console.log("extension not yet ready");
|
logVerbose && console.log("extension not yet ready");
|
||||||
@ -267,17 +217,6 @@ function init() {
|
|||||||
|
|
||||||
type HandlerFn = (detail: any, sendResponse: (msg: any) => void) => void;
|
type HandlerFn = (detail: any, sendResponse: (msg: any) => void) => void;
|
||||||
|
|
||||||
function generateNonce(): Promise<string> {
|
|
||||||
const walletMsg = {
|
|
||||||
type: "generate-nonce",
|
|
||||||
};
|
|
||||||
return new Promise<string>((resolve, reject) => {
|
|
||||||
chrome.runtime.sendMessage(walletMsg, (resp: any) => {
|
|
||||||
resolve(resp);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function downloadContract(url: string, nonce: string): Promise<any> {
|
function downloadContract(url: string, nonce: string): Promise<any> {
|
||||||
const parsed_url = new URI(url);
|
const parsed_url = new URI(url);
|
||||||
url = parsed_url.setQuery({nonce}).href();
|
url = parsed_url.setQuery({nonce}).href();
|
||||||
@ -361,8 +300,8 @@ async function processProposal(proposal: any) {
|
|||||||
timestamp: (new Date()).getTime(),
|
timestamp: (new Date()).getTime(),
|
||||||
type: "offer-contract",
|
type: "offer-contract",
|
||||||
};
|
};
|
||||||
await putHistory(historyEntry);
|
await wxApi.putHistory(historyEntry);
|
||||||
const offerId = await saveOffer(proposal);
|
const offerId = await wxApi.saveOffer(proposal);
|
||||||
|
|
||||||
const uri = new URI(chrome.extension.getURL(
|
const uri = new URI(chrome.extension.getURL(
|
||||||
"/src/webex/pages/confirm-contract.html"));
|
"/src/webex/pages/confirm-contract.html"));
|
||||||
@ -377,14 +316,14 @@ function talerPay(msg: any): Promise<any> {
|
|||||||
return new Promise(async(resolve, reject) => {
|
return new Promise(async(resolve, reject) => {
|
||||||
// current URL without fragment
|
// current URL without fragment
|
||||||
const url = new URI(document.location.href).fragment("").href();
|
const url = new URI(document.location.href).fragment("").href();
|
||||||
const res = await queryPayment(url);
|
const res = await wxApi.queryPayment(url);
|
||||||
logVerbose && console.log("taler-pay: got response", res);
|
logVerbose && console.log("taler-pay: got response", res);
|
||||||
if (res && res.payReq) {
|
if (res && res.payReq) {
|
||||||
resolve(res);
|
resolve(res);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (msg.contract_url) {
|
if (msg.contract_url) {
|
||||||
const nonce = await generateNonce();
|
const nonce = await wxApi.generateNonce();
|
||||||
const proposal = await downloadContract(msg.contract_url, nonce);
|
const proposal = await downloadContract(msg.contract_url, nonce);
|
||||||
if (proposal.data.nonce !== nonce) {
|
if (proposal.data.nonce !== nonce) {
|
||||||
console.error("stale contract");
|
console.error("stale contract");
|
||||||
@ -403,44 +342,6 @@ function talerPay(msg: any): Promise<any> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function talerPaymentFailed(H_contract: string) {
|
|
||||||
return new Promise(async(resolve, reject) => {
|
|
||||||
const walletMsg = {
|
|
||||||
detail: {
|
|
||||||
contractHash: H_contract,
|
|
||||||
},
|
|
||||||
type: "payment-failed",
|
|
||||||
};
|
|
||||||
chrome.runtime.sendMessage(walletMsg, (resp) => {
|
|
||||||
resolve();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function talerPaymentSucceeded(msg: any) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
if (!msg.H_contract) {
|
|
||||||
console.error("H_contract missing in taler-payment-succeeded");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!msg.merchantSig) {
|
|
||||||
console.error("merchantSig missing in taler-payment-succeeded");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
logVerbose && console.log("got taler-payment-succeeded");
|
|
||||||
const walletMsg = {
|
|
||||||
detail: {
|
|
||||||
contractHash: msg.H_contract,
|
|
||||||
merchantSig: msg.merchantSig,
|
|
||||||
},
|
|
||||||
type: "payment-succeeded",
|
|
||||||
};
|
|
||||||
chrome.runtime.sendMessage(walletMsg, (resp) => {
|
|
||||||
resolve();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function registerHandlers() {
|
function registerHandlers() {
|
||||||
/**
|
/**
|
||||||
|
@ -196,9 +196,10 @@ export function hashContract(contract: object): Promise<string> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Save an offer in the wallet.
|
* Save an offer in the wallet. Returns the offer id that
|
||||||
|
* the offer is stored under.
|
||||||
*/
|
*/
|
||||||
export function saveOffer(offer: object): Promise<void> {
|
export function saveOffer(offer: object): Promise<number> {
|
||||||
return callBackend("save-offer", { offer });
|
return callBackend("save-offer", { offer });
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -208,3 +209,47 @@ export function saveOffer(offer: object): Promise<void> {
|
|||||||
export function confirmReserve(reservePub: string): Promise<void> {
|
export function confirmReserve(reservePub: string): Promise<void> {
|
||||||
return callBackend("confirm-reserve", { reservePub });
|
return callBackend("confirm-reserve", { reservePub });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Query for a payment by fulfillment URL.
|
||||||
|
*/
|
||||||
|
export function queryPayment(url: string): Promise<any> {
|
||||||
|
return callBackend("query-payment", { url });
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a new history item.
|
||||||
|
*/
|
||||||
|
export function putHistory(historyEntry: any): Promise<void> {
|
||||||
|
return callBackend("put-history-entry", { historyEntry });
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mark a payment as succeeded.
|
||||||
|
*/
|
||||||
|
export function paymentSucceeded(contractTermsHash: string, merchantSig: string): Promise<void> {
|
||||||
|
return callBackend("payment-succeeded", { contractTermsHash, merchantSig });
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mark a payment as succeeded.
|
||||||
|
*/
|
||||||
|
export function paymentFailed(contractTermsHash: string): Promise<void> {
|
||||||
|
return callBackend("payment-failed", { contractTermsHash });
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the payment cookie for the current tab, or undefined if no payment
|
||||||
|
* cookie was set.
|
||||||
|
*/
|
||||||
|
export function getTabCookie(contractTermsHash: string, merchantSig: string): Promise<any> {
|
||||||
|
return callBackend("get-tab-cookie");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate a contract nonce (EdDSA key pair), store it in the wallet's
|
||||||
|
* database and return the public key.
|
||||||
|
*/
|
||||||
|
export function generateNonce(): Promise<string> {
|
||||||
|
return callBackend("generate-nonce");
|
||||||
|
}
|
||||||
|
@ -285,15 +285,15 @@ function makeHandlers(db: IDBDatabase,
|
|||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
},
|
},
|
||||||
["payment-succeeded"]: (detail, sender) => {
|
["payment-succeeded"]: (detail, sender) => {
|
||||||
const contractHash = detail.contractHash;
|
const contractTermsHash = detail.contractTermsHash;
|
||||||
const merchantSig = detail.merchantSig;
|
const merchantSig = detail.merchantSig;
|
||||||
if (!contractHash) {
|
if (!contractTermsHash) {
|
||||||
return Promise.reject(Error("contractHash missing"));
|
return Promise.reject(Error("contractHash missing"));
|
||||||
}
|
}
|
||||||
if (!merchantSig) {
|
if (!merchantSig) {
|
||||||
return Promise.reject(Error("merchantSig missing"));
|
return Promise.reject(Error("merchantSig missing"));
|
||||||
}
|
}
|
||||||
return wallet.paymentSucceeded(contractHash, merchantSig);
|
return wallet.paymentSucceeded(contractTermsHash, merchantSig);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user