1 // Copyright 2014 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 "components/keyed_service/content/browser_context_dependency_manager.h"
11 #include "base/bind.h"
12 #include "base/debug/trace_event.h"
13 #include "components/keyed_service/content/browser_context_keyed_base_factory.h"
14 #include "content/public/browser/browser_context.h"
17 #include "base/command_line.h"
18 #include "base/file_util.h"
20 // Dumps dependency information about our browser context keyed services
21 // into a dot file in the browser context directory.
22 const char kDumpBrowserContextDependencyGraphFlag
[] =
23 "dump-browser-context-graph";
26 void BrowserContextDependencyManager::AddComponent(
27 BrowserContextKeyedBaseFactory
* component
) {
28 dependency_graph_
.AddNode(component
);
31 void BrowserContextDependencyManager::RemoveComponent(
32 BrowserContextKeyedBaseFactory
* component
) {
33 dependency_graph_
.RemoveNode(component
);
36 void BrowserContextDependencyManager::AddEdge(
37 BrowserContextKeyedBaseFactory
* depended
,
38 BrowserContextKeyedBaseFactory
* dependee
) {
39 dependency_graph_
.AddEdge(depended
, dependee
);
42 void BrowserContextDependencyManager::RegisterProfilePrefsForServices(
43 const content::BrowserContext
* context
,
44 user_prefs::PrefRegistrySyncable
* pref_registry
) {
45 std::vector
<DependencyNode
*> construction_order
;
46 if (!dependency_graph_
.GetConstructionOrder(&construction_order
)) {
50 for (std::vector
<DependencyNode
*>::const_iterator it
=
51 construction_order
.begin();
52 it
!= construction_order
.end();
54 BrowserContextKeyedBaseFactory
* factory
=
55 static_cast<BrowserContextKeyedBaseFactory
*>(*it
);
56 factory
->RegisterProfilePrefsIfNecessaryForContext(context
, pref_registry
);
60 void BrowserContextDependencyManager::CreateBrowserContextServices(
61 content::BrowserContext
* context
) {
62 DoCreateBrowserContextServices(context
, false);
65 void BrowserContextDependencyManager::CreateBrowserContextServicesForTest(
66 content::BrowserContext
* context
) {
67 DoCreateBrowserContextServices(context
, true);
70 void BrowserContextDependencyManager::DoCreateBrowserContextServices(
71 content::BrowserContext
* context
,
72 bool is_testing_context
) {
75 "BrowserContextDependencyManager::DoCreateBrowserContextServices")
77 MarkBrowserContextLiveForTesting(context
);
80 will_create_browser_context_services_callbacks_
.Notify(context
);
82 std::vector
<DependencyNode
*> construction_order
;
83 if (!dependency_graph_
.GetConstructionOrder(&construction_order
)) {
88 DumpBrowserContextDependencies(context
);
91 for (size_t i
= 0; i
< construction_order
.size(); i
++) {
92 BrowserContextKeyedBaseFactory
* factory
=
93 static_cast<BrowserContextKeyedBaseFactory
*>(construction_order
[i
]);
94 if (is_testing_context
&& factory
->ServiceIsNULLWhileTesting()) {
95 factory
->SetEmptyTestingFactory(context
);
96 } else if (factory
->ServiceIsCreatedWithBrowserContext()) {
97 // Create the service.
98 factory
->CreateServiceNow(context
);
103 void BrowserContextDependencyManager::DestroyBrowserContextServices(
104 content::BrowserContext
* context
) {
105 std::vector
<DependencyNode
*> destruction_order
;
106 if (!dependency_graph_
.GetDestructionOrder(&destruction_order
)) {
111 DumpBrowserContextDependencies(context
);
114 for (size_t i
= 0; i
< destruction_order
.size(); i
++) {
115 BrowserContextKeyedBaseFactory
* factory
=
116 static_cast<BrowserContextKeyedBaseFactory
*>(destruction_order
[i
]);
117 factory
->BrowserContextShutdown(context
);
121 // The context is now dead to the rest of the program.
122 dead_context_pointers_
.insert(context
);
125 for (size_t i
= 0; i
< destruction_order
.size(); i
++) {
126 BrowserContextKeyedBaseFactory
* factory
=
127 static_cast<BrowserContextKeyedBaseFactory
*>(destruction_order
[i
]);
128 factory
->BrowserContextDestroyed(context
);
132 scoped_ptr
<base::CallbackList
<void(content::BrowserContext
*)>::Subscription
>
133 BrowserContextDependencyManager::
134 RegisterWillCreateBrowserContextServicesCallbackForTesting(
135 const base::Callback
<void(content::BrowserContext
*)>& callback
) {
136 return will_create_browser_context_services_callbacks_
.Add(callback
);
140 void BrowserContextDependencyManager::AssertBrowserContextWasntDestroyed(
141 content::BrowserContext
* context
) {
142 if (dead_context_pointers_
.find(context
) != dead_context_pointers_
.end()) {
143 NOTREACHED() << "Attempted to access a BrowserContext that was ShutDown(). "
144 << "This is most likely a heap smasher in progress. After "
145 << "KeyedService::Shutdown() completes, your "
146 << "service MUST NOT refer to depended BrowserContext "
147 << "services again.";
151 void BrowserContextDependencyManager::MarkBrowserContextLiveForTesting(
152 content::BrowserContext
* context
) {
153 dead_context_pointers_
.erase(context
);
158 BrowserContextDependencyManager
*
159 BrowserContextDependencyManager::GetInstance() {
160 return Singleton
<BrowserContextDependencyManager
>::get();
163 BrowserContextDependencyManager::BrowserContextDependencyManager() {}
165 BrowserContextDependencyManager::~BrowserContextDependencyManager() {}
170 std::string
BrowserContextKeyedBaseFactoryGetNodeName(DependencyNode
* node
) {
171 return static_cast<BrowserContextKeyedBaseFactory
*>(node
)->name();
176 void BrowserContextDependencyManager::DumpBrowserContextDependencies(
177 content::BrowserContext
* context
) {
178 // Whenever we try to build a destruction ordering, we should also dump a
179 // dependency graph to "/path/to/context/context-dependencies.dot".
180 if (CommandLine::ForCurrentProcess()->HasSwitch(
181 kDumpBrowserContextDependencyGraphFlag
)) {
182 base::FilePath dot_file
=
183 context
->GetPath().AppendASCII("browser-context-dependencies.dot");
184 std::string contents
= dependency_graph_
.DumpAsGraphviz(
186 base::Bind(&BrowserContextKeyedBaseFactoryGetNodeName
));
187 base::WriteFile(dot_file
, contents
.c_str(), contents
.size());