libaura-webview: Web pages in AURA
libs/aura-webview provides the AURA element WebView: a full Chromium page in the scene graph, using the Chromium Embedded Framework (CEF). The page supports touch interaction and communicates with C++ code through a WebChannel. Custom JavaScript can be injected into any page.
WebView {
id: page
url: "https://example.org"
script: "document.addEventListener('DOMContentLoaded', () => { ... })"
size: parent.width - 48, parent.height - 104
}
Example and tests: tests/ui-webview/webview.aura and tests/test_webview.cpp.
Building
| Option | Meaning |
|---|---|
-DAURA_WITH_WEBVIEW=ON |
Builds libaura-webview and links it into aura-view and aura_webview_tests (preset webview). Default: OFF. |
-DAURA_CEF_ROOT=<dir> |
Uses an unpacked CEF distribution instead of downloading it |
AURA_CEF_VERSION |
CEF version (default 156.0.14, Chromium 156.0.8078.48) |
- Download: Without
AURA_CEF_ROOT, the build downloads the “minimal” distribution from Spotify's CDN (cef-builds.spotifycdn.com): approximately 330 MB (x86_64) or 430 MB (arm64). SHA1 checksums are incmake/Cef.cmake. - Cache: For development, download and unpack it once, for example under
~/.cache/aura/cef/, then use-DAURA_CEF_ROOT=~/.cache/aura/cef/cef_binary_<version>_<platform>_minimal. - Wrapper: The build compiles
libcef_dll_wrapper(the C++ API overlibcef.so's C API) from the distribution's sources, using our compiler. - Runtime directory:
build/<preset>/cef/contains symlinks tolibcef.soand the resources (*.pak,icudtl.dat,v8_context_snapshot.bin,locales/), plus theaura-webview-helperexecutable. Programs locatelibcef.sothrough their rpath; the directory can be overridden at runtime withAURA_WEBVIEW_DIR.
Architecture
| Part | Responsibility |
|---|---|
WebViewNode (aura/webview/webview.h) |
The node: renders the page, forwards touch input, WebChannel, scripts |
aura-webview-helper |
CEF subprocesses (renderer, GPU, network). In the renderer, it sets up window.aura and executes scripts. The application's main() remains free of CEF. |
aura::ui::registerElementType (aura/ui/elements.h) |
Element types from other libraries for the loader. This keeps aura-ui independent of CEF. |
aura::post() (aura/core/tasks.h) |
Transfers work to the UI thread safely. The loop processes it before each frame; the aura-view server does so on every request (aura::runPosted()). |
- Rendering: CEF renders off-screen in software (
ozone-platform=headless, without GPU) into a BGRA buffer. The node draws it as a Skia image, with open dropdowns (<select>) above it. No X11 or Wayland server is required, which suits a kiosk using KMS/DRM. - Threads: CEF runs its own message loop (
multi_threaded_message_loop). A new image wakes the application (Application::wakeUp), andaura-viewdetects it throughframeCount(). - Startup: CEF starts with the first WebView; the browser starts on its first draw, when the node knows its size. A WebView that is never displayed costs nothing.
- Input: Press, drag, and release are forwarded to the page as touch events. Chromium turns them into taps and inertial scrolling. Links with
target=_blankopen in the same view. - Cache: Each process has its own
/tmp/aura-webview-<pid>directory (withcef.log), removed byshutdown(). Cookies and data do not survive a restart.
WebChannel and scripts
Every page has window.aura before its own scripts run.
const sum = await aura.call("add", 2, 3); // JavaScript -> C++, Promise
aura.on("cart", (value) => render(value)); // C++ -> JavaScript
#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;");
- Values: JSON (
AuraJson). Arguments toaura.callarrive as an array. - Handlers: They run on the UI thread and may access the scene graph and application state. An exception rejects the Promise with its message; an unknown name does the same.
emit,runJavaScript: Apply to the currently loaded page; otherwise they do nothing.- Scripts:
addUserScript()and AURA'sscript:run in every new document in the view, in the main frame, before the page's own scripts. Adding a script or changingscriptalso executes it immediately in the current page. An error goes to the page's console and does not prevent the other scripts from running. - Transport: CEF's message router (
auraQuery) for calls,ExecuteJavaScriptfor events, and process messages for script lists.
Application integration
int main(int argc, char** argv)
{
// Before building the first UI: register WebView for the loader;
// locale: Chromium language (default en-US)
aura::webview::setup(argc, argv, {.locale = "de"});
...
aura::webview::shutdown(); // closes all browsers and stops CEF
}
aura-view initializes CEF when built with WebView (aura::webview then defines the preprocessor symbol AURA_WITH_WEBVIEW). Without the library, the loader reports “element type 'WebView' is not part of this program” and uses the compiled version. A file containing WebView can only be compiled if the program links aura::webview.
Preview (aura-view, VS Code)
- Built with WebView:
aura-viewdisplays WebViews in its window, with--render, and in the server. --render: Waits until the page has not repainted for 1.5 s (at most 20 s).- Server: While a WebView is open, it reports
animating, and the extension requests an image approximately every 33 ms. A response only contains a PNG if Chromium has repainted. - Interaction: A click is a tap. Dragging with the mouse button pressed scrolls; the
movecommand was added for this. Pausing playback in the preview also pauses the page. - Setting: The preview's
aura-view(aura.preview.command) must be built with WebView.
Tests
aura_webview_tests (tests/test_webview.cpp, tests/ui-webview/webview.aura) builds a dialog containing a WebView once through compiled code and once through the loader. It loads a data: page without network access and checks:
- The result of
aura.call, - Errors and unknown handlers,
- The script defined in AURA,
emitandrunJavaScript,- The page's pixels in the node.
Runtime and integration
- The target system needs the system libraries required by the selected CEF distribution, along with its resources and locales.
- The integration currently starts CEF with
no_sandbox. Account for that when selecting and embedding web content. - Touch interaction is forwarded to Chromium; validate keyboard, IME and scaling requirements for the particular application.
- The CEF distribution contains Chromium and other third-party components. Their license notices belong with the distribution; see Dependencies & licenses.
docs/aura-webview.md · Download Markdown