Oregami
Repositories/oxedyne/daimond

oxedyne/daimond/verify/ext/background.js

2.6 KiB, 1 run

created by r2519314175:1009, which is this file's identity for as long as the history lasts, whatever it is later renamed to

download · who wrote it · its history

1// verify/ext/background.js — the Daimond Verify service worker.
2//
3// On every load of a Daimond origin it re-checks the served build and colours
4// the toolbar badge: a green tick means the code the browser just loaded is the
5// published source and was sealed in the public log; a red cross means it is
6// not; a query means it could not be sure (offline). The popup shows the detail.
7//
8// The check runs here, in installed code, against the site's own bytes and the
9// log on GitHub — so the site being checked has no way to influence the verdict.
10
11import { verifyOrigin } from './check.js';
12
13// The origins this extension vouches for. Kept narrow on purpose: an extension
14// that badged every site would teach the user to ignore the badge.
15const MATCH = [
16 /^https:\/\/daimond\.oxedyne\.com/,
17 /^https?:\/\/(127\.0\.0\.1|localhost):8777/,
18];
19
20// Last verdict per tab, for the popup to read. Memory only.
21const verdicts = {};
22
23// Exposed for the tests, which drive the worker directly; unused in the field.
24self.verifyOrigin = verifyOrigin;
25self.__verdicts = verdicts;
26
27function matched(url) { return !!url && MATCH.some(r => r.test(url)); }
28
29async function configuredLog() {
30 try { return (await chrome.storage.local.get('logUrl')).logUrl || undefined; }
31 catch (e) { return undefined; }
32}
33
34async function setBadge(tabId, state) {
35 const map = { busy: ['…', '#8a8a8a'], ok: ['✓', '#3a7d54'], no: ['✗', '#c0392b'], warn: ['?', '#c98a12'] };
36 const m = map[state] || map.warn;
37 try {
38 await chrome.action.setBadgeText({ tabId, text: m[0] });
39 await chrome.action.setBadgeBackgroundColor({ tabId, color: m[1] });
40 } catch (e) { /* the tab may be gone */ }
41}
42
43async function run(tabId, url) {
44 await setBadge(tabId, 'busy');
45 let v;
46 try {
47 v = await verifyOrigin(new URL(url).origin, await configuredLog());
48 } catch (e) {
49 v = { ok: false, failed: false, build: '', bundle: '', checks: [{ name: 'check', ok: null, detail: String(e) }] };
50 }
51 verdicts[tabId] = { ...v, url, ts: Date.now() };
52 await setBadge(tabId, v.ok ? 'ok' : v.failed ? 'no' : 'warn');
53}
54
55chrome.tabs.onUpdated.addListener((tabId, info, tab) => {
56 if (info.status === 'complete' && matched(tab.url)) run(tabId, tab.url);
57});
58
59// A tab navigating away should not keep an old verdict's badge on a new page.
60chrome.tabs.onRemoved.addListener((tabId) => { delete verdicts[tabId]; });
61
62chrome.runtime.onMessage.addListener((msg, _sender, reply) => {
63 if (msg && msg.type === 'verdict') { reply(verdicts[msg.tabId] || null); return true; }
64 if (msg && msg.type === 'recheck' && msg.tabId != null && msg.url) {
65 run(msg.tabId, msg.url).then(() => reply(verdicts[msg.tabId] || null));
66 return true;
67 }
68 return false;
69});