Compare commits

..

3 Commits

Author SHA1 Message Date
CyberMind
d2cb735f09
Merge pull request #542 from CyberMind-FR/feature/532-plan-browser-xpi-webextension-emancipate
Some checks are pending
License Headers / check (push) Waiting to run
docs: webext .xpi published + tag-pinned release note (#532)
2026-06-13 12:48:03 +02:00
9b7c6f67f1 fix(webext): 'redeclaration of const ext' SyntaxError + PNG icons, v0.1.1 (ref #532)
Real cause of the broken extension: api.js and background.js BOTH did
`const ext = …`. In a Firefox event page the background.scripts array
loads them into one shared scope (same via importScripts in a Chromium
SW), and popup.js's `const ext` collided with api.js's in the popup
page realm too — 'redeclaration of const ext' aborts the script. web-ext
lint misses it because it never concatenates/executes the scripts.
Now only api.js declares `const ext`; background.js and popup.js use
`api.ext`.

Also (defensive + Chromium-correct): replace the SVG action/extension
icon with rasterised PNGs (48/128) and keep the SVG out of the package,
so Firefox never renders SVG in chrome UI. Bump to v0.1.1; the
/wg/toolbox.xpi endpoint + fetch helper + docs point at webext-v0.1.1.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-13 12:32:17 +02:00
4289f8ff3c docs: webext .xpi published/downloadable + tag-pinned release note (ref #532)
README + wiki Browser-Extension: add the direct release download URL,
document make_latest:false / tag-pinned design. TODO/WIP: mark the
webext-v0.1.0 release published (downloadable, verified) and note the
remaining board deploy of secubox-toolbox 2.6.14.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-13 11:29:06 +02:00
12 changed files with 66 additions and 31 deletions

View File

@ -16,6 +16,9 @@
- [x] **#532 browser extension** (`clients/webext-toolbox/`) — MV3 Firefox
`.xpi`/Chromium; live tracker badge + popup mini Round-Eye graph over
`/social/*`; `GET /wg/toolbox.xpi` + fetch helper + `build-webext.yml`.
- [x] **#532 release** — tag `webext-v0.1.1` published the `.xpi`
(downloadable, verified 200). `make_latest:false` + tag-pinned URL so it
doesn't steal "Latest" from the Android APK release.
- [ ] **release signing** — Android keystore + AMO `.xpi` signing secrets in CI
for stable published fingerprints (currently unsigned sideload).
- [ ] **#532 follow-ups** — optional `GET /social/live/{token}` SSE (replace the

View File

@ -21,11 +21,18 @@ le navigateur : badge live des traceurs + popup.
- **Serve depuis la toolbox** (`2.6.14`) : `GET /wg/toolbox.xpi` (local
sinon 302 → release), bouton `🧩 Extension navigateur` sur les 2
panneaux onboard, helper `secubox-toolbox-fetch-xpi`, postinst dir.
- **CI** : `build-webext.yml``web-ext lint` + build, artifact, release
asset `secubox-toolbox-webext.xpi` sur tag `webext-v*`.
- **CI** : `build-webext.yml``web-ext lint` (0 erreur, 2 warnings
bénins) + build, artifact, release asset sur tag `webext-v*`.
- **Release** (PR #540 + #541, mergées) : tag `webext-v0.1.1` poussé →
CI a publié `secubox-toolbox-webext.xpi` (téléchargeable, vérifié 200).
`make_latest:false` + URL **tag-pinned** dans `/wg/toolbox.xpi` +
`secubox-toolbox-fetch-xpi` pour ne pas voler le pointeur "Latest" à la
release APK Android (dont l'endpoint résout via `/releases/latest/...`).
→ bumper le tag dans la constante + le helper à chaque `webext-v*`.
- **Reste à faire** : signature AMO (`.xpi` non signé = sideload/dev) ;
endpoint SSE `/social/live/{token}` optionnel ; icône PNG Chromium ;
contrôle Poke/Emancipate par-site quand #525 (déception) arrive.
contrôle Poke/Emancipate par-site quand #525 (déception) arrive ;
déployer `secubox-toolbox 2.6.14` sur la board pour activer le bouton.
---

View File

@ -28,7 +28,13 @@ to your cabine over the R3 tunnel — no third-party calls.
## Install
The toolbox serves the built extension:
Published release `.xpi` (downloadable directly):
```
https://github.com/CyberMind-FR/secubox-deb/releases/download/webext-v0.1.1/secubox-toolbox-webext.xpi
```
The toolbox also serves it from the cabine:
```
https://kbin.<board>.secubox.in/wg/toolbox.xpi
@ -36,7 +42,12 @@ https://kbin.<board>.secubox.in/wg/toolbox.xpi
The kbin onboard panel exposes a **🧩 Extension navigateur (cartographie)**
button. When a local build is present the cabine serves it; otherwise it
302-redirects to the latest GitHub release asset `secubox-toolbox-webext.xpi`.
302-redirects to the **tag-pinned** release asset above. The webext release
is published `make_latest:false` so it does not steal the repo "Latest"
pointer from the Android APK release (whose endpoint resolves via
`/releases/latest/download/…`) — bump the tag in the `/wg/toolbox.xpi`
endpoint constant + `secubox-toolbox-fetch-xpi` when a new `webext-v*`
release is cut.
- **Firefox** — open the `.xpi`. A permanent install needs an AMO-signed
build (release CI step / `web-ext sign`); for development use

View File

@ -12,15 +12,18 @@ if (typeof importScripts === "function") {
try { importScripts("api.js"); } catch (_) {}
}
// NB: do NOT declare `const ext` here — api.js already declares it in the
// shared script scope (event page) / worker global (importScripts), and a
// second `const ext` is a "redeclaration of const ext" SyntaxError that
// kills the whole background script. Use api.ext instead.
const api = globalThis.SbxApi;
const ext = globalThis.browser || globalThis.chrome;
const ALARM = "sbx-refresh";
const PERIOD_MIN = 1; // poll the cabine once a minute
function setBadge(text, color) {
try {
ext.action.setBadgeText({ text: text || "" });
api.ext.action.setBadgeText({ text: text || "" });
if (color) ext.action.setBadgeBackgroundColor({ color });
} catch (_) {}
}
@ -59,18 +62,18 @@ async function refresh() {
}
}
ext.runtime.onInstalled.addListener(() => {
ext.alarms.create(ALARM, { periodInMinutes: PERIOD_MIN });
api.ext.runtime.onInstalled.addListener(() => {
api.ext.alarms.create(ALARM, { periodInMinutes: PERIOD_MIN });
refresh();
});
ext.runtime.onStartup && ext.runtime.onStartup.addListener(() => {
ext.alarms.create(ALARM, { periodInMinutes: PERIOD_MIN });
api.ext.runtime.onStartup && api.ext.runtime.onStartup.addListener(() => {
api.ext.alarms.create(ALARM, { periodInMinutes: PERIOD_MIN });
refresh();
});
ext.alarms.onAlarm.addListener((a) => { if (a.name === ALARM) refresh(); });
api.ext.alarms.onAlarm.addListener((a) => { if (a.name === ALARM) refresh(); });
// popup asks for an immediate refresh after pairing / config change
ext.runtime.onMessage.addListener((msg, _sender, sendResponse) => {
api.ext.runtime.onMessage.addListener((msg, _sender, sendResponse) => {
if (msg && msg.type === "refresh") {
refresh().then(() => sendResponse({ ok: true }));
return true; // async response

View File

@ -14,9 +14,11 @@ OUT="secubox-toolbox-webext-${VER}.xpi"
rm -f "$OUT"
# -FS = sync (drop stale entries) ; exclude VCS, dotfiles, build script,
# any previously built artefact, and docs.
# any previously built artefact, docs, and the SVG icon source (only the
# rasterised PNGs are referenced by the manifest — keep SVG out of the
# package so Firefox never renders it in chrome UI).
zip -r -FS "$OUT" . \
-x '*.git*' '*/.*' 'build.sh' '*.xpi' 'README.md' >/dev/null
-x '*.git*' '*/.*' 'build.sh' '*.xpi' 'README.md' 'icons/icon.svg' >/dev/null
echo "built $OUT ($(stat -c%s "$OUT" 2>/dev/null || stat -f%z "$OUT") bytes)"
echo "Firefox: about:debugging → This Firefox → Load Temporary Add-on → pick the .xpi (or manifest.json)."

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 618 B

View File

@ -1,7 +1,7 @@
{
"manifest_version": 3,
"name": "SecuBox ToolBoX — Cartographie sociale",
"version": "0.1.0",
"version": "0.1.1",
"description": "Surface the SecuBox R3 toolbox live tracker analysis (cartographie sociale) in your browser: live badge, per-session trackers, mini Round-Eye graph, RGPD wipe + PDF report.",
"browser_specific_settings": {
"gecko": {
@ -17,13 +17,13 @@
"default_title": "SecuBox Cartographie",
"default_popup": "popup/popup.html",
"default_icon": {
"48": "icons/icon.svg",
"128": "icons/icon.svg"
"48": "icons/icon-48.png",
"128": "icons/icon-128.png"
}
},
"icons": {
"48": "icons/icon.svg",
"128": "icons/icon.svg"
"48": "icons/icon-48.png",
"128": "icons/icon-128.png"
},
"background": {
"service_worker": "background.js",

View File

@ -3,8 +3,10 @@
//
// SecuBox-Deb :: webext-toolbox :: popup controller
// NB: api.js (loaded first in this page) already declares `const ext` in the
// shared script scope — re-declaring it here is a "redeclaration of const ext"
// SyntaxError that aborts popup.js. Use api.ext instead.
const api = globalThis.SbxApi;
const ext = api.ext;
const $ = (id) => document.getElementById(id);
function show(which) {
@ -55,7 +57,7 @@ function paint(data) {
async function load() {
const cfg = await api.getConfig();
$("ver").textContent = "v" + (ext.runtime.getManifest().version || "");
$("ver").textContent = "v" + (api.ext.runtime.getManifest().version || "");
// tunnel indicator
api.r3Check(cfg.host).then((r) => {
@ -96,7 +98,7 @@ $("pairBtn").addEventListener("click", async () => {
await api.setConfig({ host });
const token = await api.pair(host);
await api.setConfig({ token });
ext.runtime.sendMessage({ type: "refresh" });
api.ext.runtime.sendMessage({ type: "refresh" });
await load();
} catch (e) {
$("pairMsg").textContent = e.message + " (es-tu sur le tunnel ?)";
@ -105,11 +107,11 @@ $("pairBtn").addEventListener("click", async () => {
$("openFull").addEventListener("click", async () => {
const cfg = await api.getConfig();
ext.tabs.create({ url: api.socialUrl(cfg.host, cfg.token) });
api.ext.tabs.create({ url: api.socialUrl(cfg.host, cfg.token) });
});
$("pdf").addEventListener("click", async () => {
const cfg = await api.getConfig();
ext.tabs.create({ url: api.reportUrl(cfg.host, cfg.token) });
api.ext.tabs.create({ url: api.reportUrl(cfg.host, cfg.token) });
});
$("wipe").addEventListener("click", async () => {
if (!confirm("Effacer toutes tes données de cartographie sur la cabine ?")) return;
@ -125,7 +127,7 @@ $("wipe").addEventListener("click", async () => {
});
$("settings").addEventListener("click", (e) => {
e.preventDefault();
ext.runtime.openOptionsPage();
api.ext.runtime.openOptionsPage();
});
load();

View File

@ -16,7 +16,7 @@ DEST_DIR="/var/lib/secubox/toolbox/webext"
DEST="${DEST_DIR}/secubox-toolbox-webext.xpi"
# Tag-pinned (not /latest/): the webext release is make_latest:false so it
# doesn't steal "latest" from the Android APK release. Bump on new webext-v*.
RELEASE_URL="https://github.com/CyberMind-FR/secubox-deb/releases/download/webext-v0.1.0/secubox-toolbox-webext.xpi"
RELEASE_URL="https://github.com/CyberMind-FR/secubox-deb/releases/download/webext-v0.1.1/secubox-toolbox-webext.xpi"
log() { logger -t "$MODULE" -- "$*" 2>/dev/null || echo "[$MODULE] $*" >&2; }

View File

@ -1374,7 +1374,7 @@ async def wg_toolbox_apk() -> Response:
_WEBEXT_XPI = Path("/var/lib/secubox/toolbox/webext/secubox-toolbox-webext.xpi")
_WEBEXT_XPI_RELEASE = (
"https://github.com/CyberMind-FR/secubox-deb/releases/download/"
"webext-v0.1.0/secubox-toolbox-webext.xpi"
"webext-v0.1.1/secubox-toolbox-webext.xpi"
)

View File

@ -15,7 +15,13 @@ R3 tunnel — no third-party calls.
## Install
The toolbox serves the built extension:
Published release `.xpi` (downloadable directly):
```
https://github.com/CyberMind-FR/secubox-deb/releases/download/webext-v0.1.1/secubox-toolbox-webext.xpi
```
The toolbox also serves it from the cabine:
```
https://kbin.<board>.secubox.in/wg/toolbox.xpi
@ -23,8 +29,9 @@ https://kbin.<board>.secubox.in/wg/toolbox.xpi
The kbin onboard panel exposes a **🧩 Extension navigateur (cartographie)**
button. When a local build is present the cabine serves it
(`application/x-xpinstall`); otherwise it 302-redirects to the latest GitHub
release asset `secubox-toolbox-webext.xpi`.
(`application/x-xpinstall`); otherwise it 302-redirects to the **tag-pinned**
release asset above. The webext release is published `make_latest:false` so it
does not steal the repo "Latest" pointer from the Android APK release.
- **Firefox** — open the `.xpi`. A permanent install needs an AMO-signed build
(release CI / `web-ext sign`); for development use *about:debugging → Load