A bundled add-on that answers cookie consent dialogs, rejecting all but the essentials by default (or accepting, if the user prefers the banner simply gone), so pages open without one. Built on DuckDuckGo's autoconsent (MPL-2.0): its rule bundle covers hundreds of consent managers, and a reject-button heuristic handles unknown banners in reject mode. The library runs through the page-inject slot in every http(s) frame's isolated world; the add-on hands each frame the user's settings and the rules, and counts what was handled per site for the panel, which also excludes a site with one click. build-inject.js assembles inject.js from the library in node_modules plus the glue, and copies the compact rules and licence into the add-on so a rule update can ship through the add-on channel. Host side: page-inject scripts get theseus.evalInPage for the few rules that need the page's own JavaScript (they already reach the page via contextBridge, so no new trust tier), and api.tabs is open to page-inject add-ons as well as request-filter ones.
39 lines
2.1 KiB
JavaScript
39 lines
2.1 KiB
JavaScript
// Glue between autoconsent (inlined above by build-inject.js) and the add-on.
|
|
// Runs in the isolated world of every http(s) frame. Nothing is exposed to
|
|
// the page: the library works through the DOM only, and the few rules that
|
|
// need the page's own JavaScript go through theseus.evalInPage.
|
|
//
|
|
// Message flow (see autoconsent docs/api.md): the instance asks for "init",
|
|
// the add-on answers with the user's settings and the rule bundle (or
|
|
// nothing, when the add-on is off or the site is excluded); "eval" requests
|
|
// are run in the main world and answered; the outcome messages are reported
|
|
// so the panel can count handled pop-ups per site.
|
|
let instance = null;
|
|
const isTop = (() => { try { return window.top === window; } catch { return false; } })();
|
|
const report = (msg) => theseus.invoke("consent.event", {
|
|
type: msg.type, cmp: msg.cmp || "", url: msg.url || location.href, result: msg.result === undefined ? null : !!msg.result,
|
|
isCosmetic: !!msg.isCosmetic, details: msg.type === "autoconsentError" ? String(msg.details && (msg.details.msg || msg.details.message || msg.details)).slice(0, 200) : "", top: isTop,
|
|
}).catch(() => {});
|
|
const send = async (msg) => {
|
|
try {
|
|
switch (msg.type) {
|
|
case "init": {
|
|
const r = await theseus.invoke("consent.init", { url: msg.url, top: isTop });
|
|
if (!r || !r.enabled || !instance) return;
|
|
await instance.receiveMessageCallback({ type: "initResp", rules: r.rules, config: r.config });
|
|
break;
|
|
}
|
|
case "eval": {
|
|
let result = false;
|
|
try { result = await theseus.evalInPage(msg.code); } catch { result = false; }
|
|
if (instance) await instance.receiveMessageCallback({ type: "evalResp", id: msg.id, result });
|
|
break;
|
|
}
|
|
case "cmpDetected": case "popupFound": case "optOutResult": case "optInResult":
|
|
case "autoconsentDone": case "autoconsentError": case "selfTestResult":
|
|
report(msg); break;
|
|
default: break;
|
|
}
|
|
} catch (e) { /* the page must never see a failure here */ }
|
|
};
|
|
try { instance = new AutoConsentCtor(send, null, null); } catch (e) { instance = null; }
|