1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Use of this source code is governed by a BSD-style license that can be 3ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// found in the LICENSE file. 4ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 5ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/profiles/profile_dependency_manager.h" 6ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 7ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include <algorithm> 8ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include <deque> 9ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include <iterator> 10ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 11ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/profiles/profile_keyed_service.h" 12ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/profiles/profile_keyed_service_factory.h" 13ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/notification_service.h" 14ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 15ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenclass Profile; 16ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 17ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ProfileDependencyManager::AddComponent( 18ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ProfileKeyedServiceFactory* component) { 19ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen all_components_.push_back(component); 20ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen destruction_order_.clear(); 21ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 22ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 23ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ProfileDependencyManager::RemoveComponent( 24ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ProfileKeyedServiceFactory* component) { 25ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen all_components_.erase(std::remove(all_components_.begin(), 26ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen all_components_.end(), 27ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen component), 28ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen all_components_.end()); 29ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 30ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Remove all dependency edges that contain this component. 31ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EdgeMap::iterator it = edges_.begin(); 32ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen while (it != edges_.end()) { 33ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EdgeMap::iterator temp = it; 34ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ++it; 35ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 36ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (temp->first == component || temp->second == component) 37ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen edges_.erase(temp); 38ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 39ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 40ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen destruction_order_.clear(); 41ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 42ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 43ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ProfileDependencyManager::AddEdge(ProfileKeyedServiceFactory* depended, 44ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ProfileKeyedServiceFactory* dependee) { 45ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen edges_.insert(std::make_pair(depended, dependee)); 46ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen destruction_order_.clear(); 47ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 48ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 49ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ProfileDependencyManager::DestroyProfileServices(Profile* profile) { 50ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (destruction_order_.empty()) 51ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen BuildDestructionOrder(); 52ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 53ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (std::vector<ProfileKeyedServiceFactory*>::const_iterator it = 54ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen destruction_order_.begin(); it != destruction_order_.end(); ++it) { 55ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen (*it)->ProfileShutdown(profile); 56ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 57ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 58ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (std::vector<ProfileKeyedServiceFactory*>::const_iterator it = 59ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen destruction_order_.begin(); it != destruction_order_.end(); ++it) { 60ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen (*it)->ProfileDestroyed(profile); 61ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 62ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 63ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 64ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// static 65ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenProfileDependencyManager* ProfileDependencyManager::GetInstance() { 66ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return Singleton<ProfileDependencyManager>::get(); 67ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 68ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 69ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenProfileDependencyManager::ProfileDependencyManager() {} 70ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 71ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenProfileDependencyManager::~ProfileDependencyManager() {} 72ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 73ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ProfileDependencyManager::BuildDestructionOrder() { 74ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Step 1: Build a set of nodes with no incoming edges. 75ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::deque<ProfileKeyedServiceFactory*> queue; 76ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::copy(all_components_.begin(), 77ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen all_components_.end(), 78ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::back_inserter(queue)); 79ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 80ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::deque<ProfileKeyedServiceFactory*>::iterator queue_end = queue.end(); 81ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (EdgeMap::const_iterator it = edges_.begin(); 82ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen it != edges_.end(); ++it) { 83ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen queue_end = std::remove(queue.begin(), queue_end, it->second); 84ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 85ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen queue.erase(queue_end, queue.end()); 86ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 87ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Step 2: Do the Kahn topological sort. 88ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::vector<ProfileKeyedServiceFactory*> output; 89ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EdgeMap edges(edges_); 90ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen while (!queue.empty()) { 91ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ProfileKeyedServiceFactory* node = queue.front(); 92ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen queue.pop_front(); 93ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen output.push_back(node); 94ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 95ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::pair<EdgeMap::iterator, EdgeMap::iterator> range = 96ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen edges.equal_range(node); 97ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EdgeMap::iterator it = range.first; 98ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen while (it != range.second) { 99ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ProfileKeyedServiceFactory* dest = it->second; 100ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EdgeMap::iterator temp = it; 101ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen it++; 102ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen edges.erase(temp); 103ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 104ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen bool has_incoming_edges = false; 105ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (EdgeMap::iterator jt = edges.begin(); jt != edges.end(); ++jt) { 106ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (jt->second == dest) { 107ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen has_incoming_edges = true; 108ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen break; 109ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 110ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 111ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 112ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!has_incoming_edges) 113ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen queue.push_back(dest); 114ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 115ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 116ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 117ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (edges.size()) { 118ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen NOTREACHED() << "Dependency graph has a cycle. We are doomed."; 119ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 120ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 121ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::reverse(output.begin(), output.end()); 122ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen destruction_order_ = output; 123ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 124