本来要上下简单的uml图,但是不知道怎么穿不上来,就简单描述下巴。
Chrome中profile是一个核心的对象,profile用来进行chrome账户之间的隔离,不用的账户所持有的profile不一样。所有的逻辑或多或少,直接间接的都与他发生关联。大部分的chrome服务类, 都可以通过profile来获取。这些服务类彼此之间相互依赖,提供基础的服务给浏览器的上层使用,本文大概分析下这些服务的实现结构。
实现上来说每个service都有对应的一个继承自ProfileKeyedServiceFactory的一个对应工厂类。工厂类以Singleton<>类为实体存在,维护了每个profile所对应的service的生命周期。ProfileKeyedServiceFactory负责生产service的实体对象,用map保存profile和service之间的对应关系.同时借助于ProfileDependencyManager来维护各个Service之间的互相依赖关系。摘抄一个Service的核心代码如下:
class ExtensionActionManager : public ProfileKeyedService, public content::NotificationObserver { public: ..........
static ExtensionActionManager* Get(Profile* profile)
{
return ExtensionActionManagerFactory::GetForProfile(profile);
}
.......................
};
class ExtensionActionManagerFactory : public ProfileKeyedServiceFactory { public: // ProfileKeyedServiceFactory implementation: static ExtensionActionManager* GetForProfile(Profile* profile) { return static_cast<ExtensionActionManager*>( GetInstance()->GetServiceForProfile(profile, true)); } static ExtensionActionManagerFactory* GetInstance(); private: friend struct DefaultSingletonTraits<ExtensionActionManagerFactory>; ExtensionActionManagerFactory() : ProfileKeyedServiceFactory("ExtensionActionManager", ProfileDependencyManager::GetInstance()) { } virtual ProfileKeyedService* BuildServiceInstanceFor( Profile* profile) const OVERRIDE { return new ExtensionActionManager(profile); } virtual bool ServiceRedirectedInIncognito() const OVERRIDE { return true; } }; ExtensionActionManagerFactory* ExtensionActionManagerFactory::GetInstance() { return Singleton<ExtensionActionManagerFactory>::get(); }
通过ExtensionActionManager::Get函数可以获取到某个profile对应的service,通过上面的代码可以清晰地看到ExtensionActionManagerFactory和ExtensionActionManager之间的关系,要全读懂的话,最好看下ProfileKeyedServiceFactory 的源码。
chrome中的service实现相对来说简单,但是管理service之间依赖关系的ProfileDependencyManager值得研究下. 该类内部已有向图的方式管理各个service, 程序运行时建立起各个服务组件间的依赖关系, 然后通过 有向图排列出 服务的创建和销毁顺序. 把用算法排序的函数超出来看看
void ProfileDependencyManager::BuildDestructionOrder(Profile* profile) { // Step 1: Build a set of nodes with no incoming edges. std::deque<ProfileKeyedBaseFactory*> queue; std::copy(all_components_.begin(), all_components_.end(), std::back_inserter(queue)); std::deque<ProfileKeyedBaseFactory*>::iterator queue_end = queue.end(); for (EdgeMap::const_iterator it = edges_.begin(); it != edges_.end(); ++it) { queue_end = std::remove(queue.begin(), queue_end, it->second); } queue.erase(queue_end, queue.end()); // Step 2: Do the Kahn topological sort. std::vector<ProfileKeyedBaseFactory*> output; EdgeMap edges(edges_); while (!queue.empty()) { ProfileKeyedBaseFactory* node = queue.front(); queue.pop_front(); output.push_back(node); std::pair<EdgeMap::iterator, EdgeMap::iterator> range = edges.equal_range(node); EdgeMap::iterator it = range.first; while (it != range.second) { ProfileKeyedBaseFactory* dest = it->second; EdgeMap::iterator temp = it; it++; edges.erase(temp); bool has_incoming_edges = false; for (EdgeMap::iterator jt = edges.begin(); jt != edges.end(); ++jt) { if (jt->second == dest) { has_incoming_edges = true; break; } } if (!has_incoming_edges) queue.push_back(dest); } } if (edges.size()) { NOTREACHED() << "Dependency graph has a cycle. We are doomed."; } std::reverse(output.begin(), output.end()); destruction_order_ = output; }