How Rust Is Integrated into Brave: The adblock-rust FFI Architecture
Brave integrates Rust through a C-style Foreign Function Interface (FFI) that compiles the adblock-rust crate into a static library, exposing C bindings that Brave's C++ code consumes through a thin wrapper layer.
Brave Browser leverages Rust for its core ad-blocking engine via the adblock-rust library, bridging the performance and memory-safety benefits of Rust with Chromium's existing C++ codebase. This integration relies on a carefully structured FFI layer that compiles Rust code into static libraries callable from Brave's native components.
The Three-Layer Architecture of adblock-rust Integration
Brave's Rust integration consists of three distinct layers that separate concerns between the Rust implementation and the C++ browser code.
1. Pure Rust Crate (adblock_rust)
The core logic resides in components/adblock_rust/, a standard Cargo project that implements filter parsing, cosmetic filtering, and network rule evaluation. This crate knows nothing about Chromium or C++.
Key file: components/adblock_rust/Cargo.toml defines the library target and dependencies.
2. FFI Bindings (adblock_rust_ffi)
This layer generates a thin C API around the Rust crate. The bindings are compiled into a static library (libadblock_rust_ffi.a) and linked into the Chromium build.
Key files:
components/adblock_rust_ffi/README.md– Overview and build instructionscomponents/adblock_rust_ffi/adblock_rust_ffi.h– C header exposing Rust functions
3. C++ Wrapper (adblock_engine.cc)
The final layer provides a C++-friendly façade used by Brave's UI and network stack. It translates Chromium's GURL objects into FFI-friendly types and manages object lifetimes.
Key file: components/adblock_rust_ffi/adblock_engine.cc implements the RAII wrapper around the C API.
Build System: Compiling Rust into Brave
Brave uses GN (Generate Ninja) to orchestrate the build, integrating Cargo through custom rules that compile Rust code into static libraries linkable by Chromium.
Step 1: Cargo Builds the Rust Crate
The components/adblock_rust/BUILD.gn file invokes the rust_static_library rule, which runs cargo build to produce libadblock_rust.a.
Step 2: FFI Wrapper Generation
The adblock_rust_ffi component contains a small lib.rs that re-exports needed symbols with #[no_mangle] extern "C" attributes. GN builds this via rust_static_library → static_library → libadblock_rust_ffi.a.
Step 3: Linking into Chromium
The resulting static library links into the brave_adblock target, making symbols available to C++ code throughout the browser.
The FFI Layer: C API Exported from Rust
The FFI header exposes a minimal C interface that hides Rust's complexity behind opaque pointers and primitive types.
/* components/adblock_rust_ffi/adblock_rust_ffi.h */
#ifdef __cplusplus
extern "C" {
#endif
/* Create a new engine from newline-separated filter text.
* Returns an opaque pointer to the Rust Engine. */
void* adblock_engine_new(const char* filters);
/* Check if a request should be blocked.
* Returns 1 for blocked, 0 for allowed. */
int adblock_engine_check(void* engine,
const char* url,
const char* source_url);
/* Release the engine and free memory. */
void adblock_engine_free(void* engine);
#ifdef __cplusplus
}
#endif
These functions use #[no_mangle] attributes in the Rust source to ensure symbol names remain stable across the FFI boundary.
C++ Integration: Consuming the FFI in Brave
Brave's C++ code wraps the C API in a RAII class that manages the opaque pointer automatically.
// components/adblock_rust_ffi/adblock_engine.cc
#include "components/adblock_rust_ffi/adblock_rust_ffi.h"
class AdBlockEngine {
public:
explicit AdBlockEngine(const std::string& filters) {
raw_engine_ = adblock_engine_new(filters.c_str());
}
~AdBlockEngine() {
if (raw_engine_) {
adblock_engine_free(raw_engine_);
}
}
bool ShouldBlock(const GURL& request_url, const GURL& source_url) {
int result = adblock_engine_check(
raw_engine_,
request_url.spec().c_str(),
source_url.spec().c_str());
return result != 0;
}
private:
void* raw_engine_ = nullptr;
};
This wrapper translates Chromium's GURL objects into C strings and ensures the Rust engine is properly freed when the C++ object goes out of scope.
Code Examples: Using the Adblock Engine
Example 1: Creating the Engine
#include "components/adblock_rust_ffi/adblock_engine.h"
std::unique_ptr<AdBlockEngine> CreateEngine(
const std::vector<std::string>& raw_filters) {
// Join filter lists into newline-separated text
std::string joined;
for (const auto& filter : raw_filters) {
joined += filter + "\n";
}
void* raw_engine = adblock_engine_new(joined.c_str());
if (!raw_engine) {
LOG(ERROR) << "Failed to instantiate adblock engine";
return nullptr;
}
return std::make_unique<AdBlockEngine>(raw_engine);
}
Source: components/adblock_rust_ffi/adblock_engine.cc
Example 2: Checking a Network Request
bool ShouldBlockRequest(AdBlockEngine* engine,
const GURL& request_url,
const GURL& source_url) {
// Convert GURL to UTF-8 C strings
std::string req = request_url.spec();
std::string src = source_url.spec();
int blocked = adblock_engine_check(engine->raw_ptr(),
req.c_str(),
src.c_str());
return blocked != 0;
}
Example 3: Integrating with Brave Shields UI
void BraveShieldsHandler::OnToggleAdBlocking(bool enabled) {
if (enabled) {
// Load filter lists from disk
std::vector<std::string> lists = LoadFilterLists();
adblock_engine_ = CreateEngine(lists);
} else {
adblock_engine_.reset(); // Calls adblock_engine_free internally
}
}
Source: browser/brave_shields_handler.cc
Summary
- Three-layer architecture: Pure Rust crate (
adblock_rust), C FFI bindings (adblock_rust_ffi), and C++ wrapper (adblock_engine.cc). - Static linking: The Rust code compiles into
libadblock_rust_ffi.aand links directly into the Chromium binary, avoiding runtime overhead. - Minimal FFI surface: The C API exposes only three core functions (
adblock_engine_new,adblock_engine_check,adblock_engine_free) to minimize unsafe boundary risks. - RAII wrapper: C++ code manages the opaque Rust pointer through
AdBlockEngine, ensuring automatic cleanup when the browser destroys the profile. - Cross-platform: The same Rust crate builds for Windows, macOS, Linux, Android, and iOS using Brave's GN/Cargo integration.
Frequently Asked Questions
How does Brave call Rust code from C++?
Brave uses a C-style Foreign Function Interface (FFI) that exposes Rust functions with #[no_mangle] extern "C" attributes. The C++ code includes adblock_rust_ffi.h and calls functions like adblock_engine_new() and adblock_engine_check(), which are linked from the static library libadblock_rust_ffi.a compiled by Cargo.
Why does Brave use FFI instead of rewriting everything in Rust?
Brave builds on top of Chromium, which contains millions of lines of C++ code. Rewriting the entire browser in Rust would be impractical and would complicate merging upstream Chromium updates. The FFI approach allows Brave to incrementally adopt Rust for specific components—like the ad-blocking engine—while maintaining the existing C++ infrastructure and update mechanisms.
What is the performance impact of the FFI layer?
The performance impact is negligible because the FFI uses static linking and a minimal C API surface. The Rust code compiles into a native static archive (libadblock_rust_ffi.a) that links directly into the Chromium binary, eliminating dynamic linking overhead. The C functions accept primitive types and pointers, avoiding complex marshalling costs during the critical path of network request filtering.
Where are the adblock-rust source files located?
The source files reside in the brave-core submodule under src/brave. The pure Rust implementation lives in components/adblock_rust/, while the FFI bindings and C++ wrapper are in components/adblock_rust_ffi/. The top-level brave-browser repository references these components as a submodule, with build instructions available in components/adblock_rust_ffi/README.md.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →