# Recherche-Ergebnis: WebRTC im Tauri-WebView (Mobile + Desktop) Ticket: [`../issues/01-research-webrtc-tauri-mobile.md`](../issues/01-research-webrtc-tauri-mobile.md) Map: [`../map.md`](../map.md) Stand: 14.08.2026 Methodik: Primärquellen (Apple/WebKit, AOSP, Chromium, Microsoft Learn, W3C/IETF, wry-/Tauri-Quellcode auf den tatsächlich aufgelösten Versions-Tags). Blogposts nur als Hinweisgeber, jeweils mit Datum markiert. --- ## 1. Kernantwort | Plattform | Antwort | Aufwand | Blockierender Punkt | |---|---|---|---| | **iOS** (WKWebView) | **Ja** | 1 Datei | `NSMicrophoneUsageDescription` in `src-tauri/Info.ios.plist` | | **Android** (System WebView) | **Ja** | 2 Manifest-Zeilen | `RECORD_AUDIO` **und** `MODIFY_AUDIO_SETTINGS` | | **Windows** (WebView2) | **Ja** | keiner | — (funktioniert out of the box, mit WebView2-eigenem Prompt) | | **Linux** (WebKitGTK 4.1) | **Nein** | hoch / teils unlösbar | Drei unabhängige Gates, siehe §5 | **Fazit für die Map:** Die im Council-Verdikt als Risiko 2 geführte „Mobile-WebRTC-Unbekannte" ist **aufgelöst — positiv**. Android und iOS tragen WebRTC im WebView. Das Voice-Signaling-Design ist für die Mobile-Hälfte der Zielplattformen nicht wertlos. Ticket 04 (*Voice-Topologie*) ist damit entblockt. **Die neue schlechte Nachricht liegt woanders:** Nicht Mobile ist der Problemfall, sondern **Linux**. Dort ist WebRTC in WebKitGTK weder einkompiliert noch zur Laufzeit aktivierbar noch berechtigt. Das ist keine Kleinigkeit für ein Projekt, dessen Zielgruppe Selbsthoster sind. --- ## 2. Ausgangslage im Repo (Versionsanker) Diese Recherche gilt gegen die Versionen, die `rustification-client` heute tatsächlich auflöst: | Komponente | Version | Herkunft | |---|---|---| | `@tauri-apps/cli` | **2.11.4** | `package-lock.json` | | `tauri` (Rust) | `"2"` → aktuell **2.11.5** (01.07.2026) | `src-tauri/Cargo.toml`, crates.io | | `tauri-runtime-wry` | **2.11.4** (30.06.2026) | crates.io | | → `wry` | Anforderung `^0.55.0` → **0.55.1** (04.05.2026) | crates.io Dependency-Auflösung | Das ist der wichtigste Kontext des ganzen Dokuments: **wry 0.56.0 (30.07.2026) hat die Permission-Lage grundlegend geändert**, aber `tauri-runtime-wry 2.11.4` fordert `^0.55.0` und kann 0.56 nicht ziehen (SemVer bei `0.x`: `>=0.55.0, <0.56.0`). Alles unten Beschriebene ist gegen **wry 0.55.1** verifiziert. Weitere relevante Repo-Fakten: - `src-tauri/gen/android` und `src-tauri/gen/apple` existieren **noch nicht** — Mobile ist nie initialisiert worden. Es gibt also noch nichts zu migrieren. - `app.security.csp` ist `null`. Tauri v2 hat **keine Default-CSP** ([v2.tauri.app/security/csp](https://v2.tauri.app/security/csp/): *„The CSP protection is only enabled if set on the Tauri configuration file."*). Für WebRTC ist das irrelevant (siehe §7.5), aber es ist gut zu wissen, dass hier nichts im Weg steht. - Es existiert **kein** WebRTC- oder WebSocket-Code im Client. Grüne Wiese. --- ## 3. iOS — **Ja** ### 3.1 Versionsuntergrenze `getUserMedia` ist in `WKWebView` (nicht nur Safari) seit **iOS 14.3** verfügbar. Primärquelle: WebKit-Blog, *MediaRecorder API*, Youenn Fablet, **23.11.2020** ([webkit.org/blog/11353](https://webkit.org/blog/11353/mediarecorder-api/)), wörtlich: > „Speaking of Safari in latest iOS 14.3 beta and local capture, `navigator.mediaDevices.getUserMedia` > can now be exposed to WKWebView applications. `navigator.mediaDevices.getUserMedia` is automatically > exposed **if the embedding application is able to natively capture either audio or video**." Der Satzteil „able to natively capture" ist die eigentliche Bedingung: Er bedeutet **die Usage-Description-Keys sind in der Info.plist vorhanden**. Kein Entitlement, keine private API. Tauris eigener Default `bundle.iOS.minimumSystemVersion` ist `"14.0"` — für WebRTC muss man das faktisch auf **14.3** oder höher lesen. Praktisch relevanter Floor ist ohnehin **iOS 15.0**, weil erst dort der `WKUIDelegate`-Callback existiert, den wry registriert (siehe 3.3). ### 3.2 Secure Context — passt, ohne Tricks `getUserMedia` verlangt einen Secure Context. Tauri liefert das Frontend auf iOS (wie macOS und Linux) unter dem Custom-Scheme **`tauri://localhost`** aus (`crates/tauri/src/manager/mod.rs`, `tauri_protocol_url`). Ein Custom-Scheme allein ist *nicht* vertrauenswürdig — aber WebKit prüft den **Host unabhängig vom Schema** (`Source/WebCore/page/SecurityOrigin.cpp`): ```cpp if (LegacySchemeRegistry::shouldTreatURLSchemeAsSecure(protocol)) return true; if (SecurityOrigin::isLocalHostOrLoopbackIPAddress(host)) return true; ``` Host ist `localhost` ⇒ potentially trustworthy ⇒ Secure Context. Der aus Blogposts bekannte `_registerURLSchemeAsSecure`-Hack (private API) ist **nicht nötig**. ### 3.3 Was wry bereits erledigt — verifiziert im Quellcode wry registriert einen `WKUIDelegate` und darin den Media-Capture-Callback. Quelle: `src/wkwebview/class/wry_web_view_ui_delegate.rs` am Tag **`wry-v0.55.1`**: ```rust #[unsafe(method(webView:requestMediaCapturePermissionForOrigin:initiatedByFrame:type:decisionHandler:))] fn request_media_capture_permission( &self, _webview: &WryWebView, _origin: &WKSecurityOrigin, _frame: &WKFrameInfo, _capture_type: WKMediaCaptureType, decision_handler: &Block, ) { (*decision_handler).call((WKPermissionDecision::Grant,)); } ``` Drei Beobachtungen, alle wichtig: 1. **Kein `#[cfg(target_os = "macos")]`.** Die Methode wird auf iOS mitkompiliert. (In `dev`/0.56 steht dort `#[cfg(not(macos_12_unavailable))]` — ein Flag, das der `build.rs` nur unter `target_os = "macos"` setzt; auch dort bleibt iOS also drin.) 2. **In 0.55.1 wird bedingungslos `Grant` zurückgegeben.** Es gibt in dieser Version gar keinen `permission_handler` — `WryWebViewUIDelegateIvars` hat das Feld schlicht nicht. Der WebKit-Prompt entfällt damit; es bleibt genau **ein** Prompt, nämlich der des Betriebssystems (TCC). 3. Apple dokumentiert den Default ohne Delegate-Implementierung als `WKPermissionDecision.prompt` — also **nicht** Deny ([Apple Developer](https://developer.apple.com/documentation/webkit/wkuidelegate/webview(_:requestmediacapturepermissionfor:initiatedbyframe:type:decisionhandler:)), verfügbar ab iOS 15.0 / macOS 12.0). wry macht daraus ein Grant. Sicherheitsrelevant, siehe §7.6. `allowsInlineMediaPlayback` setzt wry auf iOS hart auf `true` — relevant, sobald der Remote-Stream in ein `