Firefox Architecture
Understanding the multi-process beast: From URL to Pixels.
The Multi-Process Model (Electrolysis / e10s)
Modern Firefox isn't just one program; it's a squad of cooperating processes. This separation ensures that if one tab crashes, the browser stays open.
Deep Dive: How do languages talk to each other?
Q: "Since Mozilla is built on different languages (C++, Rust, Python, JS), how do they talk to each other?"
Excellent question! This is one of the most technical and impressive parts of Firefox's architecture. They communicate using several different "bridges":
1. C++ and Rust (The Main Runtime Bridge)
This is the most critical bridge since Firefox is moving more code from C++ to Rust. They use two main tools:
- bindgen: A tool that automatically generates Rust bindings from C++ header files. It allows Rust code to call C++ functions as if they were Rust functions.
- cbindgen: The reverse. It reads Rust code and generates C++ header files, allowing C++ to call Rust functions.
- XPCOM (Cross Platform Component Object Model): Firefox's ancient "universal object" system. An XPCOM component
is defined in an interface file (
.idl). Once defined, it can be implemented in C++, Rust, or JS. The system handles the binary interface (ABI) matching.
2. C++ and JavaScript (The Engine Bridge)
When the browser UI (JS) needs to do something heavy (like "save this file to disk"), it calls a C++ function.
- WebIDL (Web Interface Definition Language): The modern standard. Developers write a
.webidlfile defining the interface. - Build Time: Python scripts parse this file and generate "glue code" in C++.
- Runtime: When JS calls
file.save(), the engine looks up the generated C++ glue code, converts the JS string arguments to C++ strings, and calls the actual C++ implementation.
3. Python and Everything Else (The Build Bridge)
Python does not run inside Firefox when you browse the web. Its usage is almost entirely at Build Time.
-
Python scripts (
mach,configure) orchestrate the compilation. - They generate the C++ and Rust code that does run.
-
For example, Python reads a list of preferences (
firefox.js) and generates a C++ header file so the C++ engine can read them efficiently.
Summary Visualization
| Language A | Language B | Bridge Mechanism | Used For |
|---|---|---|---|
| C++ | Rust | bindgen / cbindgen / XPCOM | Core engine components (Stylo, WebRender) |
| C++ | JavaScript | WebIDL / XPCOM | Exposing Browser APIs (DOM) to JS |
| Python | C++/Rust | Code Generation | Generating boilerplate glue code (Build time) |
The Life of a Tab: Step-by-Step
What actually happens when you type google.com and
hit enter?
1. The Setup (Main Process)
The Main Process handles the UI (the address bar, back buttons). It recognizes the URL and assigns a Content Process to handle this page. If a suitable process exists, it reuses it; otherwise, it spawns a new one.
2. Networking (Socket Process)
Firefox delegates the network fetch to the Socket Process (or Main Process networking thread).
- DNS Lookup: Resolving the IP.
- TLS Handshake: Securing the connection.
- HTTP Request: Sending the headers.
Once data starts streaming back, it is shipped via IPC to the target Content Process.
3. Parsing & DOM (Content Process)
The Content Process receives the HTML stream. The Parser constructs the DOM (Document Object Model) tree. Simultaneously,
it encounters <script> tags, pausing to let
SpiderMonkey (the JS engine) download and execute
code.
4. Style & Layout (Content Process)
Gecko (the styling engine) computes the CSS for every node. It produces a Frame Tree (Layout tree), identifying exactly where every rectangle, line of text, and image sits on the page (x, y, width, height).
5. Display List & Paint (Content -> GPU)
The layout is converted into a Display List — a high-level set of drawing instructions ("Draw a red rectangle here", "Draw text here"). This list is sent to the GPU Process.
6. Composite (GPU Process)
The GPU Process uses WebRender (written in Rust) to interact with the hardware driver (OpenGL/DirectX/Vulkan). It rasterizes the commands into pixels and "composites" result onto the screen buffer.
Connect & Discuss
Have questions about systems engineering, or found a bug in the code? Reach out!
Feedback
This blog is a static site, but I'd love to hear your thoughts. You can discuss this post by sending me an email or reaching out on social media.
Send Feedback