项目简介
Ladybird[1] 是一款真正独立的网页浏览器,采用基于 Web 标准的全新引擎。
目标是打造一款完整、可用、面向现代 Web 的浏览器,而 不是 Chromium / WebKit / Gecko 的移植。 代码体量大约与 Servo 同级,约为 WebKit C++ 的 1/15、Gecko 的 1/20、Chromium 的 1/50。当前仍是 pre-alpha
Ladybird 采用多进程架构,包含一个主 UI 进程、若干 WebContent 渲染进程、一个 ImageDecoder 进程,以及一个 RequestServer 进程。
图像解码和网络连接在独立进程中完成,以提高对恶意内容的鲁棒性。每个标签页都有自己的渲染进程,并与系统其余部分隔离(沙箱化)。
目前,许多核心库支持组件继承自 SerenityOS:
LibWeb:网页渲染引擎 LibJS:JavaScript 引擎 LibWasm:WebAssembly 实现 LibCrypto / LibTLS:密码学原语与传输层安全(TLS) LibHTTP:HTTP/1.1 客户端 LibGfx:2D 图形库、图像解码与渲染 LibUnicode:Unicode 与区域设置支持 LibMedia:音频与视频播放 LibCore:事件循环、操作系统抽象层 LibIPC:进程间通信
Ladybird 的关键技术原理可以概括成一句话:按 Web 标准从零实现引擎,用多进程把“不可信网页”与 UI/网络/解码隔离开,用多棵树把页面从 HTML 变成像素。 下面按分层把源码结构对应到设计原则。
关键技术
AK/ | ErrorOr、字符串 |
Libraries/ | |
Services/ | WebContentRequestServer、ImageDecoder、WebWorker |
UI/ | |
Documentation/ |
进程模型:把攻击面切到进程边界
设计目标不是“快”,而是 面对任意(可能恶意)网页时的稳定与隔离。下面是其进程模型的示意图:
┌────────────── Browser / UI 进程 ──────────────┐
│ Qt / AppKit / GTK │
│ LibWebView::Application │
│ 设置、书签、Cookie、历史、进程生命周期 │
│ 每个标签一个 ViewImplementation ──IPC──┐ │
└──────────────────────────────────────────│────┘
│
┌──────────────┬───────────────────┴──────────────┐
▼ ▼ ▼
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ WebContent │ │ WebContent │ …每标签/站点一份 │ WebContent │
│ LibWeb+LibJS│ │ │ │ │
│ 无直接网络 │ │ │ │ │
└──────┬──────┘ └──────┬──────┘ └──────┬──────┘
│ │ │
▼ ▼ ▼
┌─────────────┐ ┌─────────────┐
│RequestServer│ HTTP/HTTPS/WebSocket/缓存/TLS │ImageDecoder │
└─────────────┘ └─────────────┘
关键隔离点:
每标签一个 WebContent:HTML/CSS/JS/布局/绘制都在这里。崩溃只死一个标签。跨源导航可再开新进程(站点隔离方向)。 网络不在渲染进程:WebContent 只能经 RequestServer出门。DNS、HTTP、TLS、磁盘缓存都在网络进程。解码不在渲染进程:图片历史上是内存破坏高发区,解码在强沙箱的 ImageDecoder,成功才回传 bitmap。WebWorker 单独进程:后台脚本与页面主世界隔离。 沙箱:文档描述 pledge()/unveil();Linux 侧还有 seccomp 一类限制。除 UI 进程外,辅助进程以非登录用户跑。
库分层
依赖方向大致是:
UI / LibWebView
↓
LibWeb ←—— LibJS ← LibGC ← AK
↓
LibGfx / LibURL / LibIPC / LibMedia / LibHTTP / LibTLS
↓
AK
原则上每个进程只链它该有的库。RequestServer 不链 LibWeb;ImageDecoder 不跑 JS。AK 相当于项目自己的 STL 风格基础层。
LibWeb 内部再按 规范名分子目录 + 命名空间:
Libraries/LibWeb/HTML/→Web::HTMLLibraries/LibWeb/DOM/→Web::DOMLibraries/LibWeb/CSS/、Fetch/、SVG/、WebGL/…
找实现就按规范找目录,这是刻意的可导航性。
4. LibWeb 渲染管线
这是整台引擎最核心的技术原理。
URL
│ IPC
▼
RequestServer 拉字节
│
▼
HTMLParser ──► DOM 树
CSSParser ──► CSSOM(变量先保持 unresolved)
LibJS ──► 脚本可 document.write 回灌解析器
│
▼
StyleComputer
选择器从右向左匹配
按 origin(UA → author)+ specificity + !important 层叠
在 cascade 阶段解析 custom property
──► StyleProperties / ComputedProperties
│
▼
TreeBuilder ──► Layout 树(CSS 盒树的 C++ 化)
display:none 不生成节点
匿名盒修复:块/行级孩子混排、残缺 table、list-item marker
│
▼
FormattingContext 递归排版(从 ICB / 视口开始)
BFC / IFC / TFC / FFC / GFC + 自研 SVGFormattingContext
产出 LayoutState(used values);可 commit 或丢弃(不可变测量)
│
▼
Paintable 树 ──► 层叠上下文
按 CSS2 附录 E 分相位绘制:背景 → 边框 → float → 前景文字 → outline → overlay
│
▼
DisplayList 记录绘制命令
DisplayListPlayerSkia 在渲染线程用 Skia(Vulkan/Metal/CPU)回放
共享 backing store 交给 Browser 进程上屏
项目地址
https://github.com/LadybirdBrowser/ladybird
感谢阅读。如果本文对你有帮助,欢迎点赞、在看,或转发给需要的朋友。
参考资料
Ladybird: https://ladybird.org/