Chromium源码编译和初步的代码阅读

起源

笔者有使用快捷键的习惯,相信不少人也都有在不同软件上定制 HotKey 的需求。然而 Chrome 自带的快捷键有些是不能改的,当使用 Chrome 连接远程桌面开发调试软件时,F1 ~ F12 功能键中有相当多是无法正常使用的。

  • 有些能通过 Chrome 脚本插件(如 tampermonkey)截断按键的捕获来解决冲突,有些则处理不了————例如 F11 这种浏览器标准中所要求的快捷键,优先级是很高的,无法从 js 的层面进行处理。
  • 当然了,第三方改键软件也不失为一种简单方便的 Workaround,但会影响到其他软件,终究不是那么的优雅。

因此打算把 Chromium 源码下载下来,直接修改快捷键的处理逻辑,将不需要的快捷键屏蔽掉。

代码下载与编译

Chromium 的下载最重要的就是 官方文档。由于国内特殊的网络环境,一些额外工作也是必不可少,贴一些我在解决问题的过程中搜到的感觉很有用的文档:

另外,设置 --no-history 也是很重要的。一开始没有设置,下载了 10G+ 的文件都才 60%,实在太慢。设置以后直接不到 1G 搞定。
此处记录一个小坑,在 fetch chromium --no-history 的执行上报错,提示 --no-history 参数错误,以为是命令行环境错误,一查官方文档提醒使用 cmd,我使用的就是 cmd,没办法只能去改脚本了,修改 depot_tools/fetch.py

def handle_args(argv):
  """Gets the config name from the command line arguments."""
  if len(argv) <= 1:
    usage('Must specify a config.')
  if argv[1] in ('-h', '--help', 'help'):
    usage()

  dry_run = False
  nohooks = False
  no_history = True        // 修改此处
  force = False
  while len(argv) >= 2:
    arg = argv[1]
    if not arg.startswith('-'):
      break
    argv.pop(1)
    if arg in ('-n', '--dry-run'):
      dry_run = True
    elif arg == '--nohooks':
      nohooks = True
    elif arg == '--no-history':
      no_history = True
    elif arg == '--force':
      force = True
    else:
      usage('Invalid option %s.' % arg)

代码下载完成后就是漫长的编译了: autoninja -C outDefault chrome
i5 7500的 CPU,16g 内存,默认开启 6 个进程,总耗时约 6 个小时。

修改代码

首先还是官方文档,大概扫了一遍,对主要的几个工程有一定的了解,其他的先暂时不管,毕竟好几千个工程,估计代码能看好几年... 全看是不现实了,直指目标,搜索关键词 "F11" 看一下,直接出来几百个搜索结果,而且文件太多了,搜索一直停不下来。将搜索停掉,忽略 ".html", ".js", ".xtb", ".inc", "*unittest.cc" 等可能与主程序逻辑不相关的搜索结果,从文件名开始扫视,fullscreen_control_host.cc 进入眼帘,打开该文件及其头文件,原来是全屏状态下显示退出的 "X" 图标。

继续找,搜索了若干相似的关键词,都没有想要的结果,好吧看来找捷径失败,滚回去乖乖看文档。
Life of a "mouse click" message: 演示了鼠标事件从 browser 到 renderer 的流程。emm,貌似 mouse 事件跟 keyboard 事件处理流程是类似的,这个没准可行!

  • 找到关键类 RenderWidgetHostViewWin,去代码中搜一搜,竟然没有,难道这个文件没有被 VS 收录?先去 Google 一下 RenderWidgetHostViewWin site:chromium.googlesource.com,得到结果 render_widget_host_view_win.h,这个文件貌似在最新版本没有了。
  • 既然官方文档没有及时更新,那就换个思路,从功能的名称来搜索。"F11" 对应的是全屏开关,果然,通过 "fullscreen" 关键词找到了 fullscreen_control.cc,其中有两个相关的方法:
void FullscreenController::ExitFullscreenModeInternal();
void FullscreenController::ExitFullscreenModeForTab(WebContents* web_contents);

根据之前文档中的描述,Tab-initiated 是由 Flash 或 Api 调用产生的全屏,那剩下的只有 ExitFullscreenModeInternal,进去加断点,在按 "F11" 退出全屏状态时成功触发断点。

找到切入点后,阅读上下文的代码就不会如无头苍蝇一般了。

修改代码,编译,运行,测试快捷键,如预期被修改成功!(此处还是要吐槽一下 chromium 的编译,哪怕只改了一个模块,增量编译也要接近 10 分钟,吃掉 5g 的内存)

暂告段落

一番折腾,周末也快过去了...但是在 Chromium 源码的阅读过程中,还是能发现不少设计模式的影子。作为一款大型桌面软件,它对软件模块的分层也值得学习,特别是插件的设计,还有 web 页面的渲染机制是什么样的(例如之前做 WPF 表格控件的时候,无法做到灵活的样式,而 HTML 中 <table> 能轻松做出合并单元格的样式),以后有时间再进一步研究。


update: 找到个文档:Chromium中文文档,对入门还是有些帮助的

原文地址:https://www.cnblogs.com/cdyang/p/chromium-compile-and-firstexperience.html