Roamium

Roamium is the Chromium browser engine binary for TermSurf. It wraps libtermsurf_chromium (a C shared library built from the Chromium fork) in a ~400-line Rust binary that handles Unix socket IPC, protobuf message dispatch, and process lifecycle.

How It Works

The GUI (Wezboard) spawns one Roamium process per browser profile. Each process serves exactly one profile — one set of cookies, storage, and cache. This is a hard constraint imposed by Chromium's BrowserContext.

Startup sequence:

  1. GUI spawns Roamium with --ipc-socket, --user-data-dir, and --listen-socket
  2. Roamium calls ts_content_main to enter Chromium's message loop
  3. Chromium initializes, fires the on_initialized callback
  4. Roamium creates a BrowserContext and connects to the GUI socket
  5. Roamium sends ServerRegister with its profile name
  6. GUI sends CreateTab with a URL and dimensions
  7. Chromium creates a WebContents, fires on_tab_ready
  8. Roamium sends TabReady back to the GUI
  9. Chromium renders and sends CaContext (GPU layer ID) to the GUI

Architecture

Roamium follows a two-layer pattern designed to be reusable across browser engines:

  • libtermsurf_chromium — a C shared library that wraps Chromium's embedding API. Exports ts_* functions for lifecycle, navigation, input forwarding, and state management. Built from the Chromium fork.
  • Roamium — a Rust binary that links the C library and handles IPC. Parses command-line args, connects to the GUI socket, dispatches protobuf messages to ts_* FFI calls, and relays Chromium callbacks back as protobuf messages.

Source Layout

File Purpose
main.rs Entry point, arg parsing, callback registration, Chromium message loop
dispatch.rs Message dispatch — routes protobuf messages to FFI calls, relays callbacks
ipc.rs Unix socket connection, length-prefixed protobuf framing, reader loop
ffi.rs FFI bindings to libtermsurf_chromium C functions

C API

The ts_* functions exported by libtermsurf_chromium:

Lifecycle

FunctionPurpose
ts_content_mainEnter Chromium's message loop (blocks)
ts_set_on_initializedRegister initialization callback
ts_post_taskPost a task to the UI thread
ts_quitShut down Chromium

Profiles and Tabs

FunctionPurpose
ts_create_browser_contextCreate a profile (BrowserContext)
ts_create_web_contentsCreate a browser tab
ts_create_devtools_web_contentsCreate a DevTools tab
ts_destroy_web_contentsClose a tab

Navigation and Input

FunctionPurpose
ts_load_urlNavigate to a URL
ts_forward_mouse_eventForward mouse click
ts_forward_mouse_moveForward mouse movement
ts_forward_scroll_eventForward scroll
ts_forward_key_eventForward keyboard input

State

FunctionPurpose
ts_set_focusSet focus state (browse/control mode)
ts_set_color_schemeSet dark/light mode
ts_set_view_sizeResize the viewport

Callbacks

Chromium fires callbacks on the UI thread. Roamium converts them to protobuf messages and sends them to the GUI:

CallbackProtobuf MessagePurpose
on_tab_readyTabReadyTab created, tab_id assigned
on_ca_context_idCaContextGPU layer ready for compositing
on_url_changedUrlChangedPage navigated
on_loading_stateLoadingStateLoading started/finished
on_title_changedTitleChangedPage title updated
on_cursor_changedCursorChangedCursor type changed (pointer, text, etc.)
on_target_url_changedTargetUrlChangedLink hover target

Multi-Engine Pattern

Roamium is the first engine binary, but the architecture is designed for multiple engines. Each engine follows the same pattern:

  1. A C shared library wrapping the engine's embedding API (ts_* functions)
  2. A Rust binary (~400 lines) handling IPC and protobuf

The Rust binary is almost entirely reusable — only the C library changes per engine. Planned engines: Surfari (WebKit), Waterwolf (Gecko), Girlbat (Ladybird).

Installation

Roamium installs to /usr/local/roamium/ alongside Chromium's dylibs, .pak resource files, and ICU data. The GUI knows to look for it there.

scripts/build.sh roamium --release
sudo scripts/install.sh roamium