Commit ca5a1aa9 authored by taco@waag.org's avatar taco@waag.org
Browse files

Merge branch 'chrome' into main

parents f05d45a6 1cf2f32c
(function(a,b){if("function"==typeof define&&define.amd)define("webextension-polyfill",["module"],b);else if("undefined"!=typeof exports)b(module);else{var c={exports:{}};b(c),a.browser=c.exports}})("undefined"==typeof globalThis?"undefined"==typeof self?this:self:globalThis,function(a){"use strict";if("object"!=typeof globalThis||"object"!=typeof chrome||!chrome||!chrome.runtime||!chrome.runtime.id)throw new Error("This script should only be loaded in a browser extension.");if("undefined"==typeof globalThis.browser||Object.getPrototypeOf(globalThis.browser)!==Object.prototype){a.exports=(a=>{const b={alarms:{clear:{minArgs:0,maxArgs:1},clearAll:{minArgs:0,maxArgs:0},get:{minArgs:0,maxArgs:1},getAll:{minArgs:0,maxArgs:0}},bookmarks:{create:{minArgs:1,maxArgs:1},get:{minArgs:1,maxArgs:1},getChildren:{minArgs:1,maxArgs:1},getRecent:{minArgs:1,maxArgs:1},getSubTree:{minArgs:1,maxArgs:1},getTree:{minArgs:0,maxArgs:0},move:{minArgs:2,maxArgs:2},remove:{minArgs:1,maxArgs:1},removeTree:{minArgs:1,maxArgs:1},search:{minArgs:1,maxArgs:1},update:{minArgs:2,maxArgs:2}},browserAction:{disable:{minArgs:0,maxArgs:1,fallbackToNoCallback:!0},enable:{minArgs:0,maxArgs:1,fallbackToNoCallback:!0},getBadgeBackgroundColor:{minArgs:1,maxArgs:1},getBadgeText:{minArgs:1,maxArgs:1},getPopup:{minArgs:1,maxArgs:1},getTitle:{minArgs:1,maxArgs:1},openPopup:{minArgs:0,maxArgs:0},setBadgeBackgroundColor:{minArgs:1,maxArgs:1,fallbackToNoCallback:!0},setBadgeText:{minArgs:1,maxArgs:1,fallbackToNoCallback:!0},setIcon:{minArgs:1,maxArgs:1},setPopup:{minArgs:1,maxArgs:1,fallbackToNoCallback:!0},setTitle:{minArgs:1,maxArgs:1,fallbackToNoCallback:!0}},browsingData:{remove:{minArgs:2,maxArgs:2},removeCache:{minArgs:1,maxArgs:1},removeCookies:{minArgs:1,maxArgs:1},removeDownloads:{minArgs:1,maxArgs:1},removeFormData:{minArgs:1,maxArgs:1},removeHistory:{minArgs:1,maxArgs:1},removeLocalStorage:{minArgs:1,maxArgs:1},removePasswords:{minArgs:1,maxArgs:1},removePluginData:{minArgs:1,maxArgs:1},settings:{minArgs:0,maxArgs:0}},commands:{getAll:{minArgs:0,maxArgs:0}},contextMenus:{remove:{minArgs:1,maxArgs:1},removeAll:{minArgs:0,maxArgs:0},update:{minArgs:2,maxArgs:2}},cookies:{get:{minArgs:1,maxArgs:1},getAll:{minArgs:1,maxArgs:1},getAllCookieStores:{minArgs:0,maxArgs:0},remove:{minArgs:1,maxArgs:1},set:{minArgs:1,maxArgs:1}},devtools:{inspectedWindow:{eval:{minArgs:1,maxArgs:2,singleCallbackArg:!1}},panels:{create:{minArgs:3,maxArgs:3,singleCallbackArg:!0},elements:{createSidebarPane:{minArgs:1,maxArgs:1}}}},downloads:{cancel:{minArgs:1,maxArgs:1},download:{minArgs:1,maxArgs:1},erase:{minArgs:1,maxArgs:1},getFileIcon:{minArgs:1,maxArgs:2},open:{minArgs:1,maxArgs:1,fallbackToNoCallback:!0},pause:{minArgs:1,maxArgs:1},removeFile:{minArgs:1,maxArgs:1},resume:{minArgs:1,maxArgs:1},search:{minArgs:1,maxArgs:1},show:{minArgs:1,maxArgs:1,fallbackToNoCallback:!0}},extension:{isAllowedFileSchemeAccess:{minArgs:0,maxArgs:0},isAllowedIncognitoAccess:{minArgs:0,maxArgs:0}},history:{addUrl:{minArgs:1,maxArgs:1},deleteAll:{minArgs:0,maxArgs:0},deleteRange:{minArgs:1,maxArgs:1},deleteUrl:{minArgs:1,maxArgs:1},getVisits:{minArgs:1,maxArgs:1},search:{minArgs:1,maxArgs:1}},i18n:{detectLanguage:{minArgs:1,maxArgs:1},getAcceptLanguages:{minArgs:0,maxArgs:0}},identity:{launchWebAuthFlow:{minArgs:1,maxArgs:1}},idle:{queryState:{minArgs:1,maxArgs:1}},management:{get:{minArgs:1,maxArgs:1},getAll:{minArgs:0,maxArgs:0},getSelf:{minArgs:0,maxArgs:0},setEnabled:{minArgs:2,maxArgs:2},uninstallSelf:{minArgs:0,maxArgs:1}},notifications:{clear:{minArgs:1,maxArgs:1},create:{minArgs:1,maxArgs:2},getAll:{minArgs:0,maxArgs:0},getPermissionLevel:{minArgs:0,maxArgs:0},update:{minArgs:2,maxArgs:2}},pageAction:{getPopup:{minArgs:1,maxArgs:1},getTitle:{minArgs:1,maxArgs:1},hide:{minArgs:1,maxArgs:1,fallbackToNoCallback:!0},setIcon:{minArgs:1,maxArgs:1},setPopup:{minArgs:1,maxArgs:1,fallbackToNoCallback:!0},setTitle:{minArgs:1,maxArgs:1,fallbackToNoCallback:!0},show:{minArgs:1,maxArgs:1,fallbackToNoCallback:!0}},permissions:{contains:{minArgs:1,maxArgs:1},getAll:{minArgs:0,maxArgs:0},remove:{minArgs:1,maxArgs:1},request:{minArgs:1,maxArgs:1}},runtime:{getBackgroundPage:{minArgs:0,maxArgs:0},getPlatformInfo:{minArgs:0,maxArgs:0},openOptionsPage:{minArgs:0,maxArgs:0},requestUpdateCheck:{minArgs:0,maxArgs:0},sendMessage:{minArgs:1,maxArgs:3},sendNativeMessage:{minArgs:2,maxArgs:2},setUninstallURL:{minArgs:1,maxArgs:1}},sessions:{getDevices:{minArgs:0,maxArgs:1},getRecentlyClosed:{minArgs:0,maxArgs:1},restore:{minArgs:0,maxArgs:1}},storage:{local:{clear:{minArgs:0,maxArgs:0},get:{minArgs:0,maxArgs:1},getBytesInUse:{minArgs:0,maxArgs:1},remove:{minArgs:1,maxArgs:1},set:{minArgs:1,maxArgs:1}},managed:{get:{minArgs:0,maxArgs:1},getBytesInUse:{minArgs:0,maxArgs:1}},sync:{clear:{minArgs:0,maxArgs:0},get:{minArgs:0,maxArgs:1},getBytesInUse:{minArgs:0,maxArgs:1},remove:{minArgs:1,maxArgs:1},set:{minArgs:1,maxArgs:1}}},tabs:{captureVisibleTab:{minArgs:0,maxArgs:2},create:{minArgs:1,maxArgs:1},detectLanguage:{minArgs:0,maxArgs:1},discard:{minArgs:0,maxArgs:1},duplicate:{minArgs:1,maxArgs:1},executeScript:{minArgs:1,maxArgs:2},get:{minArgs:1,maxArgs:1},getCurrent:{minArgs:0,maxArgs:0},getZoom:{minArgs:0,maxArgs:1},getZoomSettings:{minArgs:0,maxArgs:1},goBack:{minArgs:0,maxArgs:1},goForward:{minArgs:0,maxArgs:1},highlight:{minArgs:1,maxArgs:1},insertCSS:{minArgs:1,maxArgs:2},move:{minArgs:2,maxArgs:2},query:{minArgs:1,maxArgs:1},reload:{minArgs:0,maxArgs:2},remove:{minArgs:1,maxArgs:1},removeCSS:{minArgs:1,maxArgs:2},sendMessage:{minArgs:2,maxArgs:3},setZoom:{minArgs:1,maxArgs:2},setZoomSettings:{minArgs:1,maxArgs:2},update:{minArgs:1,maxArgs:2}},topSites:{get:{minArgs:0,maxArgs:0}},webNavigation:{getAllFrames:{minArgs:1,maxArgs:1},getFrame:{minArgs:1,maxArgs:1}},webRequest:{handlerBehaviorChanged:{minArgs:0,maxArgs:0}},windows:{create:{minArgs:0,maxArgs:1},get:{minArgs:1,maxArgs:2},getAll:{minArgs:0,maxArgs:1},getCurrent:{minArgs:0,maxArgs:1},getLastFocused:{minArgs:0,maxArgs:1},remove:{minArgs:1,maxArgs:1},update:{minArgs:2,maxArgs:2}}};if(0===Object.keys(b).length)throw new Error("api-metadata.json has not been included in browser-polyfill");class c extends WeakMap{constructor(a,b=void 0){super(b),this.createItem=a}get(a){return this.has(a)||this.set(a,this.createItem(a)),super.get(a)}}const d=a=>a&&"object"==typeof a&&"function"==typeof a.then,e=(b,c)=>(...d)=>{a.runtime.lastError?b.reject(new Error(a.runtime.lastError.message)):c.singleCallbackArg||1>=d.length&&!1!==c.singleCallbackArg?b.resolve(d[0]):b.resolve(d)},f=a=>1==a?"argument":"arguments",g=(a,b)=>function(c,...d){if(d.length<b.minArgs)throw new Error(`Expected at least ${b.minArgs} ${f(b.minArgs)} for ${a}(), got ${d.length}`);if(d.length>b.maxArgs)throw new Error(`Expected at most ${b.maxArgs} ${f(b.maxArgs)} for ${a}(), got ${d.length}`);return new Promise((f,g)=>{if(b.fallbackToNoCallback)try{c[a](...d,e({resolve:f,reject:g},b))}catch(e){console.warn(`${a} API method doesn't seem to support the callback parameter, `+"falling back to call it without a callback: ",e),c[a](...d),b.fallbackToNoCallback=!1,b.noCallback=!0,f()}else b.noCallback?(c[a](...d),f()):c[a](...d,e({resolve:f,reject:g},b))})},h=(a,b,c)=>new Proxy(b,{apply(b,d,e){return c.call(d,a,...e)}});let i=Function.call.bind(Object.prototype.hasOwnProperty);const j=(a,b={},c={})=>{let d=Object.create(null),e=Object.create(a);return new Proxy(e,{has(b,c){return c in a||c in d},get(e,f){if(f in d)return d[f];if(!(f in a))return;let k=a[f];if("function"==typeof k){if("function"==typeof b[f])k=h(a,a[f],b[f]);else if(i(c,f)){let b=g(f,c[f]);k=h(a,a[f],b)}else k=k.bind(a);}else if("object"==typeof k&&null!==k&&(i(b,f)||i(c,f)))k=j(k,b[f],c[f]);else if(i(c,"*"))k=j(k,b[f],c["*"]);else return Object.defineProperty(d,f,{configurable:!0,enumerable:!0,get(){return a[f]},set(b){a[f]=b}}),k;return d[f]=k,k},set(b,c,e){return c in d?d[c]=e:a[c]=e,!0},defineProperty(a,b,c){return Reflect.defineProperty(d,b,c)},deleteProperty(a,b){return Reflect.deleteProperty(d,b)}})},k=a=>({addListener(b,c,...d){b.addListener(a.get(c),...d)},hasListener(b,c){return b.hasListener(a.get(c))},removeListener(b,c){b.removeListener(a.get(c))}}),l=new c(a=>"function"==typeof a?function(b){const c=j(b,{},{getContent:{minArgs:0,maxArgs:0}});a(c)}:a);let m=!1;const n=new c(a=>"function"==typeof a?function(b,c,e){let f,g,h=!1,i=new Promise(a=>{f=function(b){m||(console.warn("Returning a Promise is the preferred way to send a reply from an onMessage/onMessageExternal listener, as the sendResponse will be removed from the specs (See https://developer.mozilla.org/docs/Mozilla/Add-ons/WebExtensions/API/runtime/onMessage)",new Error().stack),m=!0),h=!0,a(b)}});try{g=a(b,c,f)}catch(a){g=Promise.reject(a)}const j=!0!==g&&d(g);if(!0!==g&&!j&&!h)return!1;const k=a=>{a.then(a=>{e(a)},a=>{let b;b=a&&(a instanceof Error||"string"==typeof a.message)?a.message:"An unexpected error occurred",e({__mozWebExtensionPolyfillReject__:!0,message:b})}).catch(a=>{console.error("Failed to send onMessage rejected reply",a)})};return j?k(g):k(i),!0}:a),o=({reject:b,resolve:c},d)=>{a.runtime.lastError?a.runtime.lastError.message==="The message port closed before a response was received."?c():b(new Error(a.runtime.lastError.message)):d&&d.__mozWebExtensionPolyfillReject__?b(new Error(d.message)):c(d)},p=(a,b,c,...d)=>{if(d.length<b.minArgs)throw new Error(`Expected at least ${b.minArgs} ${f(b.minArgs)} for ${a}(), got ${d.length}`);if(d.length>b.maxArgs)throw new Error(`Expected at most ${b.maxArgs} ${f(b.maxArgs)} for ${a}(), got ${d.length}`);return new Promise((a,b)=>{const e=o.bind(null,{resolve:a,reject:b});d.push(e),c.sendMessage(...d)})},q={devtools:{network:{onRequestFinished:k(l)}},runtime:{onMessage:k(n),onMessageExternal:k(n),sendMessage:p.bind(null,"sendMessage",{minArgs:1,maxArgs:3})},tabs:{sendMessage:p.bind(null,"sendMessage",{minArgs:2,maxArgs:3})}},r={clear:{minArgs:1,maxArgs:1},get:{minArgs:1,maxArgs:1},set:{minArgs:1,maxArgs:1}};return b.privacy={network:{"*":r},services:{"*":r},websites:{"*":r}},j(a,q,b)})(chrome)}else a.exports=globalThis.browser});
//# sourceMappingURL=browser-polyfill.min.js.map
// webextension-polyfill v.0.9.0 (https://github.com/mozilla/webextension-polyfill)
/* 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/. */
This source diff could not be displayed because it is too large. You can view the blob instead.
(async function () {
if (!WebAssembly.instantiateStreaming) {
WebAssembly.instantiateStreaming = async (resp, importObject) => {
const source = await (await resp).arrayBuffer();
return await WebAssembly.instantiate(source, importObject);
};
}
const schemes = await fetch("schemes.zip");
const schemesBuffer = await schemes.arrayBuffer();
const Buffer = BrowserFS.BFSRequire("buffer").Buffer;
BrowserFS.configure(
{
fs: "OverlayFS",
options: {
readable: {
fs: "MountableFileSystem",
options: {
"/irma_configuration": {
fs: "ZipFS",
options: {
zipData: Buffer.from(schemesBuffer),
},
},
},
},
writable: {
fs: "InMemory",
},
},
},
async (e) => {
if (e) throw e;
console.log("BrowserFS configured.");
const go = new Go();
const result = await WebAssembly.instantiateStreaming(
fetch("main_opt.wasm"),
go.importObject
);
go.run(result.instance).catch((e) => console.error(err));
}
);
})();
const zip = (a, b) => a.map((k, i) => [k, b[i]]);
//to test library integration was succesful
console.log(blockhashjs);
//post to verification backend
browser.runtime.onMessage.addListener(function(msg, sender, sendResponse){
......@@ -8,6 +6,8 @@ browser.runtime.onMessage.addListener(function(msg, sender, sendResponse){
if(msg.command == "verify"){
if(!verifySignature){return;}//function not ready yet
let keys = msg.signatures.map(entry=> entry[0]);
var values = msg.signatures.map(entry=>entry[1]);
let envelopes = msg.signatures.map(entry=>entry[2]);
......@@ -36,14 +36,16 @@ browser.runtime.onMessage.addListener(function(msg, sender, sendResponse){
//now verify all signatures (with the hashes in place of the message for image fragments)
Promise.all(values.map(signature =>
fetch('http://localhost:3000/verify', { method: 'POST', headers: {
'Accept': 'application/json, text/plain, */*',
'Content-Type': 'application/json'
}, body: signature })
.then(resp => resp.text())
// fetch('http://localhost:3000/verify', { method: 'POST', headers: {
// 'Accept': 'application/json, text/plain, */*',
// 'Content-Type': 'application/json'
// }, body: signature })
verifySignature(JSON.parse(signature))
.then(resp => JSON.stringify(resp))
)).then(responses => {
handleValidationResults(msg, responses, keys, values, envelopes, tab_id);
}).catch(function(err) {
console.log(err);
browser.browserAction.setIcon({
tabId: tab_id, path: "icons/pop_certificate_server_error-48.png"
});
......@@ -67,9 +69,10 @@ function getBlockhash(url){
};
function handleValidationResults(msg, responses, keys, values, envelopes, tab_id){
console.log(responses);
//if all responses are VALID we show a green check mark
const valid = responses.every(function (response) {
return JSON.parse(response)["status"] == 'VALID';
return JSON.parse(response)["proofStatus"] == 'VALID';
});
//index resultset
......@@ -88,7 +91,19 @@ function handleValidationResults(msg, responses, keys, values, envelopes, tab_id
var args = {};
args[key2] = false;
browser.storage.local.set(args);
let fragmentCount = responses.length;
//console.log(fragmentCount);
if(fragmentCount > 0)
{
browser.browserAction.setBadgeText({text: fragmentCount.toString(), tabId: tab_id});
browser.browserAction.setBadgeBackgroundColor({color: "blue", tabId: tab_id});
browser.browserAction.onClicked.addListener((tab) => {
toggleProvenanceView(tab);
});
}
/*
if(valid){
browser.browserAction.setIcon({
tabId: tab_id, path: "icons/pop_certificate_valid-48.png"
......@@ -104,11 +119,15 @@ function handleValidationResults(msg, responses, keys, values, envelopes, tab_id
browser.browserAction.setIcon({
tabId: tab_id, path: "icons/pop_certificate_invalid-48.png"
});
}
}*/
}
//toggle provenance view for current tab
function toggleProvenanceView(active_tab) {
//to see if function is available, works cool!
//console.log(verifySignature);
console.log("in toggle for tab " + active_tab.id);
let key1 = "pop_state_" + active_tab.id;
let key2 = "pop_toggle_" + active_tab.id;
......
......@@ -3,11 +3,12 @@
"name": "Proof of provenance",
"version": "0.2",
"description": "Verifies IRMA provenance attributes",
"content_security_policy": "script-src 'self' 'wasm-eval'; object-src 'self'",
"icons": {
"48": "icons/pop_certificate_none-48.png"
},
"permissions": [
"http://localhost:/*",
"https://irma.sidn.nl/*",
"storage",
"webRequest",
"tabs"
......@@ -18,12 +19,12 @@
},
"content_scripts": [{
"matches": ["*://*/*"],
"js": ["pop_detect.js","pop_view.js"],
"js": ["browser-polyfill.min.js","pop_detect.js","pop_view.js"],
"css" : ["pop.css"],
"run_at": "document_idle"
}],
"background": {
"scripts": ["zlib.js","blockhash.js","local_backend.js"]
"scripts": ["browser-polyfill.min.js","browserfs.min.js","wasm_exec.js","irmavf.js","zlib.js","blockhash.js","local_backend.js"]
},
"web_accessible_resources": ["icons/clippy.svg"]
"web_accessible_resources": ["main_opt.wasm","schemes.zip","icons/clippy.svg"]
}
......@@ -11,6 +11,17 @@
font-family: monospace;
}
.pop-button-chrome {
margin-top: 10px;
float: right;
cursor: pointer;
background-image: url('chrome-extension://__MSG_@@extension_id__/icons/clippy.svg');
padding: .25rem;
color: black;
height: 2rem;
width: 2rem;
}
.pop-button {
margin-top: 10px;
float: right;
......
......@@ -41,7 +41,12 @@ if (window.hasRun) {
//renders a copybutton for the fragment
function appendCopyButton(fragment, type, message, envelope){
let button = document.createElement('button');
button.classList.add('pop-button');
let isFirefox = navigator.userAgent.indexOf('Firefox') !== -1;
if (!isFirefox) {
button.classList.add('pop-button-chrome');
} else {
button.classList.add('pop-button');
}
button.type = "button";
button.onclick = function() {toClipboard(message,envelope,type)};
fragment.appendChild(button);
......@@ -54,17 +59,44 @@ if (window.hasRun) {
let img = document.createElement('img');
img.src = message;
img.setAttribute(type,envelope);
navigator.clipboard.writeText(img.outerHTML);
//navigator.clipboard.writeText(img.outerHTML);
copyToClipboard(img.outerHTML).then(() => alert('copied to clipboard!')).catch(() => console.log('error'));
} else {
let blockquote = document.createElement('blockquote');
blockquote.textContent = message;
blockquote.setAttribute(type,envelope);
blockquote.cite = window.location;
navigator.clipboard.writeText(blockquote.outerHTML);
//navigator.clipboard.writeText(blockquote.outerHTML);
copyToClipboard(blockquote.outerHTML).then(() => alert('copied to clipboard!')).catch(() => console.log('error'));
}
alert('Copied to clipboard');
}
// return a promise
function copyToClipboard(textToCopy) {
// navigator clipboard api needs a secure context (https)
if (navigator.clipboard && window.isSecureContext) {
// navigator clipboard api method'
return navigator.clipboard.writeText(textToCopy);
} else {
// text area method
let textArea = document.createElement("textarea");
textArea.value = textToCopy;
// make the textarea out of viewport
textArea.style.position = "fixed";
textArea.style.left = "-999999px";
textArea.style.top = "-999999px";
document.body.appendChild(textArea);
textArea.focus();
textArea.select();
return new Promise((res, rej) => {
// here the magic happens
document.execCommand('copy') ? res() : rej();
textArea.remove();
});
}
}
function appendLabel(fragment,type){
let label = document.createElement('div');
label.classList.add('pop-label');
......@@ -73,13 +105,13 @@ if (window.hasRun) {
}
function appendProof(fragment, result){
let status = result["status"];
let status = result["proofStatus"];
var proof_string = status;
if(status == "VALID"){
let email = result["email"];
let credential = result["id"];
let issuance_date = new Date(result["issuancetime"]*1000).toLocaleDateString("nl-NL");
let email = result.disclosed[0][0].rawvalue;
let credential = result.disclosed[0][0].id;
let issuance_date = new Date(result.disclosed[0][0].issuancetime*1000).toLocaleDateString("nl-NL");
proof_string = `${status} - signed using ${credential}: ${email} issued on ${issuance_date}.`
}
......@@ -103,7 +135,7 @@ if (window.hasRun) {
let header = document.createElement('h1');
header.textContent = content;
let status = result["status"];
let status = result["proofStatus"];
if(status == "VALID"){
appendCopyButton(fragment,type,content,signature);
}
......@@ -125,7 +157,7 @@ if (window.hasRun) {
let p = document.createElement('pre');
p.textContent = content;
let status = result["status"];
let status = result["proofStatus"];
if(status == "VALID"){
appendCopyButton(fragment,type,content,signature);
}
......@@ -146,7 +178,7 @@ if (window.hasRun) {
let p = document.createElement('pre');
p.textContent = content;
let status = result["status"];
let status = result["proofStatus"];
if(status == "VALID"){
appendCopyButton(fragment,type,content,signature);
}
......@@ -167,7 +199,7 @@ if (window.hasRun) {
let p = document.createElement('pre');
p.textContent = content;
let status = result["status"];
let status = result["proofStatus"];
if(status == "VALID"){
appendCopyButton(fragment,type,content,signature);
}
......@@ -188,7 +220,7 @@ if (window.hasRun) {
let p = document.createElement('img');
p.src = content;
let status = result["status"];
let status = result["proofStatus"];
if(status == "VALID"){
appendCopyButton(fragment,type,content,signature);
}
......
This diff is collapsed.
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment