Linux Chromium already had WebXR APIs in Blink, but lacked support for
immersive-vr on Linux. My main contribution was getting WebXR over OpenXR
working again on Linux and upstreaming the backend and sandbox. The path
connects Chromium to runtimes such as Monado, SteamVR, and WiVRn.
Each runtime handles its own headset, controllers, and compositor.
This is a personal hobby project, not an official Chromium effort. I work on it for fun. I send changes upstream when there is a concrete need.
This is the first milestone: a basic version, not a finished product. I plan to keep testing it with more runtimes, hardware, and distributions.
How it works
An immersive session uses several Chromium processes:
flowchart LR
Page["Web page<br/>WebXR and WebGL"]
Blink["Blink XR"]
Browser["Browser process<br/>permissions and session requests"]
XR["XR device service<br/>Linux sandbox"]
Vulkan["OpenXR Vulkan backend"]
Loader["OpenXR loader"]
Runtime["Monado, SteamVR or WiVRn"]
GPU["GPU process<br/>SharedImages"]
Page --> Blink
Blink <--> Browser
Browser <--> XR
Page <--> GPU
XR <--> GPU
XR --> Vulkan
XR --> Loader --> Runtime
- Blink and the browser process handle WebXR API calls, permissions and session requests.
- The XR device service owns the OpenXR instance and session, Vulkan device and frame loop. The OpenXR loader connects it to the active runtime.
- The GPU process manages the SharedImages used to transfer rendered frames.
The page talks to the XR service through Chromium’s Mojo interfaces, not directly to the runtime.
For each frame, the service waits for the runtime, locates the headset views, and sends their poses to the page. After drawing, the page submits the frame; the service copies its images into OpenXR swapchains and submits it to the runtime.
Sandbox
The XR device service loads the runtime and graphics drivers, accesses the GPU, and connects to the runtime’s compositor socket inside Chromium’s Linux sandbox:
- Before lockdown: Chromium reads the active runtime manifest and prepares the runtime and graphics-library dependencies.
- After lockdown: Seccomp and the file broker remain active. The broker grants access only to the manifest, libraries, Vulkan driver, GPU devices and runtime data the service needs.
- For runtime IPC: The service uses brokered Unix-domain sockets to reach the runtime. It does not enter a network namespace, which would break those connections.
Socket and file access depends on the runtime. Monado uses
monado_comp_ipc; WiVRn uses wivrn/comp_ipc. SteamVR also needs shared memory
and log access.
Some runtime manifests use a relative library path containing .., which the
file broker rejects. Chromium loads the library before sandboxing, then uses
RTLD_NOLOAD to alias the loader’s path to that already-loaded library. This
lets the loader use it without reopening the rejected path. This fix is part of
the WiVRn sandbox change,
merged on November 4, 2026.
Chromium versions and support
| Chromium milestone | Linux WebXR/OpenXR support |
|---|---|
| M152 | Fixes two OpenXR session teardown crashes. |
| M154 | Adds the Linux OpenXR backend; runtime support is not enabled yet. |
| M156 | Runs the XR device service in the Linux sandbox. |
| M157 | Enables end-to-end WebXR over OpenXR and frame synchronization. Turn it on with --enable-features=OpenXR; it is off by default. |
| M158 | Adds WebXR Layers support. |
| M159 | Adds WiVRn sandbox support. Chromium 159.0.8135.0 was tested in Flatpak and native builds. |
Flatpak can sandbox Chromium, but this custom package lacks Flathub’s Chromium sandbox patches, so it only uses Flatpak’s app sandbox. The native build runs the XR service in Chromium’s sandbox.
Upstream work and what’s next
These changes have merged: the Linux backend,
runtime enablement,
XR sandbox,
frame synchronization,
WebXR Layers, and
WiVRn sandbox support.
OpenXR still needs the OpenXR feature enabled; enabling it by default on
Linux is
under review.
Why upstreaming takes time
My local session is one test. The changes also have to fit Chromium’s architecture and security rules and pass its builders.
Landing, reverting and relanding
The first Linux OpenXR backend was reverted after failing the Linux CFI bot’s indirect-call checks. It was relanded after those failures were fixed.
The first XR sandbox change was reverted after breaking a Cast build. It was relanded after the build issue was fixed.
Earlier Linux browser attempts
Before my first chromium-webxr-linux commit in April 2026, the
mrxz/webxr-linux project collected two
Linux experiments: a Chromium 117 patch using OpenXR, and Firefox patches using
OpenVR on Linux/X11. The Chromium patch required --no-sandbox; the Firefox
author described that work as a hack rather than a full implementation. These
were separate attempts from the implementation I later got working and
upstreamed to Chromium.
Architecture and security review
Reviewers asked me to keep platform-specific code scoped, remove redundant checks, and drop a swapchain-format option without a clear need. Sandbox review narrowed file and socket access. CFI review asked for narrowly scoped suppressions.
The test matrix is broader than a headset
The changes touch Blink, the XR service, Vulkan, browser UI, and sandbox policy. CFI and Cast builders found issues that my Monado session did not.