improve backend / content script messaging

This commit is contained in:
Florian Dold 2017-05-31 11:56:26 +02:00
parent 04a7800bc8
commit 87f981d91c
No known key found for this signature in database
GPG Key ID: D2E4F00F29D02A4B
3 changed files with 69 additions and 123 deletions

View File

@ -21,7 +21,6 @@
* to interact with the GNU Taler wallet via DOM Events.
*/
/**
* Imports.
*/
@ -48,55 +47,6 @@ interface 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;
@ -153,7 +103,7 @@ function handlePaymentResponse(walletResp: any) {
* Try to notify the wallet first, before we show a potentially
* 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;
function err() {
// FIXME: proper error reporting!
@ -165,13 +115,12 @@ function handlePaymentResponse(walletResp: any) {
}
timeoutHandle = window.setTimeout(onTimeout, 200);
talerPaymentFailed(walletResp.H_contract).then(() => {
if (timeoutHandle !== null) {
clearTimeout(timeoutHandle);
timeoutHandle = null;
}
err();
});
await wxApi.paymentFailed(walletResp.H_contract);
if (timeoutHandle !== null) {
clearTimeout(timeoutHandle);
timeoutHandle = null;
}
err();
}
logVerbose && console.log("handling taler-notify-payment: ", walletResp);
@ -185,7 +134,7 @@ function handlePaymentResponse(walletResp: any) {
r.open("post", walletResp.contract.pay_url);
r.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
r.send(JSON.stringify(walletResp.payReq));
r.onload = () => {
r.onload = async () => {
if (!r) {
return;
}
@ -193,12 +142,11 @@ function handlePaymentResponse(walletResp: any) {
case 200:
const merchantResp = JSON.parse(r.responseText);
logVerbose && console.log("got success from pay_url");
talerPaymentSucceeded({H_contract: walletResp.H_contract, merchantSig: merchantResp.sig}).then(() => {
const nextUrl = walletResp.contract.fulfillment_url;
logVerbose && console.log("taler-payment-succeeded done, going to", nextUrl);
window.location.href = nextUrl;
window.location.reload(true);
});
await wxApi.paymentSucceeded(walletResp.H_contract, merchantResp.sig);
const nextUrl = walletResp.contract.fulfillment_url;
logVerbose && console.log("taler-payment-succeeded done, going to", nextUrl);
window.location.href = nextUrl;
window.location.reload(true);
break;
default:
handleFailedPayment(r);
@ -226,6 +174,8 @@ function handlePaymentResponse(walletResp: any) {
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) => {
if (chrome.runtime.lastError) {
logVerbose && console.log("extension not yet ready");
@ -267,17 +217,6 @@ function init() {
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> {
const parsed_url = new URI(url);
url = parsed_url.setQuery({nonce}).href();
@ -361,8 +300,8 @@ async function processProposal(proposal: any) {
timestamp: (new Date()).getTime(),
type: "offer-contract",
};
await putHistory(historyEntry);
const offerId = await saveOffer(proposal);
await wxApi.putHistory(historyEntry);
const offerId = await wxApi.saveOffer(proposal);
const uri = new URI(chrome.extension.getURL(
"/src/webex/pages/confirm-contract.html"));
@ -377,14 +316,14 @@ function talerPay(msg: any): Promise<any> {
return new Promise(async(resolve, reject) => {
// current URL without fragment
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);
if (res && res.payReq) {
resolve(res);
return;
}
if (msg.contract_url) {
const nonce = await generateNonce();
const nonce = await wxApi.generateNonce();
const proposal = await downloadContract(msg.contract_url, nonce);
if (proposal.data.nonce !== nonce) {
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() {
/**

View File

@ -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 });
}
@ -208,3 +209,47 @@ export function saveOffer(offer: object): Promise<void> {
export function confirmReserve(reservePub: string): Promise<void> {
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");
}

View File

@ -285,15 +285,15 @@ function makeHandlers(db: IDBDatabase,
return Promise.resolve();
},
["payment-succeeded"]: (detail, sender) => {
const contractHash = detail.contractHash;
const contractTermsHash = detail.contractTermsHash;
const merchantSig = detail.merchantSig;
if (!contractHash) {
if (!contractTermsHash) {
return Promise.reject(Error("contractHash missing"));
}
if (!merchantSig) {
return Promise.reject(Error("merchantSig missing"));
}
return wallet.paymentSucceeded(contractHash, merchantSig);
return wallet.paymentSucceeded(contractTermsHash, merchantSig);
},
};
}