Files
SvenandClaude Opus 5 99757361ef first commit
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-20 11:05:58 +02:00

261 lines
12 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Swyx Tab Bridge — Firefox-Add-on
Verwaltet Firefox-Tabs über die WebSocket-Verbindung zu SwyxTray: Tabs auslesen, öffnen
und schließen.
## Rollenverteilung
Ein Browser-Add-on kann **keinen** WebSocket-Server betreiben — es kann nur Client sein.
Das Add-on **verbindet sich** daher zu SwyxTray (Default `ws://127.0.0.1:17655`) und
beantwortet die dort eintreffenden Aufträge.
```
[ SwyxTray, Port 17655 ] <--- verbindet sich --- [ Firefox-Add-on: WS-Client ]
| {"type":"tab","id":1,"action":"list"} ->
<- {"cmd":"tabresult","id":1,"ok":true,"tabs":[…]}
```
Zuständig ist das Add-on **ausschließlich für Tab-Nachrichten** (`"type":"tab"`).
Alles andere auf der Verbindung — Telefonie-Kommandos, Events, Nachrichten an andere
Komponenten — wird ignoriert: keine Antwort, kein Fehler.
## Protokoll
Alle Nachrichten sind JSON-Textframes. Die `id` der Anfrage wird unverändert in die
Antwort gespiegelt; die Antwort trägt immer `"cmd":"tabresult"`.
### 1. Offene Tabs auslesen (`list`)
```json
{"type":"tab","id":1,"action":"list"}
{"cmd":"tabresult","id":1,"ok":true,
"tabs":[{"id":42,"title":"Kundenakte Muster GmbH","url":"https://crm.example.local/kunden/4711","active":false},
{"id":43,"title":"Posteingang","url":"https://mail.example.local/","active":true}]}
```
Optionale Felder zum Einschränken: `currentWindowOnly` (bool), `windowId` (number),
`url` / `title` (Match-Pattern, z.B. `"*://*.example.local/*"`).
### 2. Tab mit mitgegebener URL öffnen (`open`)
```json
{"type":"tab","id":2,"action":"open","url":"https://crm.example.local/kunden/4711"}
{"cmd":"tabresult","id":2,"ok":true,"tabId":44}
```
Optionale Felder:
| Feld | Typ | Default | Beschreibung |
|-------------|---------|---------|-----------------------------------------------------------------|
| `active` | boolean | `true` | `false` = im Hintergrund öffnen |
| `reuse` | boolean | `false` | ist die URL schon offen, wird der Tab aktiviert statt neu geöffnet (Antwort enthält dann `"reused":true`) |
| `newWindow` | boolean | `false` | in neuem Fenster öffnen |
| `windowId` | number | | Zielfenster |
| `index` | number | | Position in der Tableiste |
| `pinned` | boolean | `false` | angeheftet öffnen |
Erlaubt sind `http`, `https`, `ftp`, `file`; `javascript:`, `data:` u.ä. werden abgewiesen.
### 3. Tab löschen (`close`)
```json
{"type":"tab","id":3,"action":"close","tabId":42}
{"cmd":"tabresult","id":3,"ok":true}
```
`tabId` darf auch ein Array sein (`[42,43]`); die Antwort enthält dann `"closed":[42,43]`.
### Anmeldung (`hello`)
Direkt nach dem Verbindungsaufbau meldet sich das Add-on einmal an — immer, nicht
nur mit Token:
```json
{"cmd":"hello","client":"swyx-tab-bridge","version":"1.0.0",
"actions":["list","open","close","activate","focus"]}
```
Ist unter *Einstellungen* ein Token gesetzt, kommt es als Feld `token` mit. Eine
Antwort wird nicht erwartet. SwyxTray kann die Gegenstelle erst dadurch
identifizieren und den Verbindungsaufbau protokollieren; ohne `hello` ist auf der
Leitung nicht unterscheidbar, wer sich verbunden hat.
### Fehler
```json
{"cmd":"tabresult","id":5,"ok":false,"error":"Feld 'url' fehlt."}
```
`error` ist ein zusätzliches Klartextfeld zur Diagnose — maßgeblich ist `"ok":false`.
Fehlerfälle: fehlendes/ungültiges `url` bzw. `tabId`, unerlaubtes URL-Protokoll,
unbekannte `action`, nicht existierender Tab.
SwyxTray wertet einen Auftrag nach 5 s ohne Antwort als gescheitert. Das Add-on bricht
deshalb jede Aktion nach 4 s ab (`ACTION_TIMEOUT_MS` in [`background.js`](background.js))
und antwortet dann mit `"ok":false` — es bleibt also nie stumm.
### Zusätzliche Aktionen
Über die drei SwyxTray-Aktionen hinaus versteht das Add-on:
```json
{"type":"tab","id":4,"action":"activate","tabId":42}
{"cmd":"tabresult","id":4,"ok":true,"tabId":42}
{"type":"tab","id":5,"action":"focus","url":"https://crm.example.local/kunden/4711"}
{"cmd":"tabresult","id":5,"ok":true,"focused":true,"opened":false,"tabId":42}
```
- `activate` holt einen bekannten Tab per `tabId` in den Vordergrund (inkl. Fenster).
- `focus` sucht die passende Seite und aktiviert sie; ist sie nicht offen, wird sie
geöffnet (`focused:false, opened:true`). Optional: `match` (`prefix` | `exact` |
`origin`, Default `prefix`), `open:false` (nicht öffnen), `activate:false`,
oder Suche per `title` statt `url`. Fragment (`#…`) und abschließende Slashes werden
beim Vergleich ignoriert.
### Ignorierte Nachrichten
| Nachricht | Verhalten |
|----------------------------------------------------|--------------------|
| alles ohne `"type":"tab"` (z.B. `{"cmd":"call",…}`) | wird ignoriert |
| ungültiges JSON | wird ignoriert |
## Installation (temporär, zum Entwickeln)
1. `about:debugging#/runtime/this-firefox` öffnen
2. **„Temporäres Add-on laden…”** → `manifest.json` in diesem Ordner auswählen
3. Server-Adresse ggf. unter *Einstellungen* im Popup anpassen (Default `ws://127.0.0.1:17655`)
Temporär geladene Add-ons verschwinden beim Firefox-Neustart. Für den Dauerbetrieb muss
das Add-on signiert werden (`web-ext sign`, AMO-Account) oder es wird Firefox ESR /
Developer Edition mit `xpinstall.signatures.required = false` verwendet.
Paket bauen:
```bash
npx web-ext lint
npx web-ext build # erzeugt web-ext-artifacts/*.zip -> signieren bzw. in .xpi umbenennen
```
## Signierung und Datenerhebung
Seit dem 3. November 2025 müssen neue Erweiterungen auf AMO Mozillas eingebautes
Einwilligungssystem bedienen. Im Manifest steht deshalb:
```json
"data_collection_permissions": { "required": ["browsingActivity"] }
```
Mozilla definiert Übermittlung als Daten, die *außerhalb des Add-ons oder des
lokalen Browsers* verarbeitet werden. Das Add-on gibt Tab-Titel und URLs an
SwyxTray weiter — also aus dem Browser heraus, wenn auch nur an eine lokale
Anwendung auf demselben Rechner und nicht ins Netz. `"none"` wäre eine
Untertreibung, `browsingActivity` beschreibt genau das (besuchte Seiten, URLs).
`strict_min_version` bleibt bewusst bei `115.0`, obwohl der Schlüssel erst ab
Firefox 140 ausgewertet wird. Ältere Versionen ignorieren ihn folgenlos; ein
Anheben auf `140.0` würde ESR 115 und ESR 128 ausschließen. `web-ext lint` meldet
dafür zwei Warnungen — die blockieren die Signierung nicht.
## Installation auf Windows (per SSH)
`deploy/deploy-windows.sh` zählt die Version hoch, baut das `.xpi`, überträgt es per
`scp` und führt `deploy/Install-SwyxTabBridge.ps1` auf dem Zielrechner aus:
```bash
./deploy/deploy-windows.sh # Testrechner, ohne Parameter
./deploy/deploy-windows.sh --keep-firefox # laufenden Firefox nicht beenden
./deploy/deploy-windows.sh --uninstall # rückgängig machen
```
Der nackte Aufruf erledigt alles: Version hochzählen, bei AMO signieren, übertragen,
Policy schreiben und den laufenden Firefox beenden (nur den aus dem Zielverzeichnis —
eine zweite Installation daneben bleibt offen). Ziel ist die Release-Installation, die
ausschließlich signierte Add-ons annimmt; jeder Lauf wird deshalb signiert. Ziel-Rechner,
Firefox-Verzeichnis sowie Signatur- und Neustart-Verhalten sind als Konstanten oben im
Skript voreingestellt.
Standardmäßig wird eine Enterprise-Policy (`force_installed`) geschrieben, sodass das
Add-on beim nächsten Firefox-Start ohne Rückfrage für alle Profile installiert wird.
Details, Signierung und Optionen: [deploy/README.md](deploy/README.md).
## Tests
Selbsttest der Kommandoverarbeitung ohne Firefox — `background.js` läuft mit gestubbten
`browser`-/`WebSocket`-APIs:
```bash
node test-server/test-background.mjs
```
Testserver, der SwyxTray simuliert (ohne Abhängigkeiten, nur Node):
```bash
node test-server/server.js # lauscht auf ws://127.0.0.1:17655
node test-server/server.js --log /pfad/x.log # anderes Protokoll
node test-server/server.js --no-log # nur Konsole
```
Der Server protokolliert Verbindungsaufbau, Anmeldung und Trennung mit Zeitstempel
auf der Konsole **und** in `test-server/swyx-tray.log`:
```
[2026-08-17 16:16:09.809] Verbindung geöffnet von 127.0.0.1.
[2026-08-17 16:16:09.809] Angemeldet: swyx-tab-bridge v1.0.12 (Aktionen: list, open, close, activate, focus; ohne Token)
[2026-08-17 16:16:12.314] Verbindung getrennt: swyx-tab-bridge v1.0.12 (Dauer 3 s).
```
Meldet sich eine Gegenstelle binnen drei Sekunden nicht mit `hello` an, wird das
als „unbekannte Gegenstelle" vermerkt. Das ist die Vorlage dafür, was SwyxTray
mitschreiben sollte.
| Eingabe | gesendete Nachricht |
|------------------------------------|--------------------------------------------------------|
| `list` / `list current` | `{"type":"tab","action":"list"}` |
| `open <url> [background]` | `{"type":"tab","action":"open","url":"…"}` |
| `close <tabId>` | `{"type":"tab","action":"close","tabId":42}` |
| `activate <tabId>` | `{"type":"tab","action":"activate","tabId":42}` |
| `focus <url> [titel…]` | `{"type":"tab","action":"focus","url":"…"}` |
| `raw {…}` | beliebiges JSON (ohne `type:"tab"` bleibt es unbeantwortet) |
| `quit` | beenden |
## Einstellungen
Die Einstellungsseite zeigt oben, ob das Add-on mit der Tray-App verbunden ist —
Zustand, Serveradresse, Zeitpunkt des Verbindungsaufbaus und der letzte Fehler,
laufend aktualisiert. Dieselbe Anzeige gibt es kompakt im Popup.
Über das Symbol in der Symbolleiste → *Einstellungen*:
- **WebSocket-Server** — `ws://…` oder `wss://…` (Default `ws://127.0.0.1:17655`)
- **Token** — optionales Shared Secret. Ist es gesetzt, geht es in der
`hello`-Nachricht mit.
- **Automatisch verbinden** — Auto-Reconnect mit exponentiellem Backoff (1 s → max. 30 s)
Das Symbol zeigt den Verbindungszustand: kein Badge = verbunden, `…` = Verbindungsaufbau,
`!` = getrennt.
## Dateien
| Datei | Zweck |
|-----------------------------------|---------------------------------------------------|
| `manifest.json` | Add-on-Manifest (MV2, persistenter Hintergrund) |
| `background.js` | WebSocket-Client, Reconnect, Aktionen |
| `popup.html/js` | Statusanzeige, Verbinden/Trennen |
| `options.html/js` | Server-URL, Token, Auto-Connect |
| `test-server/server.js` | Testserver (simuliert SwyxTray) |
| `test-server/test-background.mjs` | Selbsttest der Kommandoverarbeitung |
| `deploy/deploy-windows.sh` | Version hochzaehlen, bauen, per SSH ausrollen |
| `deploy/Install-SwyxTabBridge.ps1`| Installation auf dem Windows-Rechner |
## Hinweise
- **Manifest V2** ist bewusst gewählt: Nur mit persistentem Hintergrundskript bleibt die
WebSocket-Verbindung dauerhaft offen. Unter MV3 (nicht-persistente Event-Page) würde die
Verbindung nach Leerlauf abgebaut. Firefox unterstützt MV2 weiterhin.
- `ws://127.0.0.1` ist erlaubt (das Add-on läuft im `moz-extension:`-Kontext, keine
Mixed-Content-Blockade). Für Verbindungen über das Netzwerk `wss://` verwenden.
- SwyxTray sollte nur auf `127.0.0.1` lauschen — sonst kann jeder im Netz Tabs öffnen,
schließen und die Tab-Liste mitlesen.
- Die Permission `tabs` ist nötig, um `title` und `url` der Tabs zu lesen.