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::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(); it != construction_order.end(); ++it) {
52 BrowserContextKeyedBaseFactory* factory =
53 static_cast<BrowserContextKeyedBaseFactory*>(*it);
54 factory->RegisterProfilePrefsIfNecessaryForContext(context, pref_registry);
58 void BrowserContextDependencyManager::CreateBrowserContextServices(
59 content::BrowserContext* context) {
60 DoCreateBrowserContextServices(context, false);
63 void BrowserContextDependencyManager::CreateBrowserContextServicesForTest(
64 content::BrowserContext* context) {
65 DoCreateBrowserContextServices(context, true);
68 void BrowserContextDependencyManager::DoCreateBrowserContextServices(
69 content::BrowserContext* context,
70 bool is_testing_context) {
71 TRACE_EVENT0("browser",
72 "BrowserContextDependencyManager::DoCreateBrowserContextServices")
74 MarkBrowserContextLiveForTesting(context);
77 std::vector<DependencyNode*> construction_order;
78 if (!dependency_graph_.GetConstructionOrder(&construction_order)) {
83 DumpBrowserContextDependencies(context);
86 for (size_t i = 0; i < construction_order.size(); i++) {
87 BrowserContextKeyedBaseFactory* factory =
88 static_cast<BrowserContextKeyedBaseFactory*>(construction_order[i]);
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.";
139 void BrowserContextDependencyManager::MarkBrowserContextLiveForTesting(
140 content::BrowserContext* context) {
141 dead_context_pointers_.erase(context);
146 BrowserContextDependencyManager*
147 BrowserContextDependencyManager::GetInstance() {
148 return Singleton<BrowserContextDependencyManager>::get();
151 BrowserContextDependencyManager::BrowserContextDependencyManager() {
154 BrowserContextDependencyManager::~BrowserContextDependencyManager() {
160 std::string BrowserContextKeyedBaseFactoryGetNodeName(DependencyNode* node) {
161 return static_cast<BrowserContextKeyedBaseFactory*>(node)->name();
166 void BrowserContextDependencyManager::DumpBrowserContextDependencies(
167 content::BrowserContext* context) {
168 // Whenever we try to build a destruction ordering, we should also dump a
169 // dependency graph to "/path/to/context/context-dependencies.dot".
170 if (CommandLine::ForCurrentProcess()->HasSwitch(
171 kDumpBrowserContextDependencyGraphFlag)) {
172 base::FilePath dot_file =
173 context->GetPath().AppendASCII("browser-context-dependencies.dot");
174 std::string contents = dependency_graph_.DumpAsGraphviz(
176 base::Bind(&BrowserContextKeyedBaseFactoryGetNodeName));
177 file_util::WriteFile(dot_file, contents.c_str(), contents.size());