Zhyx's Blog

Back

编译与运行#

参考文档:

macOS 上需要 Xcode SDK,可以先检查:

ls -l `xcode-select -p`/Platforms/MacOSX.platform/Developer/SDKs
sh

安装 depot_tools

git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
sh

depot_tools 加入环境变量。这里用 $HOME,避免把机器用户名写死:

echo 'export PATH="$HOME/zen/depot_tools:$PATH"' >> ~/.zshrc
source ~/.zshrc
sh

获取 Chromium 源码:

caffeinate fetch chromium
sh

当前本地工作区结构是:

/Users/zhyw/zen/chromium       # gclient 工作区
/Users/zhyw/zen/chromium/src   # 真正的 Chromium 源码根目录
text

生成构建文件和编译:

cd /Users/zhyw/zen/chromium/src
gn gen out/Default
autoninja -C out/Default chrome
sh

运行:

out/Default/Chromium.app/Contents/MacOS/Chromium
sh

源码目录#

Chromium 源码根目录是 chromium/src。外层 chromium/ 主要是 gclient 工作区,包含 .gclient.cipd 等依赖同步文件。

产品层
  chrome/
  android_webview/
  headless/
  ash/

浏览器核心嵌入层
  content/

Web 平台和渲染引擎
  third_party/blink/
  v8/
  gin/

渲染后半段
  cc/
  components/viz/
  gpu/
  skia/

基础服务和 IPC
  services/
  mojo/

通用能力
  base/
  net/
  media/
  storage/
  ui/
  components/

构建、测试、工具、依赖
  build/
  tools/
  testing/
  third_party/
text

最容易混淆的是这三个目录:

目录定位
chrome/Chrome 产品层,包含 UI、浏览器功能、产品集成
content/多进程浏览器核心,负责导航、frame、进程、安全、WebContents
third_party/blink/Blink 渲染引擎和 Web Platform 实现

可以先记成一句话:

chrome 是产品,
content 是页面运行的多进程外壳,
Blink 是 DOM / CSS / Layout / Paint 的引擎。
text

chrome:Chrome 产品层#

chrome/ 包含 Chrome 这个产品的应用层代码。它不是浏览器内核本身,而是把 content/components/ui/、各种服务整合成用户可见的浏览器。

常见子目录:

目录作用
chrome/app/Chrome 进程启动入口、资源、delegate
chrome/browser/Browser Process 中的 Chrome 产品逻辑
chrome/browser/ui/浏览器窗口、标签页、地址栏、菜单、WebUI
chrome/common/多进程共享的 Chrome 常量、开关、数据结构
chrome/renderer/Chrome 产品在 Renderer Process 中的扩展逻辑
chrome/test/Chrome 层测试

用户在地址栏输入 URL 时,最前面的入口属于 chrome/

地址栏 / omnibox
→ chrome/browser/ui
→ Chrome tab / browser window
→ content/public/browser
→ content/browser 接管导航
text

chrome/ 的边界意识很重要。Chrome 产品层不应该直接操作 Blink 的 DOM 或 Layout,而是通过 content/public 提供的 API 使用网页内容容器,比如 WebContents

content:多进程浏览器核心#

content/ 是渲染一个页面所需要的核心基础设施。它实现多进程、沙盒化、导航、frame 管理、Renderer 管理、GPU 加速接入等能力,但不包含 Chrome 产品功能。

content/chrome/ 的分工:

层级负责不负责
content/Web Platform 所需的页面运行基础,多进程、导航、frame、sandbox、WebContentsChrome 产品 UI、同步、翻译、Safe Browsing 等产品能力
chrome/产品功能、浏览器 UI、Profile 集成、厂商服务集成Blink 内核实现细节

content/ 的目录通常按进程划分:

目录对应角色说明
content/browser/Browser Process导航、WebContents、FrameTree、RenderFrameHost、权限、安全、进程管理
content/renderer/Renderer ProcessRenderer 入口、RenderFrameImpl、和 Blink 的连接
content/gpu/GPU Process 相关content 对 GPU 进程的嵌入和启动逻辑
content/utility/Utility Process辅助进程相关代码
content/common/多进程共享browser/renderer 共用的数据结构、mojom、常量
content/public/对 embedder 暴露 APIChrome、WebView、headless 通过这里使用 content
content/shell/最小浏览器壳不带完整 Chrome 产品层,用于测试 content / Blink

阅读导航主线时,几个类值得先建立印象:

概念代码位置说明
标签页网页内容容器content/browser/web_contents/web_contents_impl.*WebContentsImpl 是 tab 内容的核心容器
导航请求content/browser/renderer_host/navigation_request.*NavigationRequest 表示一次正在进行的导航
Browser 侧 framecontent/browser/renderer_host/render_frame_host_impl.*RenderFrameHostImpl 代表 Renderer 中的一个 frame
Renderer 主线程入口content/renderer/render_thread_impl.*Renderer Process 和 browser 侧通信的核心连接点

content/public:embedder 边界#

content/publiccontent 暴露给上层 embedder 的 API。Chrome、Android WebView、headless 都应该通过这里使用 content,而不是直接 include content/browsercontent/renderer 的内部实现。

这层 API 的作用:

chrome/ 可以使用 content/public
content/ 不依赖 chrome/
content 内部实现不随便暴露给上层产品
text

常见边界类:

类 / 目录作用
content/public/browser/WebContents上层看到的网页内容容器接口
content/public/browser/WebContentsObserver观察导航、加载、frame 等事件
content/public/browser/ContentBrowserClientcontent 回调 embedder 的 Browser 侧接口
content/public/renderer/ContentRendererClientcontent 回调 embedder 的 Renderer 侧接口
content/public/common/跨进程、跨 embedder 的公共数据结构

components:可复用功能层#

components/ 用来放多个产品或多个 embedder 复用的功能。它不是随便拆模块的地方,而是给确实有复用需求的功能提供稳定边界。

典型使用场景:

场景说明
Chrome 和 iOS Chrome 共用//ios 不依赖 //chrome,共享逻辑需要抽出
Chrome 和 Android WebView 共用多个 content embedder 共享同一套功能
Browser Process 和 Blink 共用如果不是 Blink 自己拥有的代码,可以放在 components

一次网页打开时,权限、历史记录、下载、favicon、内容设置等功能可能会通过 components/ 参与,但页面生命周期本身仍由 content/ 管理。

services 与 mojo#

services/ 里是基础服务,mojo/ 是服务和模块之间通信的 IPC 基础设施。

可以这样区分:

services/ 定义服务集合
mojo/ 提供服务之间的接口定义和通信方式
text

常见服务:

目录服务
services/network/Network Service
services/audio/Audio Service
services/device/Device Service
services/data_decoder/数据解码服务
services/tracing/tracing / perfetto
services/viz/Viz service 接口和运行 glue

mojo 里的几个关键词:

概念含义
mojomMojo 接口定义文件
message pipe双端消息管道
data pipe适合传输大量数据
shared buffer跨进程共享内存
Remote / ReceiverC++ bindings 中常见的调用端和接收端

普通页面加载时,Network Service 的位置大致是:

content/browser
→ services/network
→ net/
text

net/ 是网络协议栈和底层实现,services/network/ 是网络能力的服务化边界。

Blink:Web 平台和渲染引擎#

Blink 主要在:

third_party/blink/
  public/
  common/
  renderer/
    core/
    modules/
    platform/
    bindings/
  web_tests/
  tools/
text

关键层次:

目录作用
third_party/blink/public/Blink 对外公开接口
third_party/blink/common/Blink browser/renderer 共用数据
third_party/blink/renderer/core/DOM、CSS、Layout、Paint、Frame、Loader 等核心 Web 平台
third_party/blink/renderer/modules/Web API 模块,如 WebAudio、WebGPU、ServiceWorker、WebRTC、MediaSource
third_party/blink/renderer/platform/图形、字体、网络抽象、scheduler、heap、media 等平台层
third_party/blink/renderer/bindings/Web IDL 到 V8 / Blink C++ 的绑定
third_party/blink/web_tests/Web 平台和 Blink 行为测试

渲染流水线主要落在 renderer/core/

阶段典型目录
HTML parsingrenderer/core/html/parser/
DOMrenderer/core/dom/
Frame / Documentrenderer/core/frame/renderer/core/dom/
Loadingrenderer/core/loader/
CSS / Stylerenderer/core/css/renderer/core/style/
Layoutrenderer/core/layout/
Pre-paint / Paintrenderer/core/paint/
Events / Inputrenderer/core/events/renderer/core/input/
Workersrenderer/core/workers/

cc、Viz、GPU:渲染后半段#

Blink 完成 Style、Layout、Paint 之后,后半段由 cc、Viz、GPU 接住。

cc/ 是 layer compositor,负责 compositor tree、commit、raster 调度、activate、draw。关键类包括:

说明
cc::LayerTreeHostmain thread 侧 layer tree host
cc::LayerTreeHostImplcompositor / impl side host
cc::Layermain thread 侧 layer 抽象
cc::LayerImplimpl side layer 抽象

components/viz/ 负责 Surface、DrawQuad、RenderPass、CompositorFrame、Surface Aggregation、Display Compositor 等。gpu/ 更靠近 GPU command buffer、图形 API 和平台后端。

后半段可以先记成:

Blink PaintArtifact
→ layerization
→ cc LayerTreeHost
→ commit 到 impl side
→ raster tile
→ activate active tree
→ DrawQuad / RenderPass
→ viz::CompositorFrame
→ Viz Surface Aggregation
→ GPU Display
text

一次网页打开:从 URL 到首帧#

把源码目录和前面的理论流程合起来,一次普通网页打开可以分成这些阶段:

1. Chrome 产品 UI
   chrome/browser/ui

2. 发起导航
   chrome/browser
   content/public/browser
   content/browser/web_contents

3. 创建导航状态
   content/browser/renderer_host/NavigationRequest
   content/browser/renderer_host/RenderFrameHostImpl

4. 发起网络请求
   content/browser/loader 或 network 相关 glue
   services/network
   net

5. 选择或创建 Renderer Process
   content/browser/renderer_host
   RenderProcessHost
   SiteInstance
   BrowsingInstance

6. 提交导航到 Renderer
   Mojo / IPC
   content/renderer

7. Blink 加载主文档
   third_party/blink/renderer/core/loader
   DocumentLoader

8. HTML 解析和子资源发现
   third_party/blink/renderer/core/html/parser
   preload scanner
   子资源继续通过 services/network 加载

9. JS 执行
   third_party/blink/renderer/bindings
   v8
   gin

10. 渲染流水线
    Blink core: Style / Layout / Pre-paint / Paint
    cc: Commit / Raster / Activate / Draw
    Viz: Aggregate / Display

11. Browser UI 和页面一起合成
    chrome/browser/ui
    ui/
    cc/
    components/viz/
    gpu/
text
负责不负责
chrome/产品 UI、浏览器功能、用户入口DOM / Layout / Paint 内核实现
content/导航、frame、进程、安全、WebContentsChrome 特有产品功能
services/network网络服务边界DOM 解析
net/网络协议栈实现页面生命周期
blink/Web 平台、DOM、CSS、Layout、PaintBrowser UI
cc/compositor tree、raster 调度、DrawQuadHTML parser
viz/Surface 聚合、Display Compositor页面业务逻辑
gpu/GPU 命令、图形后端导航策略

对应渲染流水线#

RenderingNG 的阶段可以直接映射到源码目录:

阶段主要源码目录关键产物 / 概念
Navigation commitcontent/browser/renderer_hostcontent/rendererNavigationRequestRenderFrameHostImplRenderFrameImpl
Loadingthird_party/blink/renderer/core/loaderDocumentLoader、resource load
Parsingthird_party/blink/renderer/core/html/parsertoken、DOM nodes
DOMthird_party/blink/renderer/core/domDocumentNodeElement
JS bindingsthird_party/blink/renderer/bindingsv8/gin/Web IDL binding、V8 objects
Stylethird_party/blink/renderer/core/csscore/styleComputed Style
Layoutthird_party/blink/renderer/core/layoutLayout objects / fragments
Pre-paintthird_party/blink/renderer/core/paintProperty Trees、paint invalidation
Paintthird_party/blink/renderer/core/paintDisplay items、PaintArtifact
LayerizationBlink paint + cc/compositing reasons、cc layer data
Commitcc/treesLayerTreeHostLayerTreeHostImpl
Tiling / Rastercc/tilescc/rasterskia/Tile、Raster task、texture
Activatecc/treesPending tree → Active tree
Drawcc/components/viz/common/quadsDrawQuadRenderPassCompositorFrame
Aggregatecomponents/viz/service/displaySurface Aggregation
Displaycomponents/viz/service/displaygpu/GPU output、pixels

几个概念需要持续区分:

概念说明
PaintBlink 生成绘制记录,不直接生成最终屏幕像素
Rastercc / Skia 把绘制记录转换为 tile texture 或 bitmap
Drawcc 遍历 active tree,把已有资源组织成 DrawQuad / RenderPass
DisplayViz / GPU 把聚合后的结果输出到屏幕

视频子系统#

media/ 不是主渲染流水线的一部分,但它和 <video><audio>、MSE、EME、WebRTC、硬件解码、Audio Output、VideoFrame 合成都强相关。

常见目录:

目录作用
media/base/媒体通用数据结构,如 VideoFrameAudioBus、codec enum
media/audio/平台音频输入输出实现
media/capture/屏幕、标签页、摄像头采集
media/ffmpeg/FFmpeg 绑定
media/filters/demuxer、decoder、data source、pipeline controller
media/formats/container / MSE 格式解析
media/gpu/平台硬件编解码实现
media/mojo/媒体服务化、跨进程媒体能力
media/renderers/音频/视频渲染器
media/video/抽象硬件视频解码接口和工具

视频相关代码不只在 media/,还会跨越 Blink 和 content:

典型路径作用
Blink DOMthird_party/blink/renderer/core/html/media/HTMLMediaElementHTMLVideoElement
Blink platform mediathird_party/blink/renderer/platform/media/WebMediaPlayerImplVideoFrameCompositor
content gluecontent/renderer/media/MediaFactory,连接 Blink 和 media
media pipelinemedia/filters/media/base/media/renderers/加载、解复用、解码、渲染
hardware decodemedia/gpu/平台硬解
compositor / vizcc/components/viz/视频帧参与最终合成

H5 视频相关概念#

普通 <video> 只是入口,背后还有几类重要 Web 媒体能力:

概念说明典型路径
HTMLMediaElement<audio><video> 的公共基础行为,如 load、play、pause、seekthird_party/blink/renderer/core/html/media/html_media_element.*
HTMLVideoElement<video> 元素本身,包含视频尺寸、poster、画面相关能力third_party/blink/renderer/core/html/media/html_video_element.*
MSEMedia Source Extensions,JS 手动 append 媒体分片,常用于 DASH / HLS 类播放器third_party/blink/renderer/modules/mediasource/media/filters/chunk_demuxer.*
EMEEncrypted Media Extensions,DRM / CDM 相关third_party/blink/renderer/modules/encryptedmedia/media/cdm/
MediaStream摄像头、麦克风、屏幕共享、WebRTC 等实时媒体流third_party/blink/renderer/modules/mediastream/media/capture/
WebCodecs让 JS 直接访问编码/解码能力third_party/blink/renderer/modules/webcodecs/
WebAudioWeb 音频图处理third_party/blink/renderer/modules/webaudio/

第一轮阅读先选择普通 src= 播放,不一开始展开 WebRTC、MSE、EME、WebCodecs。普通路径足够把 Blink、content、media、cc、Viz 串起来。

普通 video src 播放链路#

一个普通视频:

<video src="bear.mp4" controls></video>
html

粗略链路:

HTMLVideoElement / HTMLMediaElement
→ WebMediaPlayerImpl
→ PipelineController
→ PipelineImpl
→ FFmpegDemuxer
→ DecoderStream
→ AudioRenderer / VideoRenderer
→ VideoFrame
→ VideoFrameCompositor
→ cc / Viz
→ Display
text

更贴近源码的调用关系:

HTMLMediaElement::load()
HTMLMediaElement::play()
→ StartPlayerLoad()
→ CreateWebMediaPlayer()
→ content::MediaFactory::CreateMediaPlayer()
→ WebMediaPlayerBuilder::Build()
→ WebMediaPlayerImpl

WebMediaPlayerImpl::Load()
→ WebMediaPlayerImpl::DoLoad()
→ DemuxerManager::CreateDemuxer()
→ FFmpegDemuxer 或 ChunkDemuxer
→ PipelineController::Start()
→ PipelineImpl::Start()
→ RendererImpl
→ AudioRendererImpl / VideoRendererImpl
→ DecoderStream
→ VideoFrameCompositor
text

关键文件:

文件作用
third_party/blink/renderer/core/html/media/html_media_element.ccDOM 层媒体元素,处理 load/play/pause/seek 等状态
third_party/blink/renderer/core/html/media/html_video_element.ccvideo 元素特有行为
content/renderer/media/media_factory.ccRenderer 侧创建 media player 的 glue
third_party/blink/renderer/platform/media/web_media_player_builder.cc构建 WebMediaPlayerImpl
third_party/blink/renderer/platform/media/web_media_player_impl.ccBlink 和 media pipeline 之间的核心播放器
media/filters/pipeline_controller.cc控制 pipeline 的 start/seek/suspend/resume
media/base/pipeline_impl.ccmedia pipeline 核心编排
media/filters/ffmpeg_demuxer.cc普通 src 播放的解复用
media/filters/chunk_demuxer.ccMSE 播放的解复用
media/filters/decoder_stream.cc串联 demuxer stream 和 decoder
media/renderers/renderer_impl.cc协调 audio/video renderer
media/renderers/video_renderer_impl.cc视频渲染调度
third_party/blink/renderer/platform/media/video_frame_compositor.cc视频帧进入 compositor 的关键点

普通 src= 和 MSE 的分叉:

场景Demuxer数据来源
<video src="xxx.mp4">FFmpegDemuxerWebMediaPlayerImpl 负责从网络/文件加载 bytes
MSEChunkDemuxerJS 通过 SourceBuffer append muxed bytes

视频和普通渲染流水线的关系#

普通 DOM/CSS 内容:

DOM / CSS
→ Style
→ Layout
→ Paint
→ Raster
→ Tile texture
→ DrawQuad
→ CompositorFrame
text

视频内容:

media bytes
→ Demux
→ Decode
→ VideoFrame
→ VideoFrameCompositor
→ video quad / surface / overlay
→ Viz
→ Display
text

<video> 元素本身仍然参与 DOM、Layout、Paint。它有位置、尺寸、裁剪、透明度、transform,也可能影响 compositing。但是视频每一帧的像素数据不会像普通 DOM 内容那样每次都重新 Paint / Raster。

可以这样理解:

主渲染流水线决定 video 元素这个盒子的位置、裁剪和合成属性;
media pipeline 决定盒子里面此刻应该显示哪一帧;
Viz / GPU 负责把页面内容、视频帧、Browser UI 聚合到最终画面。
text

这也是 VideoNG 里“video 像一个洞”的含义。洞的几何属性由 Blink / cc 管,洞里的动态画面由 media pipeline 管,最后在 Viz 层统一合成。

播控流程#

播控从 DOM API 或用户操作开始,先进入 Blink 的媒体元素状态机,再传给 WebMediaPlayerImpl 和 media pipeline。

play#

HTMLMediaElement::play()
→ 更新 pending play promise / autoplay / user gesture 等状态
→ 调用 WebMediaPlayerImpl::Play()
→ pipeline resume / start rendering
→ audio/video renderer 开始按时钟拉取和输出数据
text

play() 不只是“开始解码”。它还要处理:

状态说明
autoplay policy是否允许自动播放
pending play promiseJS video.play() 返回的 Promise
readyState当前是否有足够数据播放
networkState是否需要继续加载
media session页面媒体会话状态
pipeline statepipeline 是否已经初始化、是否需要 resume

pause#

HTMLMediaElement::pause()
→ 更新 paused 状态
→ WebMediaPlayerImpl::Pause()
→ pipeline / renderer 暂停输出
→ 保留当前播放位置和缓冲状态
text

暂停一般不会释放所有资源。它更像把输出停住,并保留当前状态,方便继续播放。

seek#

HTMLMediaElement 设置 currentTime
→ 进入 seeking 状态
→ WebMediaPlayerImpl::Seek()
→ PipelineController::Seek()
→ demuxer / decoder flush 或重新定位
→ renderer 在新时间点重新输出
text

seek 要处理的事情比 play/pause 更复杂:

阶段说明
更新目标时间DOM 层记录新的 currentTime
进入 seeking触发 seeking 事件
flush清理旧时间点附近的 buffer / decoder 状态
demuxer seek找到新时间点附近的关键帧或媒体数据
decoder restart重新解码目标时间附近数据
ready有新帧后触发 seeked,继续播放或停在目标帧

关键数据和流转#

视频播放中有几类重要数据:

数据所在阶段说明
URL / ResourceRequest加载阶段视频资源地址和请求信息
encoded bytes加载后从网络、文件或 MSE 进入的压缩媒体数据
container packetsdemux 阶段MP4/WebM 等容器中拆出的音视频 packet
stream configdemux 后codec、分辨率、采样率、颜色空间等
compressed buffersdecode 前送入 decoder 的压缩音视频 buffer
decoded audioaudio decode 后供 AudioRenderer 输出
media::VideoFramevideo decode 后解码后的视频帧,可能是 CPU memory 或 GPU-backed resource
playback time渲染阶段当前播放时间、媒体时间、音视频同步
viz::DrawQuadcompositor 阶段最终合成用的绘制单元
viz::CompositorFrame提交阶段Renderer / Browser UI 提交给 Viz 的一帧合成数据

几个设计上的重点:

大块媒体数据尽量避免跨进程反复复制。
视频帧可能使用共享内存、GPU texture、mailbox 等方式流转。
音频通常以 audio callback / sink 的节奏拉取数据。
视频通常由 compositor 的节奏驱动,按显示时机取合适帧。
text

音视频同步通常以 audio time source 为核心。视频渲染器根据当前媒体时间选择合适的 VideoFrame,再通过 VideoFrameCompositor 交给 compositor。

进程和线程分工#

普通视频播放会横跨多个进程和线程:

位置负责
Browser Processtab、权限、网络服务连接、音频输出通道、进程管理
Renderer Process Main ThreadDOM、HTMLMediaElement 状态、JS 播控、Layout/Paint
Renderer Process Media Thread / Workerdemux、decode、pipeline task
Renderer Compositor Thread合成调度、视频帧提交、Draw
Utility / Network Service网络请求、资源加载
GPU / Viz ProcessSurface 聚合、GPU 资源、最终显示

一个重要原则:

DOM 状态和媒体 pipeline 状态不是同一层。
DOM 层负责 Web API 语义;
media 层负责字节、解码、音视频同步和输出;
compositor / Viz 负责最终合成。
text
chromium source code reading
https://zhyx.xyz/blog/19_chromium%E6%BA%90%E7%A0%81%E9%98%85%E8%AF%BB
Author Zhang Yix
Published at 2026年5月7日