最近抽时间分析了一下chromium的extension机制,总的来说其架构是比较清晰的,但是由于需要与chromium浏览器(或OS)运行时的各个模块交互,实现起来就比较复杂了,主要代码集中分布于如下几个目录中:./extensions/、./chrome/browser/extensions/、./chrome/common/extensions/、./chrome/renderer/extensions/;刚开始入手分析时试图从这几个目录的实现代码中找到分析突破口,走了不少弯路,总是剪不断,理还乱,几个回合下来还是一头雾水,最后尝试从chromium浏览器启动流程上跟下来,结果豁然开朗。接下来总结下extension系统的初始化过程(主要建立起依赖关系图)、extensionservice的创建及初始化、WebStore应用商店app的安装、WebRequest回调的实现这几个模块的分析情况。
首先可以将浏览器主线程的初始化作为extension系统的初始化入口,此处从BrowserMainRunnerImpl::Initialize方法开始进行分析,为便于进行描述,大致可以分为如下两个阶段:
阶段一:预初始化(从BrowserMainRunnerImpl::Initialize到ChromeBrowserMainExtraPartsProfiles::EnsureBrowserContextKeyedServiceFactoriesBuilt),关键流程如图所示:
注释1:在上图中ChromeContentBrowserClient::CreateBrowserMainParts方法中根据具体的运行平台创建对应的ChromeBrowserMainParts实现对象main_parts(此处以基类代替):
ChromeBrowserMainParts* main_parts;
// Construct the Main browser parts based on the OS type.
#if defined(OS_WIN)
main_parts = new ChromeBrowserMainPartsWin(parameters);
#elif defined(OS_MACOSX)
main_parts = new ChromeBrowserMainPartsMac(parameters);
#elif defined(OS_CHROMEOS)
main_parts = new chromeos::ChromeBrowserMainPartsChromeos(parameters);
#elif defined(OS_LINUX)
main_parts = new ChromeBrowserMainPartsLinux(parameters);
#elif defined(OS_ANDROID)
main_parts = new ChromeBrowserMainPartsAndroid(parameters);
#elif defined(OS_POSIX)
main_parts = new ChromeBrowserMainPartsPosix(parameters);
#else
NOTREACHED();
main_parts = new ChromeBrowserMainParts(parameters);
#endif
chrome::AddProfilesExtraParts(main_parts);
在main_parts对象创建之后调用chrome::AddProfilesExtraParts(main_parts);方法创建ChromeBrowserMainExtraPartsProfiles对象,并加入main_parts对象中vector中:
void AddProfilesExtraParts(ChromeBrowserMainParts* main_parts) {
main_parts->AddParts(new ChromeBrowserMainExtraPartsProfiles());
}
void ChromeBrowserMainParts::AddParts(ChromeBrowserMainExtraParts* parts) {
chrome_extra_parts_.push_back(parts);
}
注释2:在BrowserMainLoop::CreateStartupTasks方法中首先创建各种阶段性初始化任务StartupTask加入到任务队列对象startup_task_runner_中,然后通过调用startup_task_runner_->RunAllTasksNow();依次执行各个任务;此处只关注了PreMainMessageLoopRun任务的创建和执行:
StartupTask pre_main_message_loop_run = base::Bind(
&BrowserMainLoop::PreMainMessageLoopRun, base::Unretained(this));
startup_task_runner_->AddTask(pre_main_message_loop_run);
......
startup_task_runner_->RunAllTasksNow();
注释3:在ChromeBrowserMainParts::PreProfileInit方法中会依次调用上面通过AddProfilesExtraParts方法中加入到main_parts对象列表中的ExtraParts对象的PreProfileInit方法:
for (size_t i = 0; i < chrome_extra_parts_.size(); ++i)
chrome_extra_parts_[i]->PreProfileInit();
此处就会调用至这一阶段的目的地:
void ChromeBrowserMainExtraPartsProfiles::PreProfileInit() {
EnsureBrowserContextKeyedServiceFactoriesBuilt();
}
阶段二:extension系统初始化,也是最为复杂和涉及面最广的阶段,主要完成各种注册和出事化工作。入口方法如下:
void ChromeBrowserMainExtraPartsProfiles::EnsureBrowserContextKeyedServiceFactoriesBuilt() {
#if defined(ENABLE_EXTENSIONS)
apps::EnsureBrowserContextKeyedServiceFactoriesBuilt();
extensions::EnsureBrowserContextKeyedServiceFactoriesBuilt();
chrome_extensions::EnsureBrowserContextKeyedServiceFactoriesBuilt();
AppShortcutManagerFactory::GetInstance();
EphemeralAppServiceFactory::GetInstance();
#endif
......
}
首先是三个命名空间的初始化入口函数,实现分别位于./apps/browser_context_keyed_service_factories.cc、 ./chrome/browser/extensions/browser_context_keyed_service_factories.cc、./extensions/browser/browser_context_keyed_service_factories.cc三个文件中,包括后面两个对象,所有涉及到的初始化过程都是创建单例对象并加入到依赖图中,几个主要的基类如下所示:
如下./extensions/browser/browser_context_keyed_service_factories.cc文件的EnsureBrowserContextKeyedServiceFactoriesBuilt方法片段:
void EnsureBrowserContextKeyedServiceFactoriesBuilt() {
......
extensions::AudioAPI::GetFactoryInstance();
extensions::BookmarksAPI::GetFactoryInstance();
extensions::BookmarkManagerPrivateAPI::GetFactoryInstance();
extensions::BluetoothAPI::GetFactoryInstance();
extensions::BluetoothLowEnergyAPI::GetFactoryInstance();
extensions::BluetoothPrivateAPI::GetFactoryInstance();
extensions::BrailleDisplayPrivateAPI::GetFactoryInstance();
extensions::chromedirectsetting::ChromeDirectSettingAPI::GetFactoryInstance();
extensions::CommandService::GetFactoryInstance();
extensions::ContentSettingsService::GetFactoryInstance();
extensions::CookiesAPI::GetFactoryInstance();
extensions::DeveloperPrivateAPI::GetFactoryInstance();
extensions::DialAPIFactory::GetInstance();
extensions::ExtensionActionAPI::GetFactoryInstance();
extensions::ExtensionGarbageCollectorFactory::GetInstance();
extensions::ExtensionStorageMonitorFactory::GetInstance();
extensions::ExtensionSystemFactory::GetInstance();
......
TokenCacheServiceFactory::GetInstance();
extensions::ExtensionGCMAppHandler::GetFactoryInstance();
extensions::api::BluetoothSocketEventDispatcher::GetFactoryInstance();
}
每个对象的注册都是通过XXXX.GetInstance静态方法创建其单例对象,并在构造函数中通过调用基类构造函数BrowserContextKeyedServiceFactory(namestring,BrowserContextDependencyManager::GetInstance())以及构造函数BrowserContextKeyedBaseFactory(name, manager)将此对象注册到依赖对象管理器中(dependency_manager_->AddComponent(this););如果本对象依赖于其他对象 ,则在其构造函数中调用DependsOn方法将此依赖关系添加到管理器中(dependency_manager_->AddEdge(rhs, this);)。
至此通过各种XXXX.getInstance方法建立起了依赖关系图(有向图),如果能够画出此依赖图,应该会是一副较大的图;在BrowserContextDependencyManager类中提供了打印此图的debug方法DumpBrowserContextDependencies,有机会可以尝试下看看。