/*
This file is part of TALER
(C) 2015 GNUnet e.V.
TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
Foundation; either version 3, or (at your option) any later version.
TALER is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
TALER; see the file COPYING. If not, see
*/
/**
* Script that is injected into (all!) pages to allow them
* to interact with the GNU Taler wallet via DOM Events.
*
* @author Florian Dold
*/
import URI = require("urijs");
declare var cloneInto: any;
const PROTOCOL_VERSION = 1;
let logVerbose: boolean = false;
try {
logVerbose = !!localStorage.getItem("taler-log-verbose");
} catch (e) {
// can't read from local storage
}
if (document.documentElement.getAttribute("data-taler-nojs")) {
document.dispatchEvent(new Event("taler-probe-result"));
}
function subst(url: string, H_contract: string) {
url = url.replace("${H_contract}", H_contract);
url = url.replace("${$}", "$");
return url;
}
interface Handler {
type: string;
listener: (e: CustomEvent) => void|Promise;
}
const handlers: Handler[] = [];
function hashContract(contract: string): Promise {
let walletHashContractMsg = {
type: "hash-contract",
detail: {contract}
};
return new Promise((resolve, reject) => {
chrome.runtime.sendMessage(walletHashContractMsg, (resp: any) => {
if (!resp.hash) {
console.log("error", resp);
reject(Error("hashing failed"));
}
resolve(resp.hash);
});
});
}
function queryPayment(url: string): Promise {
const walletMsg = {
type: "query-payment",
detail: { url },
};
return new Promise((resolve, reject) => {
chrome.runtime.sendMessage(walletMsg, (resp: any) => {
resolve(resp);
});
});
}
function putHistory(historyEntry: any): Promise {
const walletMsg = {
type: "put-history-entry",
detail: {
historyEntry,
},
};
return new Promise((resolve, reject) => {
chrome.runtime.sendMessage(walletMsg, (resp: any) => {
resolve();
});
});
}
function saveOffer(offer: any): Promise {
const walletMsg = {
type: "save-offer",
detail: {
offer: {
contract: offer.data,
merchant_sig: offer.sig,
H_contract: offer.hash,
offer_time: new Date().getTime() / 1000
},
},
};
return new Promise((resolve, reject) => {
chrome.runtime.sendMessage(walletMsg, (resp: any) => {
if (resp && resp.error) {
reject(resp);
} else {
resolve(resp);
}
});
});
}
let sheet: CSSStyleSheet|null;
function initStyle() {
logVerbose && console.log("taking over styles");
const name = "taler-presence-stylesheet";
const content = "/* Taler stylesheet controlled by JS */";
let style = document.getElementById(name) as HTMLStyleElement|null;
if (!style) {
style = document.createElement("style");
// Needed by WebKit
style.appendChild(document.createTextNode(content));
style.id = name;
document.head.appendChild(style);
sheet = style.sheet as CSSStyleSheet;
} else {
// We've taken over the stylesheet now,
// make it clear by clearing all the rules in it
// and making it obvious in the DOM.
if (style.tagName.toLowerCase() === "style") {
style.innerText = content;
}
if (!style.sheet) {
throw Error("taler-presence-stylesheet should be a style sheet ( or