Chromium 命名規範

Chromium 代碼中的文件數不勝數,讀懂文件名可以幫我們快速定位某個文件的用途。好的文件命名方式應該是自解釋的,能夠實現 “望文生義” 的效果。不過 Chromium 只對代碼風格做了指引,並未對名稱的遣詞做統一規定,所以文件的命名更多是所在目錄的約定俗成,受 Owner 的文化背景影響,比如有 Mac 或 iOS 開發背景的 Owner 更有可能將一個類的回調對象命名爲 Delegate,而非此背景下的開發者則有可能命名爲 Client。

*_{platform}.{ext}

Chromium 代碼支持多個平臺,由於各個平臺有不同的系統 API ,通常需要將這些 API 進行封裝,並只在對應的平臺上進行編譯。 Chromium 在文件名層面區分不同的平臺的方式是命名爲 *_{platform}.{ext} ,例如 ,該文件就只在 android 平臺進行編譯。Chromium 的兩個編譯系統, gyp 原生支持在編譯時過濾非對應平臺的源文件, gn 則需要手動聲明 sources_assignment_filter 才能過濾。

目前 Chromium 常用的的平臺標識符如下:

  • android
  • chromeos
  • freebsd
  • fuchsia
  • ios
  • linux
  • mac
  • openbsd
  • posix
  • win

其中 fuchsia 是 Google 最新開發的操作系統,能夠同時支持 PC 和嵌入式設備。

*_impl.{ext}

Chromium 代碼中隨處可見 *_impl.{ext} 文件,涵義並不完全相同。

cc/ 目錄下的部分 *_impl.{ext} 文件表示該類運行在 impl-side painting 的 impl 線程,比如 cc/trees/layer_tree_host_impl.h。

除此之外的 {clazz}_impl.{ext} 文件基本上都是抽象接口 Clazz 類的具體實現類。

web_*_impl.{ext} 通常表示該類是 WebKit 的平臺實現(PlatformImpl),比如 content/child/web_url_loader_impl.h 即爲 WebKit 的 WebURLLoader 在 Chromium 平臺下的實現。

定義抽象接口類與具體實現 Impl 類的方法做到了接口與實現的分離,保證了接口類的相對穩定,也對上層模塊隱藏了實現細節;同時抽象接口類允許我們實現 Mock 類,方便進行單元測試,特別是考慮到 content/ 目錄下很多類都需要進行 IPC 通信,初始化、建立管道等操作相對於單元測試來說太過於繁瑣。

*_host.{ext}

Host 在 Chromium 代碼中的語義也不盡相同,在 Chromium 代碼中有一類 *_host.{ext} 文件標識了多進程架構下的通信關係,通常總是有一個 {clazz}.{ext} 文件與 {clazz}_host.{ext} 對應,比如 content/public/browser/render_view_host.h 與 content/public/renderer/render_view.h 。

RenderViewHost 與 RenderView 通過 IPC 消息進行通信,很大程度上可以認爲 RenderViewHost 是 RenderView 在 Browser 端的代理(Proxy),幾乎所有 Browser 端對 RenderViewHost 的操作都需要通過 IPC 消息傳給 RenderView 進行實際操作,而 RenderView 也需要通過 IPC 消息傳遞到 RenderViewHost 回調和通知 Browser 端的上層。

以下列出了幾個使用 Host 這種用法的重要的文件:

  • content/browser/frame_host/render_frame_host_impl.h 與 content/renderer/render_frame_impl.h
  • content/browser/renderer_host/render_view_host_impl.h 與 content/renderer/render_view_impl.h
  • content/browser/loader/resource_dispatcher_host_impl.h 與 content/child/resource_dispatcher.h
  • gpu/ipc/client/gpu_channel_host.h 與 gpu/ipc/service/gpu_channel.h

IPC 消息三劍客

IPC 是 Chromium 多進程架構下進程間通信的機制,通過命名管道(Linux 和 OS X 下是 socketpair)在進程間傳遞二進制數據,該二進制數據是由用於進程間通信的數據結構序列化而來,所以在 IPC 消息的接收端還要反序列化回來。

  • *_messages.{ext}

*_messages.{ext} 通過 Chromium 提供的一套 IPC 消息生成宏(參見 ipc_message_macros.h)定義 IPC 消息及其參數。我們只需要聲明 IPC 消息的類型以及參數列表,對複合型的參數聲明其數據結構中需要序列化的字段,上述消息宏會自動幫我們生成 IPC 消息序列化和反序列化的實現。

  • *_traits.{ext}

有些複合型參數,不能簡單的通過序列化和反序列化數據結構中的字段來傳遞數據,而需要做一些額外的操作。 *_traits.{ext} 文件就是用於自定義這類參數的序列化和反序列化實現。

  • *_message_filter.{ext}

IPC 消息的實際 I/O 操作在當前進程的 IO 線程上,監聽處理邏輯(IPC::Listener)運行在當前進程的主線程(Browser 端是 UI 線程,Renderer 端是 Renderer 線程)上, MessageFilter 提供了一個機會可以在 IO 線程上直接攔截 IPC 消息,通常用於將攔截到的 IPC 消息轉發到非主線程。

*.mojom

mojom 是 mojo 的模板文件,在前一篇 《Chromium代碼文化系列之二:目錄結構》中我們提到, mojo 類似於 Android 的 AIDL ,提供了跨語言(C++ / Java / JavaScript)的進程間對象(Object)通信機制, mojom 文件也類似於 aidl 文件,會生成進程間通信對象的抽象接口以及其底層的 IPC 實現。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章