chromium之extension机制简单分析一:extension初始化

最近抽时间分析了一下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,有机会可以尝试下看看。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值