# libaura-webview: Webseiten in AURA

`libs/aura-webview` bringt das AURA-Element `WebView`: eine vollwertige Chromium-Seite im Szenengraph, über das Chromium Embedded Framework (CEF). Die Seite ist per Touch bedienbar und spricht über einen WebChannel mit dem C++-Code. Eigenes JavaScript lässt sich in jede Seite einschleusen.

```qml
WebView {
    id: page
    url: "https://example.org"
    script: "document.addEventListener('DOMContentLoaded', () => { ... })"
    size: parent.width - 48, parent.height - 104
}
```

Beispiel und Tests: `tests/ui-webview/webview.aura` und `tests/test_webview.cpp`.

## Bauen

| Option | Bedeutung |
|---|---|
| `-DAURA_WITH_WEBVIEW=ON` | baut `libaura-webview`, verlinkt sie in `aura-view` und `aura_webview_tests` (Preset `webview`). Standard: `OFF`. |
| `-DAURA_CEF_ROOT=<dir>` | nimmt eine entpackte CEF-Distribution, statt sie herunterzuladen |
| `AURA_CEF_VERSION` | die CEF-Version (Standard 156.0.14, Chromium 156.0.8078.48) |

- **Download:** Ohne `AURA_CEF_ROOT` lädt der Build die „minimal“-Distribution vom Spotify-CDN (`cef-builds.spotifycdn.com`): etwa 330 MB (x86_64) bzw. 430 MB (arm64). Die SHA1-Prüfsummen stehen in `cmake/Cef.cmake`.
- **Cache:** Zum Entwickeln einmal z. B. nach `~/.cache/aura/cef/` laden und entpacken, dann `-DAURA_CEF_ROOT=~/.cache/aura/cef/cef_binary_<version>_<platform>_minimal`.
- **Wrapper:** `libcef_dll_wrapper` (die C++-API über der C-API von `libcef.so`) baut der Build aus den Quellen der Distribution, mit unserem Compiler.
- **Laufzeitverzeichnis:** `build/<preset>/cef/` enthält `libcef.so`, die Ressourcen (`*.pak`, `icudtl.dat`, `v8_context_snapshot.bin`, `locales/`) als Symlinks und das Hilfsprogramm `aura-webview-helper`. Programme finden `libcef.so` über ihren rpath; zur Laufzeit lässt sich das Verzeichnis mit `AURA_WEBVIEW_DIR` umstellen.

## Aufbau

| Teil | Aufgabe |
|---|---|
| `WebViewNode` (`aura/webview/webview.h`) | der Knoten: rendert die Seite, leitet Touch weiter, WebChannel, Skripte |
| `aura-webview-helper` | die CEF-Unterprozesse (Renderer, GPU, Netzwerk). Im Renderer richtet er `window.aura` ein und führt die Skripte aus. Das `main()` der Anwendung bleibt frei von CEF. |
| `aura::ui::registerElementType` (`aura/ui/elements.h`) | Elementtypen anderer Bibliotheken für den Loader. `aura-ui` hängt so nicht von CEF ab. |
| `aura::post()` (`aura/core/tasks.h`) | übergibt Arbeit thread-sicher an den UI-Thread. Die Schleife arbeitet sie vor jedem Frame ab, der `aura-view`-Server bei jeder Anfrage (`aura::runPosted()`). |

- **Rendering:** CEF rendert ohne Fenster in Software (`ozone-platform=headless`, ohne GPU) in einen BGRA-Puffer. Der Knoten zeichnet ihn als Skia-Bild, darüber offene Auswahllisten (`<select>`). Ein X11- oder Wayland-Server ist nicht nötig, das passt zum Kiosk mit KMS/DRM.
- **Threads:** CEF läuft mit eigener Nachrichtenschleife (`multi_threaded_message_loop`). Ein neues Bild weckt die Anwendung (`Application::wakeUp`), und `aura-view` merkt es an `frameCount()`.
- **Start:** CEF startet erst mit der ersten WebView, der Browser mit dem ersten Zeichnen: Erst dann kennt der Knoten seine Größe. Eine nie gezeigte WebView kostet nichts.
- **Eingabe:** Drücken, Ziehen und Loslassen gehen als Touch-Ereignisse an die Seite. Chromium macht daraus Tippen und Scrollen mit Schwung. Links mit `target=_blank` öffnen in derselben Ansicht.
- **Cache:** je Prozess ein eigenes Verzeichnis `/tmp/aura-webview-<pid>` (mit `cef.log`), das `shutdown()` löscht. Cookies und Daten bleiben nicht über einen Neustart.

## WebChannel und Skripte

Jede Seite hat `window.aura`, schon bevor ihre eigenen Skripte laufen.

```js
const sum = await aura.call("add", 2, 3);   // JavaScript -> C++, Promise
aura.on("cart", (value) => render(value));  // C++ -> JavaScript
```

```cpp
#include "aura/webview/webview.h"

dialog->page->handle("add", [](const auto& args) {
	return AuraJson(args[0].toInt() + args[1].toInt());
});
dialog->page->emit("cart", {{"items", 3}});
dialog->page->runJavaScript("document.body.style.zoom = 1.2");
dialog->page->addUserScript("window.kiosk = true;");
```

- **Werte:** JSON (`AuraJson`). Die Argumente von `aura.call` kommen als Array.
- **Handler:** Sie laufen auf dem UI-Thread und dürfen den Szenengraph und den App-Zustand anfassen. Eine Exception lehnt das Promise mit ihrer Meldung ab, ebenso ein unbekannter Name.
- **`emit`, `runJavaScript`:** wirken auf die gerade geladene Seite, sonst passiert nichts.
- **Skripte:** `addUserScript()` und `script:` in AURA laufen in jedem neuen Dokument der Ansicht, im Hauptframe, vor den Skripten der Seite. Wird ein Skript hinzugefügt oder `script` geändert, läuft es auch gleich in der aktuellen Seite. Ein Fehler darin landet in der Konsole der Seite und hält die übrigen Skripte nicht auf.
- **Transport:** CEFs Message-Router (`auraQuery`) für Aufrufe, `ExecuteJavaScript` für Ereignisse, Prozess-Nachrichten für die Skriptlisten.

## Anwendung

```cpp
int main(int argc, char** argv)
{
	// vor dem ersten UI-Aufbau: WebView für den Loader;
	// locale: Sprache von Chromium (Standard en-US)
	aura::webview::setup(argc, argv, {.locale = "de"});
	...
	aura::webview::shutdown();  // schließt alle Browser, beendet CEF
}
```

`aura-view` initialisiert CEF, wenn es mit WebView gebaut ist (`aura::webview` setzt dann das Präprozessor-Symbol `AURA_WITH_WEBVIEW`). Ohne die Bibliothek meldet der Loader „element type 'WebView' is not part of this program“ und nimmt die kompilierte Fassung. Eine Datei mit `WebView` lässt sich nur kompilieren, wenn das Programm `aura::webview` linkt.

## Vorschau (aura-view, VS Code)

- **Gebaut mit WebView:** `aura-view` zeigt WebViews im Fenster, bei `--render` und im Server.
- **`--render`:** wartet, bis die Seite 1,5 s lang nicht mehr neu gezeichnet hat (höchstens 20 s).
- **Server:** Solange eine WebView offen ist, meldet er `animating`, und die Erweiterung fragt etwa alle 33 ms nach einem Bild. Eine Antwort enthält nur dann ein PNG, wenn Chromium neu gezeichnet hat.
- **Bedienen:** Ein Klick ist ein Tippen. Mit gedrückter Maus ziehen scrollt, dafür ist der Befehl `move` neu. Die Wiedergabe-Pause der Vorschau hält auch die Seite an.
- **Einstellung:** Das `aura-view` der Vorschau (`aura.preview.command`) muss mit WebView gebaut sein.

## Tests

`aura_webview_tests` (`tests/test_webview.cpp`, `tests/ui-webview/webview.aura`) baut einen Dialog mit `WebView` einmal kompiliert und einmal über den Loader. Er lädt eine `data:`-Seite, ohne Netz, und prüft:
- das Ergebnis von `aura.call`,
- Fehler und unbekannte Handler,
- das Skript aus AURA,
- `emit` und `runJavaScript`,
- die Pixel der Seite im Knoten.

## Laufzeit und Integration

- Das Zielsystem benötigt die Systembibliotheken der verwendeten CEF-Distribution sowie deren Ressourcen und Locales.
- Die Integration startet CEF derzeit mit `no_sandbox`. Das muss bei der Auswahl und Einbindung von Webinhalten berücksichtigt werden.
- Touch-Interaktion wird an Chromium weitergeleitet; Tastatur-, IME- und Skalierungsanforderungen sind für die konkrete Anwendung zu prüfen.
- Die CEF-Distribution enthält Chromium und weitere Drittkomponenten. Ihre Lizenzhinweise gehören zur Distribution; siehe [Dependencies & Lizenzen](dependencies.md).
