Chromium架构之启动

总结一下Chromium浏览器从wWinMain到浏览器循环开始的这段逻辑。

chromium framework start

wWinMain

Win32程序的入口都是wWinMain,Chromium浏览器也不例外。

初始化Crashpad

一开始就调用SignalInitializeCrashReporting去初始化Crashpad崩溃报告系统。这里会创建一个ChromeCrashReporterClient的对象,用来处理crash相关的逻辑。初始化完成之后就会启动一个crashpad-handler的进程。其他浏览器进程崩溃后,这个crashpad-handler进程就会为它们生成dump。

fast start机制

wWinMain里面会调用AttemptFastNotify函数,这个是Chromium里面的fast start机制,具体可以看看我这篇博客 http://blog.gclxry.com/chromium-fast-start/

MainDllLoader

wWinMain最后会用MainDllLoader去加载浏览器实际逻辑的dll。不同的浏览器进程加载的dll不一样。比如Browser进程加载的是chrome.dll,Renderer进程加载的是chrome_child.dll,Watcher进程加载的是chrome_watcher.dll。

加载好dll之后就会调用dll里面的ChromeMain函数,执行不同的逻辑。

ChromeMain

ChromeMain里面会创建一个很重要的ChromeMainDelegate对象。这个ChromeMainDelegate对象会传递到Content层代码里面,Content代码会回调ChromeMainDelegate一些方法。

另外会设置DumpWithoutCrashing的函数,实际上调用的是chrome_elf.dll里面的DumpProcessWithoutCrash。

最后是调用content::ContentMain,进入Content层的逻辑。

ContentMain

ContentMain的逻辑依然很简单。它创建一个ContentMainRunner去执行3阶段的工作:

每个阶段,会回调ChromeMainDelegate,以便Content层以上的逻辑有机会处理一些事情。

Initialize

这里面会初始化很多东西,比如设置各种崩溃处理场景,比如无效的参数处理、Heap错误处理等等。

这里创建一个AtExitManager的对象,顾名思义,它就是管理浏览器退出的时候做的一些任务。在浏览器运行的时候可以向它注册一些回调任务,在AtExitManager析构的时候运行这些回掉任务。具体用法可以看它的代码注释和代码中其他地方的例子。还会初始化Mojo、ICU、PathProvider、V8、sandbox等等重要设施。

Run

这里面就是开始真正的运行浏览器了。根据不同的浏览器进程类型运行不同的逻辑。比如浏览器主进程运行BrowserMain,渲染进程运行RendererMain等等。RunNamedProcessTypeMain里面具体列举了各种Main类型。

Shutdown

浏览器退出后会运行到这里,它会回调ChromeMainDelegate的ProcessExiting。

ChromeMainDelegate

浏览器从启动到运行每个不同浏览器类型的各自逻辑这个阶段,ChromeMainDelegate是很重要的一个对象,它实现了浏览器每个阶段要做的事情。

ChromeMainDelegate继承自ContentMainDelegate,可以从ContentMainDelegate 的注释看到每个阶段的意思:

Client

所有类型的浏览器进程都有ChromeMainDelegate对象,所以每个不同进程类型的逻辑,就放在Content*Client里面实现,现在大概有以下几种:

BrowserMain

chromium framework start

BrowserMain跟ContentMain类似,逻辑很简单,主要逻辑在BrowserMainRunner里面。

Initialize

在这个函数里面初始化SkGraphics图像库,创建NotificationServiceImpl。NotificationService好像不建议使用了。还有初始化Ole、DirectWrite等等重要的模块。

Initialize里面创建BrowserMainLoop,BrowserMainRunner实际上很多都是调用BrowserMainLoop函数。

Run

调用BrowserMainLoop里面的RunMainMessageLoopParts。其他没什么。

Shutdown

做一些清理的工作,逻辑也很简单。

BrowserMainLoop

BrowserMainLoop是一个重要的对象,可以从上图看出浏览器Browser进程的不同阶段都会调用到它。在BrowserMainLoop里面会创建和初始化很多重要的对象,包含Browser进程里面一些重要线程,具体可以读一读browser_main_loop.cc的源代码。

另外BrowserMainLoop有一个BrowserMainParts成员,BrowserMainLoop会在不同的阶段调用通知到BrowserMainParts的逻辑。

BrowserMainParts

在这个BrowserMainLoop::Init函数里面ChromeContentBrowserClient会创建一个BrowserMainParts。它的实际类型是ChromeBrowserMainPartsWin,继承自ChromeBrowserMainParts。

ChromeBrowserMainParts里面又可以包含其他更多的ChromeBrowserMainExtraParts,类图关系如下所示: chromium framework start

BrowserMainParts机制是为了让我们自定义浏览器的逻辑而不影响它的架构。在不同的平台我们可以实现不同的ChromeBrowserMainParts*,比如Widnows平台就是ChromeBrowserMainPartsWin。对于不同业务的功能,我们可以实现不同的ChromeBrowserMainExtraParts,比如ChromeBrowserMainExtraPartsViews,然后把ChromeBrowserMainExtraParts添加到ChromeBrowserMainParts里面。

可以看browser_main_parts.h里面注释,就知道BrowserMainParts每个阶段的调用函数的意义: