CBF Book
CBF (Chromium Browser Framework) is a Rust-oriented browser backend framework built on Chromium.
It provides a browser-generic API while containing Chromium/Mojo internals behind explicit layer boundaries. By using CBF, you can develop your browser without being tied to Chromium’s frequent updates or complex build system.
This book is the primary long-form entry point for users and contributors.
Who this book is for:
- Application developers integrating CBF with prebuilt artifacts.
- Contributors changing crates, bridge code, or Chromium-fork patches.
- Maintainers reviewing architecture boundaries and failure handling rules.
Note: For API reference, please check docs.rs:
cbfcrate,cbf-chromecrate,cbf-chrome-syscrate.
Feature Matrix
This document provides a high-level overview of the features supported by CBF, categorized by functionality. The status of each feature is indicated to help users and developers understand the current capabilities and limitations of CBF.
Legend
| Symbol | Meaning |
|---|---|
| ✅ | Fully supported |
| 🚧 | Partial — see Notes for details |
| ❌ | Not yet implemented |
Page Lifecycle & Navigation
| Feature | Status | Platform | Notes |
|---|---|---|---|
| Open webpage | ✅ | macOS | |
| Navigate webpage | ✅ | macOS | |
| Close webpage | ✅ | macOS | |
| Go back/forward | ✅ | macOS | |
| Reload webpage | ✅ | macOS | |
| beforeunload events | ✅ | macOS | |
| Shutdown | ✅ | macOS |
Surface & Input
| Feature | Status | Platform | Notes |
|---|---|---|---|
| Surface creation | ✅ | macOS | Uses CAContextID |
| Change surface bounds | ✅ | macOS | |
| Send mouse/key events | ✅ | macOS | |
| Send IME events | ✅ | macOS |
Content & Interaction
| Feature | Status | Platform | Notes |
|---|---|---|---|
| Get DOM html | ✅ | macOS | |
| Drag and Drop on webpage | ✅ | macOS | |
| Drag and Drop from other apps | ✅ | ||
| Context menu events | 🚧 | macOS | Some native items are not yet supported |
Downloads & Print
| Feature | Status | Platform | Notes |
|---|---|---|---|
| Download management | ✅ | macOS | |
| Show print dialog UI | 🚧 | macOS | UI can be shown; window can’t activated |
| Show print preview UI | ❌ |
Profile & Extensions
| Feature | Status | Platform | Notes |
|---|---|---|---|
| Open webpage with profile | ✅ | macOS | |
| Get profile list | ✅ | macOS | |
| Get profile info | ✅ | macOS | |
| Get extension list | ✅ | macOS | |
| Extension inline UI | ✅ | macOS | |
| Full extension support | 🚧 | macOS |
Developer Tools & Built-in Pages
| Feature | Status | Platform | Notes |
|---|---|---|---|
| DevTools UI | 🚧 | macOS | You can embed DevTools in your app |
chrome://version | ✅ | macOS | |
chrome://history | 🚧 | macOS | Deleting all history at once is not yet supported |
chrome://settings | 🚧 | macOS | Some settings options are not yet available |
Concepts
CBF is a reusable browser backend framework for Rust applications. Its design goal is a stable browser-generic surface with strict containment of Chromium-specific implementation details.
1. Layer model
cbf: browser-generic public APIcbf-chrome: chrome-specific safe backendcbf-chrome-sys: C ABI / FFI boundary andcbf_bridgebinding target- Chromium process (Mojo integration and browser runtime)
Dependency direction:
Application -> cbf + cbf-chromecbf-chrome -> cbfcbf-chrome -> cbf-chrome-sys <-- IPC --> Chromium processcbfmust not depend on browser-specific crates.
Browser backends are adapters that depend on cbf, so cbf can stay focused on browser-generic vocabulary and remain extensible to additional backends (for example, a future Firefox backend).
Applications may also depend on browser-specific backend crates (such as cbf-chrome) for practical integration points, including browser bootstrap, graphics/surface integration, and controlled escape-hatch APIs.
2. Interaction and failure semantics
CBF intentionally separates application code from browser internals through a strict asynchronous boundary. This boundary is a core design principle, not just an implementation detail.
CBF models interactions as:
BrowserCommand: upstream request from application to backendBrowserEvent: backend fact/notification to upstream
Because communication is asynchronous, every request is treated as potentially fallible by design. Disconnects, timeouts, crashes, and protocol mismatch are normal outcomes that should be surfaced explicitly.
This model prevents tight coupling to browser-specific behavior and avoids implicit assumptions about browser guarantees. It also helps CBF users naturally design recovery paths, while limiting direct blast radius from browser-side failures.
Typical failure states:
- backend not running
- disconnect/timeouts/protocol mismatch
- renderer or browser crash
3. Ownership and identity boundary
BrowsingContextis mapped to Chrome-layerTabin the current runtime model.Tabremains WebContents-backed internally, andWebContents/Tabownership stays in the Chromium process.cbfpublic layer usesBrowsingContextId, while chrome-facing layers useTabId.BrowsingContextId <-> TabIdis treated as a stable logical mapping at boundary conversion points.- Rust-side APIs track stable logical IDs, not raw Chromium pointers.
4. API evolution policy
- Keep
cbfvocabulary browser-generic. - Prefer additive changes over breaking changes.
- Avoid unnecessary public surface expansion.
- Keep lifecycle and failure semantics explicit in API shape.
User Setup
This chapter is for application developers using prebuilt CBF and cbf_bridge artifacts.
If you will modify Chromium-side code or bridge internals, use Contributor Setup.
1. Prerequisites
- Stable Rust toolchain (install from https://rustup.rs/)
2. Obtain the Chromium fork binary
The CBF Chromium fork is a patched Chromium build required as the browser backend. Do not use stock Chromium — it does not include the CBF bridge patches.
You can obtain it from:
- GitHub Releases (planned): download the prebuilt artifact for your platform
- Local build: build from the
chromium/directory (this can take considerable time, see [../developer-guide/contributor-setup.md])
Platform-specific artifact names and executable_path values:
| Platform | Artifact | executable_path |
|---|---|---|
| macOS | Chromium.app | Chromium.app/Contents/MacOS/Chromium |
| Linux | currently unsupported | … |
| Windows | currently unsupported | … |
On macOS, executable_path must point to the binary inside the .app bundle, not the bundle itself.
3. Configure bridge library path
You can obtain the bridge library from:
- GitHub Releases (planned): download the prebuilt artifact for your platform
- Local build: use the output directory from your Chromium build (this can take considerable time, see [../developer-guide/contributor-setup.md])
Platform-specific library names:
| Platform | Library |
|---|---|
| macOS | libcbf_bridge.dylib |
| Linux | libcbf_bridge.so (currently unsupported) |
| Windows | cbf_bridge.dll (currently unsupported) |
Set CBF_BRIDGE_LIB_DIR to the directory containing the bridge library:
export CBF_BRIDGE_LIB_DIR="/path/to/cbf_bridge/libdir"
You can also pin it per project in .cargo/config.toml instead of setting an environment variable:
[env]
CBF_BRIDGE_LIB_DIR = "/path/to/cbf_bridge/libdir"
Then verify crates compile:
cargo check -p cbf
cargo check -p cbf-chrome
cargo check -p cbf-chrome-sys
4. Launch Chromium through CBF
Try it with simpleapp first
If you want to verify your setup before writing your own app,
examples/simpleapp
is a working single-window reference app
that demonstrates the full integration. It also serves as a concrete example of the patterns
described below.
# Set the Chromium-fork executable path, then run:
CBF_CHROMIUM_EXECUTABLE=/path/to/Chromium.app/Contents/MacOS/Chromium \
cargo run -p simpleapp
Note:
simpleappcurrently supports macOS only.
What start_chromium does (and does not do)
start_chromium spawns the Chromium process and establishes the IPC bridge.
It returns a session handle, an event stream, and a process handle — no window is created.
#![allow(unused)]
fn main() {
use std::path::PathBuf;
use cbf_chrome::backend::ChromiumBackendOptions;
use cbf_chrome::process::{
ChromiumProcessOptions, ChromiumRuntime, RuntimeSelection, StartChromiumOptions,
start_chromium,
};
let (session, events, process) = start_chromium(
StartChromiumOptions {
process: ChromiumProcessOptions {
runtime: RuntimeSelection::Chrome,
executable_path: PathBuf::from("/path/to/chromium"),
user_data_dir: Some("./.cbf-user-data".to_owned()),
..Default::default()
},
backend: ChromiumBackendOptions::new(),
},
)?;
let runtime = ChromiumRuntime::new(session, events, process);
runtime.install_signal_handlers()?;
}
Operational notes:
- Prefer explicit
user_data_dirto avoid profile conflicts. executable_pathshould point to the CBF Chromium-fork binary obtained in §2.start_chromiumremains the core tuple API;ChromiumRuntimeis the opt-in lifecycle wrapper for signal forwarding and best-effort shutdown hardening.
Windows and surface attachment
Displaying browser content requires two additional steps that the application is responsible for:
- Create a native window using a windowing library such as
winit. - Attach a surface — after
BackendReadyand browsing context creation, you will receive aSurfaceHandleUpdatedevent containing a platform-specific surface handle. Attach this handle to your host window usingcbf-compositoror your own platform-native integration. If you later hide a browsing context and show it again, macOS may recreate the underlying compositor surface. In that case CBF can emit anotherSurfaceHandleUpdatedevent with a new handle, and the host should reattach or rebind the surface using that latest handle.
simpleapp implements this full cycle using winit and cbf-compositor.
See examples/simpleapp/src/ for the platform-specific surface attachment and event loop wiring.
5. Validate behavior
start_chromiumlaunches and connects successfully.- Baseline lifecycle events (
BackendReady,BackendStopped) are observable. - Crash/disconnect paths surface as events/errors, not silent hangs.
6. macOS app bundling
cbf-cli can package an app binary with Chromium + bridge into a .app bundle.
Configure via Cargo metadata
Bundle settings are read from [package.metadata.cbf.macos-bundle] in your Cargo.toml.
This is the recommended way to declare app identity, as it is committed alongside your project:
[package.metadata.cbf.macos-bundle]
app-name = "My App"
bundle-identifier = "com.example.myapp"
icon = "assets/icon.icns" # relative to Cargo.toml
runtime-app-name = "My App Engine"
runtime-bundle-identifier = "com.example.myapp.runtime"
runtime-icon = "assets/runtime.icns" # defaults to `icon` when omitted
category = "public.app-category.developer-tools"
minimum-system-version = "13.0"
bundle-version is taken automatically from [package] version.
cbf-cli uses runtime terminology in config and implementation, while the
default user-visible bundled runtime branding still uses Engine.
Run the bundler
The following three inputs are always required on the command line (or via environment variables):
cargo run -p cbf-cli -- bundle macos \
--bin-path /path/to/your/app/binary \
--chromium-app /path/to/Chromium.app \
--bridge-lib-dir /path/to/cbf_bridge/libdir
Environment variable alternatives:
CBF_CHROMIUM_APPfor--chromium-appCBF_BRIDGE_LIB_DIRfor--bridge-lib-dir
CLI overrides
CLI arguments take priority over Cargo metadata values when both are present:
| Cargo metadata key | CLI override flag |
|---|---|
app-name | --app-name |
bundle-identifier | --bundle-identifier |
icon | --icon |
runtime-app-name | --runtime-app-name |
runtime-bundle-identifier | --runtime-bundle-identifier |
runtime-icon | --runtime-icon |
category and minimum-system-version are metadata-only (no CLI equivalent).
Additional CLI-only options: --out-dir (default: dist), --codesign-identity, --package (for workspaces).
The bundled runtime is placed under:
<App>.app/Contents/CBF Runtime/<RuntimeAppName>.app
Branding changes are applied before signing. If you pass --codesign-identity,
cbf-cli will sign the final app bundle and validate it with codesign and
spctl. MVP runtime branding support currently targets release-style Chromium
runtime bundles (is_component_build = false).
Contributor Setup
This chapter is for contributors who modify CBF crates, bridge code, or Chromium-fork patches.
1. Prerequisites
You need the following tools installed and configured:
- Stable Rust toolchain
- Git
- Python 3
depot_tools- Chromium build dependencies for your OS
- Chromium source code
For downloading Chromium source code and depot_tools and setting up the Chromium build environment, follow the official guide: https://chromium.googlesource.com/chromium/src/+/HEAD/docs/get_the_code.md
You should place Chromium source tree at chromium/src relative to the repository root. This allows build scripts to locate bridge artifacts without additional configuration.
It is also recommended to place depot_tools at ./depot_tools relative to the repository root so helper commands can discover it consistently.
2. Build Chromium targets
Before building, generate GN build files (this creates chromium/src/out/Default/args.gn):
cd chromium/src
gn gen out/Default
Optionally, you can tune out/Default/args.gn for CBF development. Example:
# Build release-like binaries for faster runtime and smaller output.
is_debug = false
# Keep DCHECK-enabled behavior even in non-debug builds.
# This is important for CBF development since CBF and Chromium often rely
# on DCHECKs to validate invariants and catch issues early.
dcheck_always_on = true
# Use component build for faster incremental link/build cycles.
is_component_build = true
# Enable ccache via wrapper to speed up repeated C/C++ compilation.
cc_wrapper = "env CCACHE_SLOPPINESS=time_macros ccache"
# Reduce overall symbol volume.
symbol_level = 1
# CBF usually does not modify Blink/V8 internals, so strip more symbols there.
blink_symbol_level = 0
v8_symbol_level = 0
Then build relevant targets with autoninja from chromium/src:
autoninja -C out/Default chrome
autoninja -C out/Default cbf_bridge
This builds the main Chromium target and the CBF bridge library, which is required for cbf-chrome-sys to link successfully.
Release packaging uses a separate chromium/src/out/Release directory and a
different args.gn policy. See Release Process for the
release-specific flow.
Warning
Chromium builds can take several hours or longer, and CPU usage may stay high during the entire build, which can keep sustained load on your machine. Because builds are long-running, you can mitigate sleep-related build interruption by using tools such as
caffeinateof macOS.
3. Configure bridge linkage
cbf-chrome-sys and cbf-chrome needs bridge artifacts from CBF_BRIDGE_LIB_DIR:
export CBF_BRIDGE_LIB_DIR="/path/to/chromium/src/out/Default"
Then run focused checks:
cargo check -p cbf
cargo check -p cbf-chrome
cargo check -p cbf-chrome-sys
cargo test -p cbf
cargo test -p cbf-chrome
cargo test -p cbf-chrome-sys
4. Contributor validation checklist
- Rust crates compile and tests pass for touched areas.
- Rust code changes are formatted with
cargo fmt. - Rust code follows lint rules with
cargo clippy. cbf_bridgebuilds against current Chromium revision.- Run Chromium-side tests as needed based on the impact scope of your changes (see Chromium Fork Workflow for how to run them).
5. Where to continue
- Integration invariants: Chromium Integration Rules
- Implementation details: Chromium Implementation Guide
- Fork operations and patch queue: Chromium Fork Workflow
- Local release packaging: Release Process
- Decision history: Decisions
Versioning and Release Metadata
This guide defines how CBF versions Rust crates and GitHub release artifacts.
It separates crate compatibility from packaged Chromium runtime revisions so
maintainers can publish crate-specific releases and can re-release
Chromium.app and cbf_bridge without forcing an unrelated crate publish.
1. Goals
CBF publishes two kinds of versioned outputs:
- Rust crates on crates.io
- GitHub Releases for crate history and prebuilt runtime bundles
These outputs have different compatibility concerns:
cbfandcbf-chromeexpose Rust APIs and should follow normal SemVer rules.cbf-chrome-systracks the Chromium generation that defines the low-level FFI and wire boundary.- GitHub Releases serve two purposes:
- crate-specific release history
- packaged runtime bundle distribution
2. Crate Versioning
cbf
cbf uses normal SemVer.
- Major/minor indicate public API compatibility in the browser-generic Rust API.
- Patch indicates compatible bug fixes and documentation-only corrections.
- Before
1.0.0, maintainers should treat minor bumps as the main signal for breaking public API changes.
Examples:
0.1.00.2.00.2.1
cbf-chrome
cbf-chrome also uses normal SemVer.
- Its version tracks the Chrome-specific safe Rust API surface.
- It is versioned independently from
cbf. - Its release cadence may be higher than
cbfbecause it sits closer tocbf-chrome-sys, Chromium integration, and backend-specific behavior.
Examples:
cbf = 0.3.0cbf-chrome = 0.7.2
cbf-chrome-sys
cbf-chrome-sys uses a Chromium-generation-oriented version scheme:
<chromium-milestone>.<minor>.<patch>
Rules:
major: Chromium milestone, such as146or147minor: additive compatible changes to the FFI/wire boundary within that Chromium milestone linepatch: compatible fixes only
Examples:
146.1.0146.1.1146.2.0147.0.0
Do not encode the full Chromium revision in SemVer build metadata as the
primary compatibility signal. For example,
146.1.0+chromium-146.0.7632.160 is acceptable as descriptive metadata, but
Cargo dependency resolution does not treat build metadata as part of version
precedence.
3. Compatibility Model
The expected compatibility split is:
cbfandcbf-chromedefine the Rust-side API contract.cbf-chrome-sysdefines the Rust-to-bridge ABI contract for a Chromium milestone line.- crate releases identify changes to one Rust crate at a time.
- runtime bundle releases identify the concrete prebuilt runtime bundle that
contains:
Chromium.applibcbf_bridge.dylib
As a result:
- A crate may receive a GitHub Release even when no new runtime bundle is published.
cbfandcbf-chromedo not need matching version numbers.- Compatibility between
cbfandcbf-chromeshould be expressed through Cargo dependency requirements and release notes, not version-number alignment. - A
Chromium.apporcbf_bridgerebuild may require a new GitHub Release without requiring a newcbf-chrome-syscrate release. - A new
cbf-chrome-sysrelease is required when the ABI/wire boundary changes in a way that should be represented to Cargo users.
4. GitHub Release Types
CBF uses two GitHub Release types:
- crate releases
- runtime bundle releases
These release types should use different tag namespaces.
Crate releases
Create a GitHub Release for each public crate publish so maintainers and users can track crate-specific changes independently.
Canonical tag format:
<crate-name>-v<crate-version>
Examples:
cbf-v0.1.0
cbf-chrome-v0.1.0
cbf-chrome-sys-v146.1.0
cbf-compositor-v0.1.0-alpha.1
cbf-cli-v0.1.0
Recommended title format:
<crate-name> v<crate-version>
Examples:
cbf v0.1.0
cbf-chrome v0.1.0
cbf-chrome-sys v146.1.0
cbf-compositor v0.1.0-alpha.1
cbf-cli v0.1.0
Crate release notes should focus on:
- what changed in that crate
- compatibility expectations for downstream users
- links to related runtime bundle releases when relevant
Runtime bundle releases
GitHub Release tags identify the packaged runtime bundle, not just crate versions.
The canonical tag format is:
cbf-chrome-runtime-v<cbf-chrome-version>+chromium-<chromium-version>-r<release-revision>
Example:
cbf-chrome-runtime-v0.1.0+chromium-146.0.7632.160-r1
Field meanings:
<cbf-chrome-version>: the publishedcbf-chromecrate line for this bundle<chromium-version>: the full Chromium runtime version included in the bundle<release-revision>: packaging and redistribution revision for the same crate/runtime combination, starting at1
Release revision increments when maintainers republish artifacts for the same crate versions and the same Chromium version, for example:
- refreshed
Chromium.app - rebuilt
libcbf_bridge.dylib - corrected packaging or bundled notices
- regenerated archives due to packaging mistakes
Examples:
cbf-chrome-runtime-v0.1.0+chromium-146.0.7632.160-r1cbf-chrome-runtime-v0.1.0+chromium-146.0.7632.160-r2cbf-chrome-runtime-v0.1.0+chromium-147.0.7651.5-r1
5. Runtime Bundle Release Titles
Use a human-readable title that mirrors the tag and makes the bundled Chromium version obvious.
Recommended format:
CBF Chrome v<cbf-chrome-version> for Chromium v<chromium-version> (Release <n>)
Examples:
CBF Chrome v0.1.0 for Chromium v146.0.7632.160 (Release 1)CBF Chrome v0.1.0 for Chromium v146.0.7632.160 (Release 2)
6. Release Notes Metadata
Each runtime bundle release should explicitly record:
cbfversioncbf-chromeversioncbf-chrome-sysversion- bundled Chromium version
- release revision (
r1,r2, …) - notable changes since the previous release revision or version
The runtime bundle release notes should be derived from:
chromium/CHANGELOG.md- the crate changelogs when a runtime release depends on crate-side changes that should be called out explicitly
Recommended release note structure:
Crates
- cbf: 0.1.0
- cbf-chrome: 0.1.0
- cbf-chrome-sys: 146.1.0
Bundled runtime
- Chromium: 146.0.7632.160
- Release revision: r1
Notes
- Initial public prebuilt release for Chromium milestone 146.
Each crate release should explicitly record:
- crate name
- crate version
- notable changes in that crate
- compatibility notes
- related runtime bundle release tags when the crate expects a specific runtime
Each crate release note should be derived from that crate’s local
CHANGELOG.md.
7. Changelog Layout
CBF keeps changelogs close to the release unit they describe.
Recommended changelog files:
crates/cbf/CHANGELOG.mdcrates/cbf-chrome/CHANGELOG.mdcrates/cbf-chrome-sys/CHANGELOG.mdcrates/cbf-compositor/CHANGELOG.mdcrates/cbf-cli/CHANGELOG.mdchromium/CHANGELOG.md
Rules:
- Each crate changelog tracks only that crate’s public release history.
chromium/CHANGELOG.mdtracks runtime bundle history forChromium.app,libcbf_bridge.dylib, and other Chromium-side packaging changes that affect prebuilt runtime releases.- GitHub Release notes should summarize and link back to the corresponding changelog entry instead of becoming the only source of change history.
- Maintainers may include only the relevant excerpt in GitHub Release notes, but the full changelog entry should remain in the repository.
8. Maintainer Guidance
- Treat crate versions and GitHub Release tags as separate identifiers with different responsibilities.
- Create crate releases for public crate publishes so each crate has its own visible release history.
- Maintain one changelog per public crate and one runtime changelog under
chromium/CHANGELOG.md. - Do not try to keep
cbfandcbf-chromenumerically aligned when their actual release cadence differs. - Do not force a
cbf-chrome-syspublish only because a runtime bundle was rebuilt. - Publish a new
cbf-chrome-sysversion when ABI or wire-boundary compatibility changes should be visible to Cargo users. - Keep runtime bundle release notes explicit about both the crate line and the packaged Chromium revision.
- Keep the crate tag namespace and runtime tag namespace distinct.
Release Process
This guide defines the MVP release flow for pre-built macOS artifacts. It is intentionally local and manually invoked. Artifact upload is still a maintainer step outside the repository automation.
For crate versioning and GitHub Release tag/title rules, see
docs/developer-guide/versioning-and-release-metadata.md.
1. Scope
The MVP release bundle contains these top-level files:
Chromium.applibcbf_bridge.dylibCBF_LICENSE.txtTHIRD_PARTY_LICENSES.txtSOURCE_INFO.txt
The default archive name is:
cbf-chrome-macos-<git-tag>.tar.gz
The archive is written under dist/release/.
2. Release build requirements
Release packaging always reads Chromium outputs from:
chromium/src/out/Release
The out/Release/args.gn file must exist and must contain these values:
is_debug = false
dcheck_always_on = false
is_component_build = false
is_official_build = true
For the MVP OSS browser distribution, the release helper also expects the architecture and codec policy to be pinned explicitly:
# Pin the release architecture explicitly for deterministic packaging.
target_cpu = "arm64" # or "x64"
# Keep the MVP distribution within the Chromium codec/license surface.
proprietary_codecs = false
ffmpeg_branding = "Chromium"
Recommended complete out/Release/args.gn example for the MVP stage:
is_debug = false
dcheck_always_on = false
is_component_build = false
is_official_build = true
target_cpu = "arm64" # or "x64"
proprietary_codecs = false
ffmpeg_branding = "Chromium"
Notes:
dcheck_always_on = falseis required for release stability; do not reuse the development-onlyout/Defaultsetting here.proprietary_codecs = falsekeeps the MVP bundle out of the additional proprietary codec licensing path.ffmpeg_branding = "Chromium"makes that policy explicit even though it is already the default for non-Chrome-branded builds.
target_os is recorded in SOURCE_INFO.txt when present. target_cpu,
proprietary_codecs, and ffmpeg_branding are always captured by the release
helper.
3. Required tools
The local release flow expects:
uv- Python 3
tarshasumorsha256sumchromium/src./depot_tools
By default, the runtime release bundle identifier is taken from the single git
tag that points at HEAD. Use the canonical runtime bundle tag format defined
in docs/developer-guide/versioning-and-release-metadata.md.
If HEAD is untagged, the release flow fails.
If a maintainer needs to package a different tagged revision or HEAD has
multiple release-related tags, pass --tag <tag> to select the release tag
explicitly.
4. Task entrypoints
The root Taskfile.yml is the entrypoint for the release flow.
Validate prerequisites:
task release:check
Explicit tag:
task release:check TAG=cbf-chrome-runtime-v0.1.0+chromium-146.0.7632.160-r1
Build release artifacts:
task release:build
Generate license files:
task release:licenses
Generate source metadata:
task release:source-info
Assemble the release archive:
task release:package
Run the full flow:
task release
If a maintainer intentionally needs to package a dirty tree for investigation,
they can pass ALLOW_DIRTY=true to the task invocation. Normal releases should
keep both the repository root and chromium/src clean.
5. Generated files
The release helper writes generated files under:
dist/release/<git-tag>/
Generated outputs:
CBF_LICENSE.txtTHIRD_PARTY_LICENSES.txtSOURCE_INFO.txt
The final release archive is written to:
dist/release/cbf-chrome-macos-<git-tag>.tar.gz
6. Manual upload
Artifact publication remains manual for the MVP stage.
After task release completes:
- Inspect the generated files under
dist/release/<git-tag>/. - Inspect
SOURCE_INFO.txtand confirm the recorded revisions and GN args. - Upload
dist/release/cbf-chrome-macos-<git-tag>.tar.gzto the matching runtime bundle GitHub Release.
7. Release legal checklist
Before publishing a binary release, confirm at least the following:
out/Release/args.gnpinsproprietary_codecs = false.out/Release/args.gnpinsffmpeg_branding = "Chromium".task release:licenseswas run from the exact source revision used for the release archive.THIRD_PARTY_LICENSES.txtis included in the final archive and was generated from the exact Chromium revision being distributed.CBF_LICENSE.txtis included in the final archive and matches the repositoryLICENSE.SOURCE_INFO.txtrecords the exact CBF commit, Chromium commit, patch queue state, and selected GN args used for the release.- The release notes or download page state that CBF includes Chromium and other third-party components under their own licenses.
- FFmpeg remains within the Chromium/LGPL distribution path for the shipped build; do not enable GPL or nonfree FFmpeg options for the MVP release.
- If the release changes media/codec policy, packaging terms, or bundled third-party binaries, request legal review before publication.
No GitHub Actions workflow, Jenkins job, or scheduled release automation is part of this MVP process.
Chromium Integration Rules
This document defines cross-layer design rules for Chromium integration in CBF. It describes invariants and policy shared by:
cbf_bridge(Chromium-side bridge and Mojo wiring)chrometarget integration in Chromiumcbf-chrome-sysboundary crates
For concrete implementation patterns, troubleshooting steps, and command snippets, see Chromium Implementation Guide.
1. Boundary contract
- Browser-generic API surface remains in
cbf. - Chromium-specific behavior and details stay in
cbf-chrome-sysor Chromium-side bridge code. - Public types in
cbfdo not include Chromium/Mojo internals. - C ABI and exported C functions remain in
cbf-chrome-sys. - Chromium-owned constants are not duplicated into
cbfpublic API.
Dependency direction must remain:
Application -> cbf + cbf-chromecbf-chrome -> cbfcbf-chrome -> cbf-chrome-sys <-- IPC --> Chromium process
2. Architecture and ownership model
- Treat
cbfas a logical browser API; avoid embedding product/domain terms in this layer. - Preserve stable logical IDs as the only stable cross-process identity (
WebPageId, etc.). - Resolve platform objects from IDs at execution time instead of caching and dereferencing platform pointers across asynchronous boundaries.
3. IPC contract
- IPC is asynchronous, non-blocking, and failure-aware.
- IPC APIs are sequence-sensitive; a bound channel must be used only on its bound sequence.
- Disconnects, late callbacks, and incomplete handshakes are regular runtime outcomes, not exceptional states.
- Design API and event flow so operations can be retried, deferred, or dropped safely.
4. Lifetime safety policy
- Raw platform pointers must not cross async boundaries.
- Avoid capturing owning
thisin callbacks that may outlive owners. - Use weak ownership mechanisms (
WeakPtr) where re-entry can happen. - If an ID re-resolution fails, the correct behavior is safe no-op.
- On shutdown/close races, do not fail-fast on missing state.
5. Safety and failure policy
- Crash-unsafe assertions (
CHECK) are forbidden on expected lifecycle races. - Expected failure states should be represented as errors/events, enabling upstream recovery decisions (retry, restart session, or fail gracefully).
- Duplicate, late, or out-of-order lifecycle operations must be handled idempotently.
- Failure handling should prioritize availability and observability over strict assumptions.
6. Chromium process policy
- Default startup path is the Rust
start_chromiumflow. - Manual launch without bridge attachment is a debug-only scenario and must not be treated as normal production behavior.
- Any code path that bypasses the standard startup path should carry explicit operational notes.
7. Review expectations
When reviewing Chromium-side integration changes, verify these rule-level outcomes:
- Boundary ownership and dependency direction are preserved.
- Identity and lifetime assumptions are explicit.
- Async paths avoid unsafe object capture and include safe no-op behavior on stale IDs.
- Failure states are surfaced as events/errors and are testable.
- Changes remain reviewable against this document before implementation details are finalized.
Chromium Implementation Guide
This guide is for contributors implementing Chromium-side behavior in cbf-chrome-sys and
cbf_bridge-adjacent code.
For the higher-level invariants and design constraints, see Chromium Integration Rules.
For setup flow, see:
1. Purpose and audience
This document provides implementation guidance for:
cbf_bridgeand Mojo plumbing updatescbf-chrome-sysboundary code and FFI surfaces- conversion or dispatch layers between Chromium process data and
cbfevents/commands
It is not a product API guide.
2. IPC and threading invariants (implementation)
IPC contract policy is defined in Chromium Integration Rules §3.
Concrete Mojo/threading patterns:
- Bind each
mojo::Remoteon its intended sequence and keep all use-sites on that sequence. - Route bridge calls through the task runner / sequence for the bound remote.
- Add explicit sequence checks where practical to catch regressions during development.
- Express async continuation as callbacks or futures — do not block threads waiting for IPC results.
- Treat disconnect and late callbacks as regular control-flow branches (
drop/retry/surface error).
3. Async lifetime safety patterns (implementation)
Lifetime safety policy is defined in Chromium Integration Rules §4.
Concrete implementation checklist:
- Capture stable IDs (e.g.,
WebPageId) and resolve platform objects (e.g.,WebContents*) at task execution time — do not cache raw pointers across async boundaries. - Treat unresolved IDs as expected; apply a guarded no-op and emit a structured error/event where applicable.
Emergency hatch: restricted base::Unretained
base::Unretained(...) is acceptable only as temporary technical debt:
- You can prove lifetime for the full async window.
- The reason is documented in code comments.
- A follow-up task/TODO tracks conversion to safe ownership.
- The preferred next step is replacing it with
ID + re-resolution.
4. FFI boundary implementation
Platform boundary rule
- Keep Chromium-specific behavior out of public
cbfAPIs. - Keep conversion/state-machine logic in bridge or
cbf-chrome-sys. - Convert to Rust-facing API shapes at boundary layers only.
Constant ownership rule
- Do not duplicate Chromium constants in
cbf. - Expose required constant values through
cbf-chrome-sys/bridge when Rust needs them.
Bridge-first rule
- Prefer native Chromium values from bridge outputs.
- Treat bridge outputs as the source of truth and avoid reconstructing Chromium state in
cbf.
5. Failure handling implementation
Failure policy is defined in Chromium Integration Rules §5.
Expected runtime conditions to handle gracefully (not exceptional):
- backend not running
- backend disconnects
- timeout and protocol mismatch
- renderer/browser crash
Additional implementation note:
- Retain in-progress state for recoverable retries only when it is safe to restore.
6. Implementation troubleshooting
Build drift between Chromium and bridge
If bridge compilation fails after Chromium changes:
- rebase/refresh CBF patches
- regenerate bridge contracts where needed
- validate ABI expectations in
cbf-chrome-sys
Async lifetime crash patterns
If shutdown/close races crash:
- inspect captured values in callbacks
- replace raw pointer captures with IDs and
WeakPtr - remove synchronous assumptions from callback chains
IPC connection failures
If connect/auth path fails:
- confirm inherited endpoint and session-token are passed consistently
- verify fd flags are prepared as expected before spawn
- ensure parent side closes its copied endpoint appropriately after spawn
- confirm Rust and Chromium agree on the selected session token
7. Contributor review checklist
Before merging bridge/boundary changes, verify:
- no raw pointer ownership crosses async boundaries
- any
base::Unretaineduse has explicit justification + replacement plan - race-prone paths use guarded no-op behavior rather than hard assertions
- new APIs keep Chromium details inside bridge/FFI layers
- disconnect/crash paths have explicit behavior and, where feasible, tests
8. Chromium-side targets and execution
For Chromium-side impact, build and run:
chromium/src/out/Default/cbf_testschromium/src/out/Default/browser_testschromium/src/out/Default/unit_tests
Prefer focused filters first (for example Cbf* suites), then expand.
Example commands:
chromium/src/out/Default/browser_tests --gtest_filter='Cbf*'
chromium/src/out/Default/unit_tests --gtest_filter='CbfBrowserServiceTest.*'
9. Required Chromium switches injected by start_chromium
start_chromium is the default runtime path and injects required Chromium flags
for CBF bootstrap automatically.
The following switches are required and are always set by start_chromium:
-
--enable-features=Cbf- Enables CBF-specific Chromium feature wiring.
- Without this, CBF bridge integration paths are not activated.
-
--cbf-ipc-handle=<platform-specific-value>- Carries the inherited IPC endpoint information generated by
IpcClient::prepare_channel(). - Chromium uses this value to recover the parent-provided endpoint and complete the bridge-side IPC bootstrap.
- Carries the inherited IPC endpoint information generated by
-
--cbf-session-token=<hex-token>- Provides per-process-session authentication material.
- The Rust and Chromium sides must agree on this token during initial handshake/authentication.
Common optional flags controlled by StartChromiumOptions include:
--user-data-dir=...- When
user_data_diris set,start_chromiumalso injects--breakpad-dump-location=<user_data_dir>/Crashpadso Crashpad data stays under the same application data root on macOS.
- When
--enable-logging=...--log-file=...--v=.../--vmodule=...--no-startup-window(default unless explicitly overridden)
Manual Chromium launch is primarily for low-level local debugging. If you bypass
start_chromium, you must provide equivalent bootstrap inputs yourself.
Chromium Fork Workflow
This chapter covers Chromium-fork specific workflow for CBF contributors.
1. Scope
CBF requires a Chromium fork with CBF integration. Do not assume stock Chromium has equivalent behavior.
Relevant locations:
- CBF Chromium code:
chromium/src/chrome/browser/cbf/ - Bridge implementation:
chromium/src/chrome/browser/cbf/bridge - Exported patch queue:
chromium/patches/cbf
2. Build and test targets
You should use autoninja to build Chromium targets from chromium/src:
autoninja -C out/Default chrome
autoninja -C out/Default cbf_bridge
From the repository root, you can also execute the following command:
This command will automatically add ./depot_tools to PATH.
uv run tool build -t chrome -t cbf_bridge
# If you activated venv with uv, you can also use:
python3 tool build -t chrome -t cbf_bridge
These targets are relevant for CBF development:
chrome: Chromium-fork build target with CBF integration.cbf_bridge: CBF bridge library target. It is used fromcbf-chrome-sys.cbf_tests,browser_tests,unit_tests: Chromium-side test targets covering different test scopes and types. See their respective BUILD.gn files for details.
3. Patch queue policy
Changes to Chromium are exported as patches using Git’s format-patch and stored in the cbf repository. You should maintain a clean with the following principles:
- Keep CBF-specific changes traceable in
chromium/patches/cbf. - Curate
chromium/srccommit stack, then export patches. - Fold refinements with
fixup/squashrather than appending noisy fix patches.
Patch-splitting principles:
- Keep one primary responsibility per patch.
- Keep dependency direction explicit in patch ordering.
- Prefer mechanical moves/refactors before behavior changes.
- Keep each patch buildable in the target Chromium output directory.
- Use short imperative English subjects for exported patches; do not use Conventional Commits in patch titles.
- When refining an existing patch, prefer
fixup/squashinto that patch instead of adding a follow-up fix patch.
Common tooling flow:
uv run tool apply
uv run tool export
uv run tool git <...args>
uv run tool commit -m "<message>"
Patch files live in chromium/patches/cbf/.
4. Runtime constraints
- CBF runtime behavior depends on
--enable-features=Cbf. - IPC bootstrap uses inherited endpoint + session token injected by
start_chromium. start_chromiumshould be the default runtime path; manual launch is primarily for debugging.
ADR Guide in CBF
This project stores Architecture Decision Records (ADRs) under docs/decisions/ at the repository.
The goal of an ADR is to preserve why a decision was made so future maintainers, AI agents, and contributors can trace it.
An ADR is not an implementation design document.
1. Naming Convention
- Filename:
NNNN-kebab-case-title.mdNNNNis a 4-digit sequential number (for example,0001-...)- As a rule, numbering order should match decision order
- Title line:
# ADR NNNN: ...
2. Required Sections (in this order)
Every ADR must include the following sections:
StatusDateContextDecisionConsequencesAlternatives ConsideredNotesFollow-ups
2.1 Status
Recommended values (you may add more if needed):
Proposed: under proposal (not yet decided)Accepted: adopted (decision made)Rejected: rejectedDeprecated: previously valid but now deprecatedSuperseded: replaced by another ADR (explicitly include the replacing ADR number)
2.2 Date
- Format:
YYYY-MM-DD - Use the date when the ADR became an actual decision (typically when set to
Accepted)
3. Writing Guidelines
Context
- Describe the problem to solve, constraints, assumptions, current state, and why a decision is needed now
- If references exist, include links or repository paths
Decision
- State in definitive form what will be done, at which boundary, and in which dependency direction
- When possible, make responsibilities and dependencies explicit (avoid cycles)
Consequences
- Separate
Positive(expected benefits) andNegative / Trade-offs(costs, drawbacks) - Consider impact areas such as developer experience, changeability, performance, operations, and testing
Alternatives Considered
- List alternatives and briefly explain why each was not chosen
Notes
- Add important supplemental information that does not fit naturally in Context/Decision/Consequences
- You may explicitly mark what is out of scope for this ADR
Follow-ups
- List concrete next actions as bullets (entry points to implementation tasks)
- If possible, include ordering or the first step
4. Template
Create new ADRs by copying the template below.
# ADR NNNN: <Short Title>
- Status: <Proposed | Accepted | ...>
- Date: YYYY-MM-DD
## Context
<Background, problem, constraints, reference links>
## Decision
<Definitive statement of this decision>
## Consequences
### Positive
- <Benefit>
### Negative / Trade-offs
- <Cost or drawback>
## Alternatives Considered
### A. <Alternative>
- <Reason it was not selected>
## Notes
- <Supplemental notes>
## Follow-ups
- <Next action>
CBF Licensing Guide
WARNING: This document is a work in progress and may be updated as the project evolves. It is intended to provide practical guidance on licensing policy for the CBF project, but should not be considered legal advice. For specific legal questions, consult a qualified attorney.
1. Scope
This document defines practical licensing policy for the standalone CBF repository. It is an engineering policy document and not legal advice.
2. Base License Choice
Recommended base license for CBF-authored code:
BSD 3-Clause
Why:
- Permissive and widely acceptable for library reuse.
- Consistent style with Chromium/CEF ecosystem expectations.
3. Layered License Model
Use a layered interpretation, not a single-license simplification:
- CBF source authored in this project: BSD 3-Clause
- Chromium and bundled third-party components: each component’s own license terms
Important implication:
- Repository base license does not remove third-party notice obligations.
4. Redistribution Responsibilities
For source-only distribution:
- Keep BSD 3-Clause license text for CBF code.
- Document that Chromium/tooling dependencies are governed by their own licenses.
- If the repository includes Chromium patch files or other Chromium-derived
source diffs, include the Chromium license text alongside the repository
(for example as
LICENSE.chromium) and note that Chromium-derived portions remain subject to Chromium’s license terms.
For binary/distribution bundles containing Chromium artifacts:
- Include third-party notices in release artifacts.
- Preserve required copyright and attribution texts.
For example apps (Tauri/GPUI etc.):
- Track app-specific dependency licenses separately from core CBF notices.
5. Release Bundle Files
For the current MVP pre-built macOS distribution, include:
Chromium.applibcbf_bridge.dylibCBF_LICENSE.txtTHIRD_PARTY_LICENSES.txtSOURCE_INFO.txt
Optional supplemental artifact:
CHROMIUM_THIRD_PARTY_NOTICES.html
CBF_LICENSE.txt is copied from the repository LICENSE.
THIRD_PARTY_LICENSES.txt should be generated from Chromium with:
python tools/licenses/licenses.py license_file --format txt
CHROMIUM_THIRD_PARTY_NOTICES.html is human-readable supplemental attribution.
It does not replace the required bundled license text.
6. Release Process Policy
The current release flow is local and manually invoked.
Recommended process:
- Regenerate
THIRD_PARTY_LICENSES.txtfrom the exact Chromium revision used for the build. - Generate
SOURCE_INFO.txtfrom the exact tagged source state used for the bundle. - Verify the release archive includes all required files.
- Manually upload the final archive after inspection.
See Release Process for the concrete MVP workflow.
7. Contributor/Consumer Clarity
README should state clearly:
- CBF code is BSD 3-Clause.
- Chromium/third-party components remain under their own licenses.
- Redistributors must include relevant notices.
8. Compliance Checklist
Before release:
-
CBF_LICENSE.txtis present and matches the repositoryLICENSE -
THIRD_PARTY_LICENSES.txtis generated for the exact Chromium revision being distributed -
SOURCE_INFO.txtis generated for the exact tagged source state being distributed - Release artifacts include the required bundled license files
- README licensing section matches actual distribution behavior
9. References
- Chromium repository license page:
- https://github.com/chromium/chromium
- Chromium license tooling:
- https://chromium.googlesource.com/chromium/src.git/+/HEAD/tools/licenses/licenses.py
- Chromium OS licensing overview:
- https://www.chromium.org/chromium-os/licensing/
- SPDX BSD-3-Clause:
- https://spdx.org/licenses/BSD-3-Clause.html