本篇笔记跟踪记录了Chromium的启动过程,主要关注 Browser
进程和 Renderer
进程。根据 Chromium
项目的分层设计,我们把 Content API
称作为 Content
层,而把调用 Content API
实现浏览器程序的部分称作为 Embedder
层。在项目中,Embedder
层有 chrome
、content_shell
等多种实现。
1、main() 函数
Chromium的main函数在 chrome\app\chrome_exe_main_win.cc
,具体如下:
// chrome\app\chrome_exe_main_win.cc
#if !defined(WIN_CONSOLE_APP) int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE prev, wchar_t*, int) { #else int main() { HINSTANCE instance = GetModuleHandle(nullptr); #endif install_static::InitializeFromPrimaryModule(); SignalInitializeCrashReporting();
......
// Load and launch the chrome dll. *Everything* happens inside. VLOG(1) << "About to load main DLL."; MainDllLoader* loader = MakeMainDllLoader(); int rc = loader->Launch(instance, exe_entry_point_ticks); loader->RelaunchChromeBrowserWithNewCommandLineIfNeeded(); delete loader; return rc; }
|
在main函数中,最重要的一步,就是 int rc = loader->Launch(instance, exe_entry_point_ticks);
载入 chrome.dll运行
。
2、载入 chrome.dll
在这里首先调用了 MakeMainDllLoader()
函数,这是一个静态函数,在chrome\app\main_dll_loader.cc
中,内容如下:
// chrome\app\main_dll_loader.cc
MainDllLoader* MakeMainDllLoader() { #if defined(GOOGLE_CHROME_BUILD) return new ChromeDllLoader(); #else return new ChromiumDllLoader(); #endif }
|
函数创建并返回一个 ChromiumDllLoader
,紧接着再调用它的 Launch
函数,内容如下:
// chrome\app\main_dll_loader.cc
int MainDllLoader::Launch(HINSTANCE instance, base::TimeTicks exe_entry_point_ticks) { const base::CommandLine& cmd_line = *base::CommandLine::ForCurrentProcess(); process_type_ = cmd_line.GetSwitchValueASCII(switches::kProcessType);
......
dll_ = Load(&file); if (!dll_) return chrome::RESULT_CODE_MISSING_DATA;
OnBeforeLaunch(cmd_line, process_type_, file); DLL_MAIN chrome_main = reinterpret_cast<DLL_MAIN>(::GetProcAddress(dll_, "ChromeMain")); int rc = chrome_main(instance, &sandbox_info, exe_entry_point_ticks.ToInternalValue()); OnBeforeExit(file); return rc; }
|
这里完成了 chrome.dll
的载入,并且执行里面的 ChromeMain
函数。
3、ChromeMain() 函数
ChromeMain
函数负责 Embedder
层的实现类创建,并传递给 Content
层,定义在 chrome\app\chrome_main.cc
中,内容如下:
// chrome\app\chrome_main.cc
extern "C" { DLLEXPORT int __cdecl ChromeMain(HINSTANCE instance, sandbox::SandboxInterfaceInfo* sandbox_info, int64_t exe_entry_point_ticks); }
......
#if defined(OS_WIN) DLLEXPORT int __cdecl ChromeMain(HINSTANCE instance, sandbox::SandboxInterfaceInfo* sandbox_info, int64_t exe_entry_point_ticks) { #elif defined(OS_POSIX) int ChromeMain(int argc, const char** argv) { int64_t exe_entry_point_ticks = 0; #endif
#if defined(OS_WIN) install_static::InitializeFromPrimaryModule(); #endif
ChromeMainDelegate chrome_main_delegate( base::TimeTicks::FromInternalValue(exe_entry_point_ticks)); content::ContentMainParams params(&chrome_main_delegate);
......
int rv = content::ContentMain(params);
return rv; }
|
在ChromeMain中,最终执行到了 content::ContentMain
这个函数。
4、content::ContentMain() 函数
代码执行到这里,进入了 Content
层,并且传入参数 content::ContentMainParams
类型的参数 params
,它是由 Embedder
层传递过来的重要参数,里面包含了 Embedder
层的具体实现信息,此结构体在 content\public\app\content_main.h
中定义如下:
// content\public\app\content_main.h
struct ContentMainParams { explicit ContentMainParams(ContentMainDelegate* delegate) : delegate(delegate) {}
ContentMainDelegate* delegate;
......
|
其中有一个重要的成员变量 delegate
,其类型为 content::ContentMainDelegate
,它在 content\public\app\content_main_delegate.cc
中定义如下:
// content\public\app\content_main_delegate.cc
class CONTENT_EXPORT ContentMainDelegate { public: virtual ~ContentMainDelegate() {}
virtual bool BasicStartupComplete(int* exit_code); virtual void PreSandboxStartup() {} virtual void SandboxInitialized(const std::string& process_type) {} virtual int RunProcess( const std::string& process_type, const MainFunctionParams& main_function_params); virtual void ProcessExiting(const std::string& process_type) {}
......
virtual void PreCreateMainMessageLoop() {}
......
protected: friend class ContentClientInitializer;
virtual ContentBrowserClient* CreateContentBrowserClient(); virtual ContentGpuClient* CreateContentGpuClient(); virtual ContentRendererClient* CreateContentRendererClient(); virtual ContentUtilityClient* CreateContentUtilityClient(); };
|
可以看到,这里定义了一系列与启动相关的操作,并且通过几个 CreateXXX
的函数,获取 ContentBrowserClient
、ContentRendererClient
等接口具体的实现,这也是 content API
的巧妙设计,通过这种方式,将浏览器的实现放入了 content
中。
继续往下看,content::ContentMain()
中调用了 content\app\content_main.cc
中的 service_manager::Main()
:
// content\app\content_main.cc
int ContentMain(const ContentMainParams& params) { ContentServiceManagerMainDelegate delegate(params); service_manager::MainParams main_params(&delegate); #if !defined(OS_WIN) && !defined(OS_ANDROID) main_params.argc = params.argc; main_params.argv = params.argv; #endif return service_manager::Main(main_params); }
|
在这里,使用一个 content::ContentServiceManagerMainDelegate
对象来构建了 main_params
,并传入了 service_manager::Main()
。
5、service_manager::Main 函数
service_manager::Main
函数位于 services\service_manager\embedder\main.cc
,接收一个 MainParams
类型的参数,具体如下:
// services\service_manager\embedder\main.cc
int Main(const MainParams& params) { MainDelegate* delegate = params.delegate;
......
ProcessType process_type = delegate->OverrideProcessType();
...... // A flag to indicate whether Main() has been called before. On Android, we // may re-run Main() without restarting the browser process. This flag // prevents initializing things more than once. static bool is_initialized = false; #if !defined(OS_ANDROID) DCHECK(!is_initialized); #endif if (!is_initialized) { is_initialized = true;
......
#if defined(OS_WIN) base::win::RegisterInvalidParamHandler(); ui::win::CreateATLModuleIfNeeded(); #endif // defined(OS_WIN)
......
base::CommandLine::Init(argc, argv);
......
const auto& command_line = *base::CommandLine::ForCurrentProcess();
#if defined(OS_WIN) base::win::SetupCRT(command_line); #endif
MainDelegate::InitializeParams init_params;
...... mojo::core::Init(mojo_config);
......
exit_code = delegate->Initialize(init_params);
......
}
const auto& command_line = *base::CommandLine::ForCurrentProcess(); if (process_type == ProcessType::kDefault) { std::string type_switch = command_line.GetSwitchValueASCII(switches::kProcessType); if (type_switch == switches::kProcessTypeServiceManager) { process_type = ProcessType::kServiceManager; } else if (type_switch == switches::kProcessTypeService) { process_type = ProcessType::kService; } else { process_type = ProcessType::kEmbedder; } } switch (process_type) { case ProcessType::kDefault: NOTREACHED(); break;
case ProcessType::kServiceManager: exit_code = RunServiceManager(delegate); break;
case ProcessType::kService: CommonSubprocessInit(); exit_code = RunService(delegate); break;
case ProcessType::kEmbedder: if (delegate->IsEmbedderSubprocess()) CommonSubprocessInit(); exit_code = delegate->RunEmbedderProcess(); break; }
......
if (process_type == ProcessType::kEmbedder) delegate->ShutDownEmbedderProcess();
return exit_code; }
|
这里截取的代码比较长,也非常重要,我们主要关注这四个部分:
-
- 根据传入的
delegate
和 command_line
决定进程的类型 - 运行环境的初始化,比如
CreateATLModuleIfNeeded
,SetupCRT
并用 is_initialized
来防止重复执行 - 通过传入的
delegate
进行程序的初始化操作,delegate->Initialize(init_params)
- 根据进程类型启动相应的工作
-
这里的 delegate
类型为 service_manager::MainDelegate*
,是在 services/service_manager/embedder/main_delegate.h
中定义的抽象类,在这里我们主要关注它的 Initialize
、RunEmbedderProcess
和 ShutDownEmbedderProcess
,其中 Initialize
为被声明为纯虚函数,RunEmbedderProcess
和 ShutDownEmbedderProcess
又是什么都不做的,代码如下:
// services/service_manager/embedder/main_delegate.h
class COMPONENT_EXPORT(SERVICE_MANAGER_EMBEDDER) MainDelegate { public: // Perform early process initialization. Returns -1 if successful, or the exit // code with which the process should be terminated due to initialization // failure. virtual int Initialize(const InitializeParams& params) = 0;
......
// Runs the embedder's own main process logic. Called exactly once after a // successful call to Initialize(), and only if the Service Manager core does // not know what to do otherwise -- i.e., if it is not starting a new Service // Manager instance or launching an embedded service. // // Returns the exit code to use when terminating the process after // RunEmbedderProcess() (and then ShutDown()) completes. virtual int RunEmbedderProcess();
......
// Called just before process exit if RunEmbedderProcess() was called. virtual void ShutDownEmbedderProcess();
|
// services/service_manager/embedder/main_delegate.cc
int MainDelegate::RunEmbedderProcess() { return 0; }
...
void MainDelegate::ShutDownEmbedderProcess() {}
|
回到 service_manager::Main()
,我们看到第一句 MainDelegate* delegate = params.delegate;
中的 params.delegate
就是前面在 content::ContentMain
中构建 main_params
所使用的 content::ContentServiceManagerMainDelegate
对象,因此,上述的三个函数 Initialize
、RunEmbedderProcess
、ShutDownEmbedderProcess
是由 ContentServiceManagerMainDelegate
来最终实现的,来看代码:
// content\app\content_service_manager_main_delegate.cc
int ContentServiceManagerMainDelegate::Initialize( const InitializeParams& params) {
......
return content_main_runner_->Initialize(content_main_params_); }
......
int ContentServiceManagerMainDelegate::RunEmbedderProcess() { return content_main_runner_->Run(start_service_manager_only_); }
......
void ContentServiceManagerMainDelegate::ShutDownEmbedderProcess() { #if !defined(OS_ANDROID) content_main_runner_->Shutdown(); #endif }
|
在这三个函数的定义中,都使用了 content_main_runner_
这个成员变量来具体执行,它的定义为 std::unique_ptr<ContentMainRunnerImpl>
。
6、整个程序的Runner,content::ContentMainRunnerImpl
这个 content::ContentMainRunnerImpl
是 content::ContentMainRunner
接口的一个实现,先来看接口的声明:
// content\app\content_main_runner_impl.h
class CONTENT_EXPORT ContentMainRunner { public: virtual ~ContentMainRunner() {}
// Create a new ContentMainRunner object. static ContentMainRunner* Create();
// Initialize all necessary content state. virtual int Initialize(const ContentMainParams& params) = 0;
// Perform the default run logic. virtual int Run(bool start_service_manager_only) = 0;
// Shut down the content state. virtual void Shutdown() = 0; };
|
再来看实现类的代码:
// content\app\content_main_runner_impl.h
class ContentMainRunnerImpl : public ContentMainRunner { public: static ContentMainRunnerImpl* Create();
ContentMainRunnerImpl(); ~ContentMainRunnerImpl() override;
int TerminateForFatalInitializationError();
// ContentMainRunner: int Initialize(const ContentMainParams& params) override; int Run(bool start_service_manager_only) override; void Shutdown() override;
......
}
|
7、ContentMainRunner::Initialize() 函数
先来看 Initialize
函数:
// content\app\content_main_runner_impl.cc
int ContentMainRunnerImpl::Initialize(const ContentMainParams& params) { ui_task_ = params.ui_task; created_main_parts_closure_ = params.created_main_parts_closure;
#if defined(OS_WIN) sandbox_info_ = *params.sandbox_info; #else // !OS_WIN
......
is_initialized_ = true; delegate_ = params.delegate;
......
int exit_code = 0; if (delegate_->BasicStartupComplete(&exit_code)) return exit_code; completed_basic_startup_ = true;
......
delegate_->PreSandboxStartup(); #if defined(OS_WIN) if (!InitializeSandbox( service_manager::SandboxTypeFromCommandLine(command_line), params.sandbox_info)) return TerminateForFatalInitializationError(); #elif defined(OS_MACOSX)
......
#endif
delegate_->SandboxInitialized(process_type);
......
// Return -1 to indicate no early termination. return -1; }
|
大致看一下,在这个 Initialize
中,主要是根据 command_line
启动了相应的 sandbox service
,并在启动前后都触发了 delegate_->PreSandboxStartup()
和 delegate_->SandboxInitialized(process_type)
,这个 delegate_
来自于传入的 content::ContentMainParams
结构体,这个结构体是在 chrome_main.cc
中调用 content::ContentMain(params)
时所创建,所以这个 delegate_
正是前面所提到的巧妙设计中,继承自 content::ContentMainDelegate
的 ChromeMainDelegate
对象,通过这一系列的调用,content
层就把创建 sandbox service
前后的事件触发了出来,具体实现者只要在 ChromeMainDelegate
中填充这两个时间点要做的事即可。
8、进程入口,ContentMainRunner::Run() 函数
再来看 Run
函数:
// // content\app\content_main_runner_impl.cc
int ContentMainRunnerImpl::Run(bool start_service_manager_only) {
......
const base::CommandLine& command_line = *base::CommandLine::ForCurrentProcess(); std::string process_type = command_line.GetSwitchValueASCII(switches::kProcessType);
......
MainFunctionParams main_params(command_line); main_params.ui_task = ui_task_; main_params.created_main_parts_closure = created_main_parts_closure_;
......
if (process_type.empty()) return RunServiceManager(main_params, start_service_manager_only);
return RunOtherNamedProcessTypeMain(process_type, main_params, delegate_); }
|
此处先判断 process_type
是否为空,为空则代表当前执行的是默认进程(一般情况下为 Browser
进程),则调用 RunServiceManager()
,否则调用 RunOtherNamedProcessTypeMain
根据process_type
来执行相应的进程。先来看 RunServiceManager
:
// content\app\content_main_runner_impl.cc
int ContentMainRunnerImpl::RunServiceManager(MainFunctionParams& main_params, bool start_service_manager_only) {
......
if (!service_manager_context_) {
......
delegate_->PreCreateMainMessageLoop();
......
delegate_->PostEarlyInitialization(main_params.ui_task != nullptr);
......
}
if (should_start_service_manager_only) return -1;
is_browser_main_loop_started_ = true; startup_data_ = std::make_unique<StartupDataImpl>(); startup_data_->thread = std::move(service_manager_thread_); startup_data_->service_manager_context = service_manager_context_.get(); main_params.startup_data = startup_data_.get(); return RunBrowserProcessMain(main_params, delegate_); }
|
同样,这里通过 delegate_
做了一些操作之后,最后调用了 RunBrowserProcessMain()
函数,内容如下:
// content\app\content_main_runner_impl.cc
int RunBrowserProcessMain(const MainFunctionParams& main_function_params, ContentMainDelegate* delegate) { int exit_code = delegate->RunProcess("", main_function_params); #if defined(OS_ANDROID) // In Android's browser process, the negative exit code doesn't mean the // default behavior should be used as the UI message loop is managed by // the Java and the browser process's default behavior is always // overridden. return exit_code; #else if (exit_code >= 0) return exit_code; return BrowserMain(main_function_params); #endif }
|
非常简单明了,首先通过 delegate->RunProcess
把执行默认进程的优先权交由 Embedder
层,如果 Embedder
层成功执行了进程并最终返回了成功标志(exit_code >= 0
),那么就退出函数;如果 Embedder
层对默认进程没有定义,就继续执行 content::BrowserMain
,由此,Browser
进程开始执行。
再来看 RunOtherNamedProcessTypeMain
函数:
// content\app\content_main_runner_impl.cc
int RunOtherNamedProcessTypeMain(const std::string& process_type, const MainFunctionParams& main_function_params, ContentMainDelegate* delegate) { static const MainFunction kMainFunctions[] = {
......
{switches::kUtilityProcess, UtilityMain}, {switches::kRendererProcess, RendererMain}, {switches::kGpuProcess, GpuMain}, };
for (size_t i = 0; i < base::size(kMainFunctions); ++i) { if (process_type == kMainFunctions[i].name) { int exit_code = delegate->RunProcess(process_type, main_function_params); if (exit_code >= 0) return exit_code; return kMainFunctions[i].function(main_function_params); } }
......
// If it's a process we don't know about, the embedder should know. return delegate->RunProcess(process_type, main_function_params); }
|
先建立了一个进程类型和入口函数指针的对应数组,再根据进程类型去具体执行,执行的过程与 Browser
进程一样,先通过 delegate->RunProcess
交由 Embedder
层处理,如果未处理再调用默认的进程入口函数,可以看到分别提供了 UtilityMain
、RendererMain
、GpuMain
这三个进程的入口,其中 RendererMain
则是我们关注的 Renderer
进程的入口函数,Renderer
进程从此处开始执行。最后一句,如果进程类型不在以上范围内,则交由 Embedder
去处理。
9、程序结束
void ContentMainRunnerImpl::Shutdown() { DCHECK(is_initialized_); DCHECK(!is_shutdown_);
if (completed_basic_startup_) { const base::CommandLine& command_line = *base::CommandLine::ForCurrentProcess(); std::string process_type = command_line.GetSwitchValueASCII(switches::kProcessType);
delegate_->ProcessExiting(process_type); }
#if !defined(CHROME_MULTIPLE_DLL_CHILD) // The BrowserTaskExecutor needs to be destroyed before |exit_manager_|. BrowserTaskExecutor::Shutdown(); #endif // !defined(CHROME_MULTIPLE_DLL_CHILD)
#if defined(OS_WIN) #ifdef _CRTDBG_MAP_ALLOC _CrtDumpMemoryLeaks(); #endif // _CRTDBG_MAP_ALLOC #endif // OS_WIN
exit_manager_.reset(nullptr);
delegate_ = nullptr; is_shutdown_ = true; }
|
首先通过 delegate_->ProcessExiting(process_type)
通知 Embedder
层处理,然后做了一些善后释放的工作,最后将 is_shutdown_
标记置为 true
。
10、总结
前面分析了这么多,其实结合类图来看一下还是很简单明了的,主要起到作用的就是图中标红的三个,service_manager::Main
通过 content::ContentServiceManagerMainDelegate
的实例调用了 content::ContentMainRunnerImpl
实例中的 Initialize()
、Run()
、Shutdown()
函数,而在这个Runner中,又通过 content::ContentMainDelegate
接口指针调用到了由 Embedder
层创建的 ChromeMainDelegate
实例中的函数,由此完成了程序的启动以及 Content
层对 Embedder
的交互。