QUIC, a multiplexed stream transport over UDP 是Chromium使用的通信协议,是基于UDP实现的类似于 TCP+TLS+HTTP/2 的协议。也是HTTP 3.0的设计方案。有兴趣的话大家可参考文档: Playing with QUIC
Chromium项目是开源的,The Chromium Projects(http://dev.chromium.org/chromium-projects) 文档详细介绍了Chromium项目的实现原理,以及如何获取源码并进行编译。
Cronet 库是Chrome使用的移动端网络库。支持 HTTP、HTTP/2 以及 QUIC 协议。支持 Android 和 iOS 平台。 其编译工具是 gn 和 ninja,类似于 cmake 与 make 的关系。 下面介绍 Cronet 库的编译及编译注意事项。
可以参考官方文档:Checking out and building Chromium for Mac
获取源码之前,首先需要下载安装 depot_tools 工具。在一个适当的目录下clone depot_tools包:
$ git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
将depot_tools
的路径(最好是绝对路径,~
需替换为$HOME
)加进环境变量PATH中,假设 depot_tools
工程在/path/to/depot_tools
目录下:
export PATH=$PATH:/path/to/depot_tools
如果从来没有下载过Chromium的代码的话,为源码创建一个文件夹并下载源码:
mkdir chromium && cd chromium
fetch --no-history chromium # 可能花费30min或几小时,依网络速度而不同
–no-history
可以节省代码下载时间,它忽略仓库的历史信息;整个代码量较大,约 14G,且需要,1M 左右的速度需要 20~30 分钟。若中间拉取失败,可以执行 gclient sync
继续拉取, 拉取结束后,该目录会生成一个 src 目录,包含 cronet 源码。
获取源码是很漫长的过程,Chromium项目的源码有8G。我花了2个半小时才完成。中途遇到了download_from_google_storage.py 下载文件没反应的问题,参考了Chromium的源码获取与编译(2018-06-06)
命令行,需要使用 http proxy 配置:
export http_proxy=http://127.0.0.1:8118
export https_proxy=http://127.0.0.1:8118
// git代理,我没有使用
git config --global http.proxy 'socks5://127.0.0.1:1080'
git config --global https.proxy 'socks5://127.0.0.1:1080'
启动 privoxy 转换 socks5 为 http proxy:
privoxy --no-daemon /usr/local/etc/privoxy/config
Cronet的源码位于 src/components/cronet
目录,官方编译流程可参考Cronet build instructions,编译环境要求:
$ ./components/cronet/tools/cr_cronet.py gn --out_dir=out/Cronet # 生成 ninja 文件
如果主机是linux,build的是Android的库。如果主机是MacOS,build的是ios库。以下命令在Mac上会生成 cronet 静态库,目录 obj/components/cronet/ios/libcronet*.a
gn gen out/Cronet
输入 ninja 文件执行编译,必须指定为 cronet_package
$ ninja -C out/Cronet cronet_package
这个命令会编译 cronet 模块,及其依赖的所有模块,包括base,crypto,boringssl,protobuf,url等。编译Cronet库,最终文件可以在out/Cronet/cornet
中寻找。
iOS 库:
Android 库:
C++层的日志可以通过 adb logcat
输出. 但是默认只显示 FATAL 级别的日志。如果想要更改日志输出级别,可以通过以下命令打开chromium日志输出:
$ adb shell setprop log.tag.CronetUrlRequestContext VERBOSE
$ adb shell setprop log.tag.CronetUrlRequestContext DEBUG
$ adb shell setprop log.tag.CronetUrlRequestContext NONE
NetLog 是 Chromium 网络模块的日志:NetLog: Chrome’s network logging system。可以使用下面两行代码操作 dump 出 chromium 网络模块的日志:
CronetEngine.startNetLogToFile()
CronetEngine.stopNetLog()
Chromium网络模块的日志输出内容是 JSON 格式的,所以需要主动调用 stopNetLog()
方法保证 JSON日志的完整性。
导出的log文件可以使用 https://netlog-viewer.appspot.com/#import 分析。如果打不开,可以使用 Chromium NetLog dump viewer 这个Chrome扩展程序。
参考 GN Quick Start guide 和 GN Language and Operation,建议大家先了解下target的概念,因为gn命令操作的基本上都是target。
// 列出指定构建目录下所有的targets
$ gn ls out/Default
// 查看当前环境的配置参数
$ gn args --list out/Default
// 显示关于一个给定target或config的信息。
// usage: gn desc
$ gn desc out/Default net
// 查找两个taregets之间的依赖路径
$ gn path out/Default //base //net --all
// 查找反向的依赖(也就是依赖此target的其他targets)
$ gn refs out/Default/ //net
// 检查头文件依赖的有效性
$ gn check out/Default/ //net
[外链图片转存失败(img-Oj5Ub8tT-1564461659657)(/gallery/android_commoncronet-lifecycle.svg)]
$ ninja -help
usage: ninja [options] [targets...]
if targets are unspecified, builds the 'default' target (see manual).
options:
--version print ninja version ("1.8.2")
-C DIR change to DIR before doing anything else
-f FILE specify input build file [default=build.ninja]
-j N run N jobs in parallel [default=6, derived from CPUs available]
-k N keep going until N jobs fail [default=1]
-l N do not start new jobs if the load average is greater than N
-n dry run (don't run commands but act like they succeeded)
-v show all command lines while building
-d MODE enable debugging (use -d list to list modes)
-t TOOL run a subtool (use -t list to list subtools)
terminates toplevel options; further flags are passed to the tool
-w FLAG adjust warnings (use -w list to list warnings)