Chromium架构之启动

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

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阶段的工作:

  1. Initialize,浏览器初始化工作
  2. Run,运行浏览器
  3. Shutdown,浏览器关闭后的逻辑

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

Initialize

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

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

Run

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

Shutdown

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

ChromeMainDelegate

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

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

  • BasicStartupComplete。基本的初始化工作已经完成。现在可以安全的创建一些单例和检查命令行工作。
  • PreSandboxStartup。sandbox之前的所有初始化逻辑。这里初始化了User Data目录,PDF模块。
  • SandboxInitialized。sandbox逻辑已经运行了。
  • RunProcess。决定是否启动其他进程
  • ProcessExiting。进程退出时回调。

Client

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

  • ContentBrowserClient,Chrome的实现逻辑ChromeContentBrowserClient
  • ContentGpuClient,Chrome的实现逻辑ChromeContentGpuClient
  • ContentRendererClient,Chrome的实现逻辑ChromeContentRendererClient
  • ContentUtilityClient,Chrome的实现逻辑ChromeContentUtilityClient

BrowserMain

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,类图关系如下所示:

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

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

  • EarlyInitialization阶段,在浏览器启动前需要尽快做的事情可以放到这里面。
  • MainMessageLoopStart,浏览器启动消息循环阶段。
  • RunMainMessageLoopParts,运行浏览器消息循环阶段。

发表评论

电子邮件地址不会被公开。 必填项已用*标注