1 // Copyright (c) 2013 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/browser_context_keyed_service/browser_context_dependency_manager.h"
11 #include "base/bind.h"
12 #include "base/debug/trace_event.h"
13 #include "components/browser_context_keyed_service/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::CreateBrowserContextServices(
43 content::BrowserContext
* context
) {
44 DoCreateBrowserContextServices(context
, false, false);
47 void BrowserContextDependencyManager::CreateBrowserContextServicesForTest(
48 content::BrowserContext
* context
,
49 bool force_register_prefs
) {
50 DoCreateBrowserContextServices(context
, true, force_register_prefs
);
53 void BrowserContextDependencyManager::DoCreateBrowserContextServices(
54 content::BrowserContext
* context
,
55 bool is_testing_context
,
56 bool force_register_prefs
) {
57 TRACE_EVENT0("browser",
58 "BrowserContextDependencyManager::DoCreateBrowserContextServices")
60 // Unmark |context| as dead. This exists because of unit tests, which will
61 // often have similar stack structures. 0xWhatever might be created, go out
62 // of scope, and then a new BrowserContext object might be created
64 dead_context_pointers_
.erase(context
);
67 std::vector
<DependencyNode
*> construction_order
;
68 if (!dependency_graph_
.GetConstructionOrder(&construction_order
)) {
73 DumpBrowserContextDependencies(context
);
76 for (size_t i
= 0; i
< construction_order
.size(); i
++) {
77 BrowserContextKeyedBaseFactory
* factory
=
78 static_cast<BrowserContextKeyedBaseFactory
*>(construction_order
[i
]);
80 if (!context
->IsOffTheRecord() || force_register_prefs
) {
81 // We only register preferences on normal contexts because the incognito
82 // context shares the pref service with the normal one. Always register
83 // for standalone testing contexts (testing contexts that don't have an
84 // "original" profile set) as otherwise the preferences won't be
86 factory
->RegisterUserPrefsOnBrowserContext(context
);
89 if (is_testing_context
&& factory
->ServiceIsNULLWhileTesting()) {
90 factory
->SetEmptyTestingFactory(context
);
91 } else if (factory
->ServiceIsCreatedWithBrowserContext()) {
92 // Create the service.
93 factory
->CreateServiceNow(context
);
98 void BrowserContextDependencyManager::DestroyBrowserContextServices(
99 content::BrowserContext
* context
) {
100 std::vector
<DependencyNode
*> destruction_order
;
101 if (!dependency_graph_
.GetDestructionOrder(&destruction_order
)) {
106 DumpBrowserContextDependencies(context
);
109 for (size_t i
= 0; i
< destruction_order
.size(); i
++) {
110 BrowserContextKeyedBaseFactory
* factory
=
111 static_cast<BrowserContextKeyedBaseFactory
*>(destruction_order
[i
]);
112 factory
->BrowserContextShutdown(context
);
116 // The context is now dead to the rest of the program.
117 dead_context_pointers_
.insert(context
);
120 for (size_t i
= 0; i
< destruction_order
.size(); i
++) {
121 BrowserContextKeyedBaseFactory
* factory
=
122 static_cast<BrowserContextKeyedBaseFactory
*>(destruction_order
[i
]);
123 factory
->BrowserContextDestroyed(context
);
128 void BrowserContextDependencyManager::AssertBrowserContextWasntDestroyed(
129 content::BrowserContext
* context
) {
130 if (dead_context_pointers_
.find(context
) != dead_context_pointers_
.end()) {
131 NOTREACHED() << "Attempted to access a BrowserContext that was ShutDown(). "
132 << "This is most likely a heap smasher in progress. After "
133 << "BrowserContextKeyedService::Shutdown() completes, your "
134 << "service MUST NOT refer to depended BrowserContext "
135 << "services again.";
141 BrowserContextDependencyManager
*
142 BrowserContextDependencyManager::GetInstance() {
143 return Singleton
<BrowserContextDependencyManager
>::get();
146 BrowserContextDependencyManager::BrowserContextDependencyManager() {
149 BrowserContextDependencyManager::~BrowserContextDependencyManager() {
155 std::string
BrowserContextKeyedBaseFactoryGetNodeName(DependencyNode
* node
) {
156 return static_cast<BrowserContextKeyedBaseFactory
*>(node
)->name();
161 void BrowserContextDependencyManager::DumpBrowserContextDependencies(
162 content::BrowserContext
* context
) {
163 // Whenever we try to build a destruction ordering, we should also dump a
164 // dependency graph to "/path/to/context/context-dependencies.dot".
165 if (CommandLine::ForCurrentProcess()->HasSwitch(
166 kDumpBrowserContextDependencyGraphFlag
)) {
167 base::FilePath dot_file
=
168 context
->GetPath().AppendASCII("browser-context-dependencies.dot");
169 std::string contents
= dependency_graph_
.DumpAsGraphviz(
171 base::Bind(&BrowserContextKeyedBaseFactoryGetNodeName
));
172 file_util::WriteFile(dot_file
, contents
.c_str(), contents
.size());