Eximia Download

Eximia docs

WebView scheme

How an SLMEximia app's WebView loads its HTML, JavaScript, CSS, and assets. The summary lives in ADR-005; this doc is the implementation contract.


The scheme

The WebView in an SLMEximia app loads:

slm-eximia://app/index.html

app is the fixed authority for app source code. res is reserved for runtime-bundled resources (icons, the dev console). No other authorities are valid; the scheme handler MUST return HTTP 404 for any authority it doesn't recognise.

Allowed paths

AuthorityMaps toUse
appassets/www/ (Android) · bundle www/ (iOS)App source: HTML, JS, CSS, images, fonts.
resruntime-bundled resourcesInternal: dev-mode console, error pages.

A plugin that wants to expose its own assets at a custom authority MUST declare it in its plugin.json (future work — not v1.0).


Android implementation

Component

androidx.webkit.WebViewAssetLoader, configured via the runtime in SLMEximiaWebView.kt.

Wiring

val assetLoader = WebViewAssetLoader.Builder()
    .setDomain("app.slm-eximia.local")   // Used internally by WebViewAssetLoader
    .setHttpAllowed(false)
    .addPathHandler("/", AssetsPathHandler(context))
    .build()

webView.webViewClient = object : WebViewClientCompat() {
    override fun shouldInterceptRequest(
        view: WebView, request: WebResourceRequest
    ): WebResourceResponse? = assetLoader.shouldInterceptRequest(request.url)
}

WebViewAssetLoader only supports https:// schemes natively. The SLMEximia runtime extends this by intercepting slm-eximia://app/* URLs and translating them to internal https://app.slm-eximia.local/* for WebViewAssetLoader, then translates back outbound. This keeps the public URL clean while reusing the well-tested handler.

Cookies and origin

The browser sees slm-eximia://app as the origin for all requests from the loaded page. Cookies are scoped to that origin; localStorage, indexedDB, and cacheStorage are isolated likewise.

CORS

Cross-origin requests (fetch('https://api.example.com/x') from inside the WebView) are subject to the standard CORS rules. The remote server must respond with Access-Control-Allow-Origin: slm-eximia://app or *. Apps that need to call non-CORS endpoints route them through a plugin — the plugin makes the request natively.


iOS implementation

Component

WKURLSchemeHandler, registered on the WKWebViewConfiguration in SLMEximiaSchemeHandler.swift.

Wiring

let cfg = WKWebViewConfiguration()
cfg.setURLSchemeHandler(SLMEximiaSchemeHandler(bundle: .main),
                        forURLScheme: "slm-eximia")
let webView = WKWebView(frame: .zero, configuration: cfg)
webView.load(URLRequest(url: URL(string: "slm-eximia://app/index.html")!))

SLMEximiaSchemeHandler reads the requested URL, walks the requested path relative to the bundle's www/ directory (or Resources/), and emits a URLResponse with the right MIME type plus the file contents.

MIME type detection

The handler maps file extension → MIME type via a static table (html → text/html, js → application/javascript, css → text/css, png/jpg/gif/webp → image/*, woff/woff2 → font/*, etc.). Unknown extensions get application/octet-stream.

Range requests

For media files (audio, video), the handler MUST honour Range request headers and return 206 Partial Content with Accept-Ranges: bytes. Without this, large media playback stalls on iOS.

Cookies and origin

WKWebView's cookie store is per WKHTTPCookieStore instance, and we use the default. Origin is slm-eximia://app — consistent with Android.


Disallowed behaviours

The scheme handler MUST NOT:

  • Serve any path outside the app's www/ directory (no ../ traversal).
  • Serve /etc/, /var/, or any absolute filesystem path.
  • Return responses for any URL whose scheme is not slm-eximia.
  • Honor javascript: URLs inside the page (configured via webview options).

The runtime MUST also configure:

  • webView.allowFileAccess = false (Android)
  • webView.allowContentAccess = false (Android)
  • webView.allowFileAccessFromFileURLs = false (Android)
  • webView.allowUniversalAccessFromFileURLs = false (Android)

Equivalent settings on iOS are the defaults for WKWebView.


Dev mode

When the CLI runs slm-eximia dev, the WebView is configured to load from a development server (typically http://localhost:5173/index.html) instead of slm-eximia://app/. The scheme handler is still installed but inactive for the dev session. See ../cli/docs/commands/dev.md.

For dev mode to work, the app's AndroidManifest.xml must allow android:usesCleartextTraffic="true" for localhost only — the CLI emits a network_security_config.xml automatically when targeting dev.


Testing

The runtime test suite covers:

  • slm-eximia://app/index.html loads with status 200 and right MIME.
  • slm-eximia://app/../etc/passwd returns 404 (path traversal blocked).
  • slm-eximia://other/x returns 404 (unknown authority).
  • Range requests on a large file return 206 with correct partial body (iOS).
  • Origin checks: a fetch('/api/x') from the page makes a request with Origin: slm-eximia://app.

See ../android/docs/SLMEximiaWebView.md and ../ios/docs/SLMEximiaSchemeHandler.md for the implementation detail.