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