以下内容可以参考demo_shell
的相关代码。
浏览器的启动流程可以简单分为以下几个阶段:
- 初始化Content模块;
- 初始化Browser进程;
- 创建GPU进程;
- 创建UI;
- 创建Render进程;
content初始化相关类图见: https://drive.google.com/file/d/1pzPrpgA26QrBxfHBlqtMbQ7ecJ6vXVsv/view?usp=sharing
content 通过被 services 模块启动。
content实现了services 模块提供的接口,并且在 content::ContentMain() 中启动(services模块提供的) service_manager::Main() ,在这个函数中进行一些通用的初始化工作,最后(将content作为services的embedder)启动由content实现的RunEmbedderProcess()方法,至此servcies模块将控制权完全转移到content模块的ContentMainRunner。
ContentMainRunner会启动ServiceManager,最后通过调用BrowserMain()将控制权转移到browser子模块。
BrowserMain()通过BrowserMainRunner继续启动,BrowserMainRunner包装了BrowserMainLoop,BrowserMainLoop的主要功能包括:
- 调用BrowserMainParts,以便允许用户的逻辑被执行;
- 调用content::BrowserStartupComplete(),以便通知Android初始化完成;
- 初始化主线程;
- 创建IO线程;
- 初始化Mojo;
- 初始化音视频/麦克风/触摸屏等设备;
- 初始化WebRTC;
- 初始化剪切板相关服务;
- 根据需求启动GPU进程;
- 启动主线程的消息循环;
BrowserMainParts作为Browser初始化的末端,用户在这里进行扩展,插入创建UI的逻辑。
#0 content/public/browser/browser_main_parts.cc:*()
#1 content/browser/browser_main_loop.cc:*()
#2 content/browser/browser_main_runner_impl.cc:*()
#3 content/browser/browser_main.cc:43:BrowserMain()
#4 content/app/content_main_runner_impl.cc529:RunBrowserProcessMain()
#5 content/app/content_main_runner_impl.cc:978:RunServiceManager()
#6 content/app/content_main_runner_impl.cc:878:Run()
#7 content/app/content_service_manager_main_delegate.cc:52:RunEmbedderProcess()
综上,Browser进程的初始化流程如下: content::ContentMain()->service_manager::Main()->SerivceManagerMainDelegate->ContentMainRunner->content::BrowserMain()->BrowserMainRunner->BrowserMainLoop->BrowserMainParts->(创建UI)
TODO
Browser初始化完成之后,会在BrowserMainParts中创建UI。
注意:并不是一定要在这里创建UI,因为创建UI是一个相对独立的过程,可以放在任何业务觉得合适的时机,比如放在用户打开某一个网页的时候再创建。
创建UI可以分为以下几步:
- 创建Native窗口;
- 创建WebContents,并将WebContents和Native窗口关联;
初始化OutputSurface
ContentViewRenderView 用来显示网页内容,它内部维护了一个SurfaceView/TextureView,并且将他们的Surface传递到Native层,Native层使用它们创建OutputSurface,并且在该OutputSurface上绘制网页内容。
TODO
Render进程并不会一开始就创建,而是在要打开某一个网页的时候才创建。
Render进程的启动流程如下: WebContents->NavigationController->NavigationRequest->RenderFrameHostManager->SiteInstance->RenderProcessHost::Init()->ChildProcessLauncher
由于RenderProcess是按需启动的,因此它的启动流程比较复杂。
TODO