1 // Copyright (c) 2012 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.
5 #include "chrome/browser/profiles/profile_dependency_manager.h"
11 #include "chrome/browser/autofill/personal_data_manager_factory.h"
12 #include "chrome/browser/background/background_contents_service_factory.h"
13 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
14 #include "chrome/browser/content_settings/cookie_settings.h"
15 #include "chrome/browser/custom_handlers/protocol_handler_registry_factory.h"
16 #include "chrome/browser/download/download_service_factory.h"
17 #include "chrome/browser/extensions/api/bluetooth/bluetooth_api_factory.h"
18 #include "chrome/browser/extensions/api/commands/command_service_factory.h"
19 #include "chrome/browser/extensions/api/discovery/suggested_links_registry_factory.h"
20 #include "chrome/browser/extensions/api/processes/processes_api_factory.h"
21 #include "chrome/browser/extensions/api/tab_capture/tab_capture_registry_factory.h"
22 #include "chrome/browser/extensions/app_restore_service_factory.h"
23 #include "chrome/browser/extensions/extension_system_factory.h"
24 #include "chrome/browser/favicon/favicon_service_factory.h"
25 #include "chrome/browser/google/google_url_tracker_factory.h"
26 #include "chrome/browser/history/history_service_factory.h"
27 #include "chrome/browser/history/shortcuts_backend_factory.h"
28 #include "chrome/browser/intents/web_intents_registry_factory.h"
29 #include "chrome/browser/media_gallery/media_galleries_preferences_factory.h"
30 #include "chrome/browser/notifications/desktop_notification_service_factory.h"
31 #include "chrome/browser/password_manager/password_store_factory.h"
32 #include "chrome/browser/plugins/plugin_prefs_factory.h"
33 #include "chrome/browser/predictors/autocomplete_action_predictor_factory.h"
34 #include "chrome/browser/predictors/predictor_database_factory.h"
35 #include "chrome/browser/predictors/resource_prefetch_predictor_factory.h"
36 #include "chrome/browser/prerender/prerender_link_manager_factory.h"
37 #include "chrome/browser/prerender/prerender_manager_factory.h"
38 #include "chrome/browser/printing/cloud_print/cloud_print_proxy_service_factory.h"
39 #include "chrome/browser/profiles/profile.h"
40 #include "chrome/browser/profiles/profile_keyed_service.h"
41 #include "chrome/browser/profiles/profile_keyed_service_factory.h"
42 #include "chrome/browser/protector/protector_service_factory.h"
43 #include "chrome/browser/search_engines/template_url_fetcher_factory.h"
44 #include "chrome/browser/search_engines/template_url_service_factory.h"
45 #include "chrome/browser/sessions/session_service_factory.h"
46 #include "chrome/browser/sessions/tab_restore_service_factory.h"
47 #include "chrome/browser/signin/signin_manager_factory.h"
48 #include "chrome/browser/signin/token_service_factory.h"
49 #include "chrome/browser/speech/chrome_speech_recognition_preferences.h"
50 #include "chrome/browser/speech/speech_input_extension_manager.h"
51 #include "chrome/browser/spellchecker/spellcheck_factory.h"
53 #include "chrome/browser/sync/credential_cache_service_factory_win.h"
55 #include "chrome/browser/sync/profile_sync_service_factory.h"
56 #include "chrome/browser/themes/theme_service_factory.h"
57 #include "chrome/browser/thumbnails/thumbnail_service_factory.h"
58 #include "chrome/browser/ui/find_bar/find_bar_state_factory.h"
59 #include "chrome/browser/ui/global_error/global_error_service_factory.h"
60 #include "chrome/browser/ui/tabs/pinned_tab_service_factory.h"
61 #include "chrome/browser/ui/webui/chrome_url_data_manager_factory.h"
62 #include "chrome/browser/ui/webui/ntp/ntp_resource_cache_factory.h"
63 #include "chrome/browser/user_style_sheet_watcher_factory.h"
64 #include "chrome/browser/visitedlink/visitedlink_master_factory.h"
65 #include "chrome/browser/webdata/web_data_service_factory.h"
67 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
68 #include "chrome/browser/captive_portal/captive_portal_service_factory.h"
71 #if defined(ENABLE_CONFIGURATION_POLICY)
72 #include "chrome/browser/policy/user_policy_signin_service_factory.h"
76 #include "chrome/browser/ui/gesture_prefs_observer_factory_aura.h"
80 #include "base/command_line.h"
81 #include "base/file_util.h"
82 #include "chrome/common/chrome_switches.h"
87 void ProfileDependencyManager::AddComponent(
88 ProfileKeyedBaseFactory
* component
) {
89 all_components_
.push_back(component
);
90 destruction_order_
.clear();
93 void ProfileDependencyManager::RemoveComponent(
94 ProfileKeyedBaseFactory
* component
) {
95 all_components_
.erase(std::remove(all_components_
.begin(),
96 all_components_
.end(),
98 all_components_
.end());
100 // Remove all dependency edges that contain this component.
101 EdgeMap::iterator it
= edges_
.begin();
102 while (it
!= edges_
.end()) {
103 EdgeMap::iterator temp
= it
;
106 if (temp
->first
== component
|| temp
->second
== component
)
110 destruction_order_
.clear();
113 void ProfileDependencyManager::AddEdge(ProfileKeyedBaseFactory
* depended
,
114 ProfileKeyedBaseFactory
* dependee
) {
115 edges_
.insert(std::make_pair(depended
, dependee
));
116 destruction_order_
.clear();
119 void ProfileDependencyManager::CreateProfileServices(Profile
* profile
,
120 bool is_testing_profile
) {
122 // Unmark |profile| as dead. This exists because of unit tests, which will
123 // often have similar stack structures. 0xWhatever might be created, go out
124 // of scope, and then a new Profile object might be created at 0xWhatever.
125 dead_profile_pointers_
.erase(profile
);
128 AssertFactoriesBuilt();
130 if (destruction_order_
.empty())
131 BuildDestructionOrder(profile
);
133 // Iterate in reverse destruction order for creation.
134 for (std::vector
<ProfileKeyedBaseFactory
*>::reverse_iterator rit
=
135 destruction_order_
.rbegin(); rit
!= destruction_order_
.rend();
137 if (!profile
->IsOffTheRecord()) {
138 // We only register preferences on normal profiles because the incognito
139 // profile shares the pref service with the normal one.
140 (*rit
)->RegisterUserPrefsOnProfile(profile
);
143 if (is_testing_profile
&& (*rit
)->ServiceIsNULLWhileTesting()) {
144 (*rit
)->SetEmptyTestingFactory(profile
);
145 } else if ((*rit
)->ServiceIsCreatedWithProfile()) {
146 // Create the service.
147 (*rit
)->CreateServiceNow(profile
);
152 void ProfileDependencyManager::DestroyProfileServices(Profile
* profile
) {
153 if (destruction_order_
.empty())
154 BuildDestructionOrder(profile
);
156 for (std::vector
<ProfileKeyedBaseFactory
*>::const_iterator it
=
157 destruction_order_
.begin(); it
!= destruction_order_
.end(); ++it
) {
158 (*it
)->ProfileShutdown(profile
);
162 // The profile is now dead to the rest of the program.
163 dead_profile_pointers_
.insert(profile
);
166 for (std::vector
<ProfileKeyedBaseFactory
*>::const_iterator it
=
167 destruction_order_
.begin(); it
!= destruction_order_
.end(); ++it
) {
168 (*it
)->ProfileDestroyed(profile
);
173 void ProfileDependencyManager::AssertProfileWasntDestroyed(Profile
* profile
) {
174 if (dead_profile_pointers_
.find(profile
) != dead_profile_pointers_
.end()) {
175 NOTREACHED() << "Attempted to access a Profile that was ShutDown(). This "
176 << "is most likely a heap smasher in progress. After "
177 << "ProfileKeyedService::Shutdown() completes, your service "
178 << "MUST NOT refer to depended Profile services again.";
184 ProfileDependencyManager
* ProfileDependencyManager::GetInstance() {
185 return Singleton
<ProfileDependencyManager
>::get();
188 ProfileDependencyManager::ProfileDependencyManager()
189 : built_factories_(false) {
192 ProfileDependencyManager::~ProfileDependencyManager() {}
194 // This method gets the instance of each ServiceFactory. We do this so that
195 // each ServiceFactory initializes iteslf and registers its dependencies with
196 // the global PreferenceDependencyManager. We need to have a complete
197 // dependency graph when we create a profile so we can dispatch the profile
198 // creation message to the services that want to create their services at
199 // profile creation time.
201 // TODO(erg): This needs to be something else. I don't think putting every
202 // FooServiceFactory here will scale or is desireable long term.
203 void ProfileDependencyManager::AssertFactoriesBuilt() {
204 if (built_factories_
)
207 #if defined(ENABLE_BACKGROUND)
208 BackgroundContentsServiceFactory::GetInstance();
210 BookmarkModelFactory::GetInstance();
211 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
212 captive_portal::CaptivePortalServiceFactory::GetInstance();
214 ChromeURLDataManagerFactory::GetInstance();
215 #if defined(ENABLE_PRINTING)
216 CloudPrintProxyServiceFactory::GetInstance();
218 CookieSettings::Factory::GetInstance();
219 #if defined(ENABLE_NOTIFICATIONS)
220 DesktopNotificationServiceFactory::GetInstance();
222 DownloadServiceFactory::GetInstance();
223 #if defined(ENABLE_EXTENSIONS)
224 extensions::AppRestoreServiceFactory::GetInstance();
225 extensions::BluetoothAPIFactory::GetInstance();
226 extensions::CommandServiceFactory::GetInstance();
227 extensions::SuggestedLinksRegistryFactory::GetInstance();
228 extensions::ExtensionSystemFactory::GetInstance();
229 extensions::ProcessesAPIFactory::GetInstance();
230 extensions::TabCaptureRegistryFactory::GetInstance();
232 FaviconServiceFactory::GetInstance();
233 FindBarStateFactory::GetInstance();
234 #if defined(USE_AURA)
235 GesturePrefsObserverFactoryAura::GetInstance();
237 GlobalErrorServiceFactory::GetInstance();
238 GoogleURLTrackerFactory::GetInstance();
239 HistoryServiceFactory::GetInstance();
240 MediaGalleriesPreferencesFactory::GetInstance();
241 NTPResourceCacheFactory::GetInstance();
242 PasswordStoreFactory::GetInstance();
243 PersonalDataManagerFactory::GetInstance();
244 #if !defined(OS_ANDROID)
245 PinnedTabServiceFactory::GetInstance();
247 PluginPrefsFactory::GetInstance();
248 #if defined(ENABLE_CONFIGURATION_POLICY) && !defined(OS_CHROMEOS)
249 // Not used on chromeos because signin happens before the profile is loaded.
250 policy::UserPolicySigninServiceFactory::GetInstance();
252 predictors::AutocompleteActionPredictorFactory::GetInstance();
253 predictors::PredictorDatabaseFactory::GetInstance();
254 predictors::ResourcePrefetchPredictorFactory::GetInstance();
255 prerender::PrerenderManagerFactory::GetInstance();
256 prerender::PrerenderLinkManagerFactory::GetInstance();
257 ProfileSyncServiceFactory::GetInstance();
258 ProtocolHandlerRegistryFactory::GetInstance();
259 #if defined(ENABLE_PROTECTOR_SERVICE)
260 protector::ProtectorServiceFactory::GetInstance();
262 #if defined(ENABLE_SESSION_SERVICE)
263 SessionServiceFactory::GetInstance();
265 ShortcutsBackendFactory::GetInstance();
266 ThumbnailServiceFactory::GetInstance();
267 SigninManagerFactory::GetInstance();
268 #if defined(ENABLE_INPUT_SPEECH)
269 SpeechInputExtensionManager::InitializeFactory();
270 ChromeSpeechRecognitionPreferences::InitializeFactory();
272 SpellcheckServiceFactory::GetInstance();
274 syncer::CredentialCacheServiceFactory::GetInstance();
276 TabRestoreServiceFactory::GetInstance();
277 TemplateURLFetcherFactory::GetInstance();
278 TemplateURLServiceFactory::GetInstance();
279 #if defined(ENABLE_THEMES)
280 ThemeServiceFactory::GetInstance();
282 TokenServiceFactory::GetInstance();
283 UserStyleSheetWatcherFactory::GetInstance();
284 VisitedLinkMasterFactory::GetInstance();
285 WebDataServiceFactory::GetInstance();
286 #if defined(ENABLE_WEB_INTENTS)
287 WebIntentsRegistryFactory::GetInstance();
290 built_factories_
= true;
293 void ProfileDependencyManager::BuildDestructionOrder(Profile
* profile
) {
295 // Whenever we try to build a destruction ordering, we should also dump a
296 // dependency graph to "/path/to/profile/profile-dependencies.dot".
297 if (CommandLine::ForCurrentProcess()->HasSwitch(
298 switches::kDumpProfileDependencyGraph
)) {
300 profile
->GetPath().AppendASCII("profile-dependencies.dot");
301 std::string contents
= DumpGraphvizDependency();
302 file_util::WriteFile(dot_file
, contents
.c_str(), contents
.size());
306 // Step 1: Build a set of nodes with no incoming edges.
307 std::deque
<ProfileKeyedBaseFactory
*> queue
;
308 std::copy(all_components_
.begin(),
309 all_components_
.end(),
310 std::back_inserter(queue
));
312 std::deque
<ProfileKeyedBaseFactory
*>::iterator queue_end
= queue
.end();
313 for (EdgeMap::const_iterator it
= edges_
.begin();
314 it
!= edges_
.end(); ++it
) {
315 queue_end
= std::remove(queue
.begin(), queue_end
, it
->second
);
317 queue
.erase(queue_end
, queue
.end());
319 // Step 2: Do the Kahn topological sort.
320 std::vector
<ProfileKeyedBaseFactory
*> output
;
321 EdgeMap
edges(edges_
);
322 while (!queue
.empty()) {
323 ProfileKeyedBaseFactory
* node
= queue
.front();
325 output
.push_back(node
);
327 std::pair
<EdgeMap::iterator
, EdgeMap::iterator
> range
=
328 edges
.equal_range(node
);
329 EdgeMap::iterator it
= range
.first
;
330 while (it
!= range
.second
) {
331 ProfileKeyedBaseFactory
* dest
= it
->second
;
332 EdgeMap::iterator temp
= it
;
336 bool has_incoming_edges
= false;
337 for (EdgeMap::iterator jt
= edges
.begin(); jt
!= edges
.end(); ++jt
) {
338 if (jt
->second
== dest
) {
339 has_incoming_edges
= true;
344 if (!has_incoming_edges
)
345 queue
.push_back(dest
);
350 NOTREACHED() << "Dependency graph has a cycle. We are doomed.";
353 std::reverse(output
.begin(), output
.end());
354 destruction_order_
= output
;
359 std::string
ProfileDependencyManager::DumpGraphvizDependency() {
360 std::string
result("digraph {\n");
362 // Make a copy of all components.
363 std::deque
<ProfileKeyedBaseFactory
*> components
;
364 std::copy(all_components_
.begin(),
365 all_components_
.end(),
366 std::back_inserter(components
));
368 // State all dependencies and remove |second| so we don't generate an
369 // implicit dependency on the Profile hard coded node.
370 std::deque
<ProfileKeyedBaseFactory
*>::iterator components_end
=
372 result
.append(" /* Dependencies */\n");
373 for (EdgeMap::const_iterator it
= edges_
.begin(); it
!= edges_
.end(); ++it
) {
375 result
.append(it
->second
->name());
376 result
.append(" -> ");
377 result
.append(it
->first
->name());
378 result
.append(";\n");
380 components_end
= std::remove(components
.begin(), components_end
,
383 components
.erase(components_end
, components
.end());
385 // Every node that doesn't depend on anything else will implicitly depend on
387 result
.append("\n /* Toplevel attachments */\n");
388 for (std::deque
<ProfileKeyedBaseFactory
*>::const_iterator it
=
389 components
.begin(); it
!= components
.end(); ++it
) {
391 result
.append((*it
)->name());
392 result
.append(" -> Profile;\n");
395 result
.append("\n /* Toplevel profile */\n");
396 result
.append(" Profile [shape=box];\n");
398 result
.append("}\n");