
[Note]ChromiumOS | 从启动Chrome到进入Out of Box Experience
CrOS要做定制,其中第一个任务就是需要定制登录,有了自己的凭证才能用自己的服务。最容易追踪的就是oobe的过程。
这篇并不是讲解性的内容,只是个人阅读代码的记录。幕布:https://mubu.com/app/edit/home/iyQPBdWUie
Chrome启动
ChromeMain
ChromeOS启动以后图形界面全部由Chrome完成,入口和Linux桌面Chrome入口都在chrome\app\chrome_exe_main_aura.cc
,main函数直接启动ChromeMain,ChromeMain在同目录的chrome_main.cc
中定义,也是一个比较简单的函数。
主要是解析了命令行参数
params.argc = argc;
params.argv = argv;
base::CommandLine::Init(params.argc, params.argv);
如果是headless chromium那就直接返回headless::HeadlessShellMain(params)
,否则用content::ContentMain(params)
#if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_MAC) || \
defined(OS_WIN)
if (command_line->HasSwitch(switches::kHeadless)) {
return headless::HeadlessShellMain(params);
}
#endif // defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_MAC) ||
// defined(OS_WIN)
int rv = content::ContentMain(params);
content::ContentMain && RunContentProcess && ContentMainRunnerImpl::Run
ContentMain实际上是启动了RunContentProcess和ContentMainRunnerImpl的一个实例的Run函数。
RunContentProcess
大致来说还是解析命令行,然后处理fd啊、设置进程标题啊、设置信号啊、启动子进程啊这些事情。比较长,不贴代码凑字数了。
ContentMainRunnerImpl::Run && ContentMainRunnerImpl::RunBrowser
经过解析命令行,各个进程都知道了自己的职责。下来就是根据需求加载库,准备执行浏览器的逻辑。
大部分的逻辑都是配置各种各样的服务,创建消息循环,加载Locale,创建线程池。
完成这些以后就开始运行BrowserMain的部分了。
RunBrowserProcessMain && BrowserMain
类似于ContentMain,RunBrowserProcessMain也是代理到了BrowserMain,BrowserMain。BrowserMain则是创建了一个BrowserMainRunnerImpl,然后执行这个Runner。
BrowserMainRunnerImpl && BrowserMainRunnerImpl::Run
BrowserMainRunner没啥好说的,就是初始化然后启动MainLoop的过程。
但是在BrowserMainRunnerImpl::Init中,有一个BrowserMainParts:
void BrowserMainLoop::Init() {
TRACE_EVENT0("startup", "BrowserMainLoop::Init");
// |startup_data| is optional. If set, the thread owned by the data
// will be registered as BrowserThread::IO in CreateThreads() instead of
// creating a brand new thread.
if (parameters_.startup_data) {
StartupDataImpl* startup_data =
static_cast<StartupDataImpl*>(parameters_.startup_data);
// This is always invoked before |io_thread_| is initialized (i.e. never
// resets it).
io_thread_ = std::move(startup_data->io_thread);
mojo_ipc_support_ = std::move(startup_data->mojo_ipc_support);
}
parts_ = GetContentClient()->browser()->CreateBrowserMainParts(parameters_);
}
而CreateBrowserMainParts就是注册Browser要用的各种类的函数。具体的实现在 https://source.chromium.org/chromium/chromium/src/+/master:chrome/browser/chrome_content_browser_client.cc?q=CreateBrowserMainParts&ss=chromium&start=11
不同的目标会加入不同的parts,也就会有不同的视图,会有不同的视图入口。
ChromeOS中使用到了一个ChromeBrowserMainPartsChromeos
和ChromeBrowserMainExtraPartsAsh
。
其中ChromeBrowserMainPartsChromeos
在登陆这一方面为我们做的最重要的几个事情是:
- 启动并初始化SessionManager
- 初始化UserManager 而ChromeBrowserMainExtraPartsAsh主要是提供了Ash窗口管理器
最终SessionManager在 初始化 时,执行StartLoginOOBESession,在其中执行ShowLoginWizard(OobeScreen::SCREEN_UNKNOWN)。如果是完成了OOBE流程且有用户存在时,执行LoginDisplayHostMojo的StartSigninScreen,否则执行LoginDisplayHostWebUI的StartWizard,由WizardController控制进入本地保存的OOBE流程所在Screen或者WelcomeScreen。