browser_context_dependency_manager.cc revision 1320f92c476a1ad9d19dba2a48c72b75566198e9
124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Copyright 2014 The Chromium Authors. All rights reserved. 224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Use of this source code is governed by a BSD-style license that can be 324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// found in the LICENSE file. 424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "components/keyed_service/content/browser_context_dependency_manager.h" 624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include <algorithm> 824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include <deque> 924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include <iterator> 10144188bc458a35997d2f2e52206ab69747439073Greg Clayton 1124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "base/bind.h" 1224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "base/debug/trace_event.h" 1324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "components/keyed_service/content/browser_context_keyed_base_factory.h" 1424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "content/public/browser/browser_context.h" 1524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 16257663e753af15633e48c7b00eb7b5880168090bGreg Clayton#ifndef NDEBUG 17257663e753af15633e48c7b00eb7b5880168090bGreg Clayton#include "base/command_line.h" 1824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "base/files/file_util.h" 1924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 2024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Dumps dependency information about our browser context keyed services 2124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// into a dot file in the browser context directory. 22257663e753af15633e48c7b00eb7b5880168090bGreg Claytonconst char kDumpBrowserContextDependencyGraphFlag[] = 23be42123fa214b039b86ad152bd21d910db7a7af2Greg Clayton "dump-browser-context-graph"; 24257663e753af15633e48c7b00eb7b5880168090bGreg Clayton#endif // NDEBUG 2524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 26257663e753af15633e48c7b00eb7b5880168090bGreg Claytonvoid BrowserContextDependencyManager::AddComponent( 27257663e753af15633e48c7b00eb7b5880168090bGreg Clayton BrowserContextKeyedBaseFactory* component) { 28257663e753af15633e48c7b00eb7b5880168090bGreg Clayton dependency_graph_.AddNode(component); 29257663e753af15633e48c7b00eb7b5880168090bGreg Clayton} 30257663e753af15633e48c7b00eb7b5880168090bGreg Clayton 31257663e753af15633e48c7b00eb7b5880168090bGreg Claytonvoid BrowserContextDependencyManager::RemoveComponent( 32257663e753af15633e48c7b00eb7b5880168090bGreg Clayton BrowserContextKeyedBaseFactory* component) { 3324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner dependency_graph_.RemoveNode(component); 34257663e753af15633e48c7b00eb7b5880168090bGreg Clayton} 35257663e753af15633e48c7b00eb7b5880168090bGreg Clayton 36257663e753af15633e48c7b00eb7b5880168090bGreg Claytonvoid BrowserContextDependencyManager::AddEdge( 37257663e753af15633e48c7b00eb7b5880168090bGreg Clayton BrowserContextKeyedBaseFactory* depended, 38257663e753af15633e48c7b00eb7b5880168090bGreg Clayton BrowserContextKeyedBaseFactory* dependee) { 39257663e753af15633e48c7b00eb7b5880168090bGreg Clayton dependency_graph_.AddEdge(depended, dependee); 40257663e753af15633e48c7b00eb7b5880168090bGreg Clayton} 41257663e753af15633e48c7b00eb7b5880168090bGreg Clayton 42178710cd4307f3d44dc76ebd70fc7daf7ebe17c5Greg Claytonvoid BrowserContextDependencyManager::RegisterProfilePrefsForServices( 43178710cd4307f3d44dc76ebd70fc7daf7ebe17c5Greg Clayton const content::BrowserContext* context, 44257663e753af15633e48c7b00eb7b5880168090bGreg Clayton user_prefs::PrefRegistrySyncable* pref_registry) { 45257663e753af15633e48c7b00eb7b5880168090bGreg Clayton std::vector<DependencyNode*> construction_order; 46257663e753af15633e48c7b00eb7b5880168090bGreg Clayton if (!dependency_graph_.GetConstructionOrder(&construction_order)) { 47257663e753af15633e48c7b00eb7b5880168090bGreg Clayton NOTREACHED(); 48257663e753af15633e48c7b00eb7b5880168090bGreg Clayton } 49257663e753af15633e48c7b00eb7b5880168090bGreg Clayton 50257663e753af15633e48c7b00eb7b5880168090bGreg Clayton for (std::vector<DependencyNode*>::const_iterator it = 51257663e753af15633e48c7b00eb7b5880168090bGreg Clayton construction_order.begin(); 52257663e753af15633e48c7b00eb7b5880168090bGreg Clayton it != construction_order.end(); 53257663e753af15633e48c7b00eb7b5880168090bGreg Clayton ++it) { 54257663e753af15633e48c7b00eb7b5880168090bGreg Clayton BrowserContextKeyedBaseFactory* factory = 55257663e753af15633e48c7b00eb7b5880168090bGreg Clayton static_cast<BrowserContextKeyedBaseFactory*>(*it); 56257663e753af15633e48c7b00eb7b5880168090bGreg Clayton factory->RegisterProfilePrefsIfNecessaryForContext(context, pref_registry); 57257663e753af15633e48c7b00eb7b5880168090bGreg Clayton } 58257663e753af15633e48c7b00eb7b5880168090bGreg Clayton} 59257663e753af15633e48c7b00eb7b5880168090bGreg Clayton 60257663e753af15633e48c7b00eb7b5880168090bGreg Claytonvoid BrowserContextDependencyManager::CreateBrowserContextServices( 61257663e753af15633e48c7b00eb7b5880168090bGreg Clayton content::BrowserContext* context) { 62257663e753af15633e48c7b00eb7b5880168090bGreg Clayton DoCreateBrowserContextServices(context, false); 6324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner} 64257663e753af15633e48c7b00eb7b5880168090bGreg Clayton 65257663e753af15633e48c7b00eb7b5880168090bGreg Claytonvoid BrowserContextDependencyManager::CreateBrowserContextServicesForTest( 66257663e753af15633e48c7b00eb7b5880168090bGreg Clayton content::BrowserContext* context) { 67257663e753af15633e48c7b00eb7b5880168090bGreg Clayton DoCreateBrowserContextServices(context, true); 68257663e753af15633e48c7b00eb7b5880168090bGreg Clayton} 6936da2aa6dc5ad9994b638ed09eb81c44cc05540bGreg Clayton 70257663e753af15633e48c7b00eb7b5880168090bGreg Claytonvoid BrowserContextDependencyManager::DoCreateBrowserContextServices( 71257663e753af15633e48c7b00eb7b5880168090bGreg Clayton content::BrowserContext* context, 72bc36a861b8e0b2f2dde34f27c9fa9629a357d598Greg Clayton bool is_testing_context) { 73257663e753af15633e48c7b00eb7b5880168090bGreg Clayton TRACE_EVENT0( 74257663e753af15633e48c7b00eb7b5880168090bGreg Clayton "browser", 75257663e753af15633e48c7b00eb7b5880168090bGreg Clayton "BrowserContextDependencyManager::DoCreateBrowserContextServices") 76257663e753af15633e48c7b00eb7b5880168090bGreg Clayton#ifndef NDEBUG 77257663e753af15633e48c7b00eb7b5880168090bGreg Clayton MarkBrowserContextLiveForTesting(context); 78257663e753af15633e48c7b00eb7b5880168090bGreg Clayton#endif 79257663e753af15633e48c7b00eb7b5880168090bGreg Clayton 80257663e753af15633e48c7b00eb7b5880168090bGreg Clayton will_create_browser_context_services_callbacks_.Notify(context); 81257663e753af15633e48c7b00eb7b5880168090bGreg Clayton 82257663e753af15633e48c7b00eb7b5880168090bGreg Clayton std::vector<DependencyNode*> construction_order; 83257663e753af15633e48c7b00eb7b5880168090bGreg Clayton if (!dependency_graph_.GetConstructionOrder(&construction_order)) { 84257663e753af15633e48c7b00eb7b5880168090bGreg Clayton NOTREACHED(); 85257663e753af15633e48c7b00eb7b5880168090bGreg Clayton } 86257663e753af15633e48c7b00eb7b5880168090bGreg Clayton 8724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#ifndef NDEBUG 8824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner DumpBrowserContextDependencies(context); 89257663e753af15633e48c7b00eb7b5880168090bGreg Clayton#endif 90257663e753af15633e48c7b00eb7b5880168090bGreg Clayton 9124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner for (size_t i = 0; i < construction_order.size(); i++) { 9224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner BrowserContextKeyedBaseFactory* factory = 9324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner static_cast<BrowserContextKeyedBaseFactory*>(construction_order[i]); 9424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (is_testing_context && factory->ServiceIsNULLWhileTesting() && 95 !factory->HasTestingFactory(context)) { 96 factory->SetEmptyTestingFactory(context); 97 } else if (factory->ServiceIsCreatedWithBrowserContext()) { 98 // Create the service. 99 factory->CreateServiceNow(context); 100 } 101 } 102} 103 104void BrowserContextDependencyManager::DestroyBrowserContextServices( 105 content::BrowserContext* context) { 106 std::vector<DependencyNode*> destruction_order; 107 if (!dependency_graph_.GetDestructionOrder(&destruction_order)) { 108 NOTREACHED(); 109 } 110 111#ifndef NDEBUG 112 DumpBrowserContextDependencies(context); 113#endif 114 115 for (size_t i = 0; i < destruction_order.size(); i++) { 116 BrowserContextKeyedBaseFactory* factory = 117 static_cast<BrowserContextKeyedBaseFactory*>(destruction_order[i]); 118 factory->BrowserContextShutdown(context); 119 } 120 121#ifndef NDEBUG 122 // The context is now dead to the rest of the program. 123 dead_context_pointers_.insert(context); 124#endif 125 126 for (size_t i = 0; i < destruction_order.size(); i++) { 127 BrowserContextKeyedBaseFactory* factory = 128 static_cast<BrowserContextKeyedBaseFactory*>(destruction_order[i]); 129 factory->BrowserContextDestroyed(context); 130 } 131} 132 133scoped_ptr<base::CallbackList<void(content::BrowserContext*)>::Subscription> 134BrowserContextDependencyManager:: 135RegisterWillCreateBrowserContextServicesCallbackForTesting( 136 const base::Callback<void(content::BrowserContext*)>& callback) { 137 return will_create_browser_context_services_callbacks_.Add(callback); 138} 139 140#ifndef NDEBUG 141void BrowserContextDependencyManager::AssertBrowserContextWasntDestroyed( 142 content::BrowserContext* context) { 143 if (dead_context_pointers_.find(context) != dead_context_pointers_.end()) { 144 NOTREACHED() << "Attempted to access a BrowserContext that was ShutDown(). " 145 << "This is most likely a heap smasher in progress. After " 146 << "KeyedService::Shutdown() completes, your " 147 << "service MUST NOT refer to depended BrowserContext " 148 << "services again."; 149 } 150} 151 152void BrowserContextDependencyManager::MarkBrowserContextLiveForTesting( 153 content::BrowserContext* context) { 154 dead_context_pointers_.erase(context); 155} 156#endif 157 158// static 159BrowserContextDependencyManager* 160BrowserContextDependencyManager::GetInstance() { 161 return Singleton<BrowserContextDependencyManager>::get(); 162} 163 164BrowserContextDependencyManager::BrowserContextDependencyManager() {} 165 166BrowserContextDependencyManager::~BrowserContextDependencyManager() {} 167 168#ifndef NDEBUG 169namespace { 170 171std::string BrowserContextKeyedBaseFactoryGetNodeName(DependencyNode* node) { 172 return static_cast<BrowserContextKeyedBaseFactory*>(node)->name(); 173} 174 175} // namespace 176 177void BrowserContextDependencyManager::DumpBrowserContextDependencies( 178 content::BrowserContext* context) { 179 // Whenever we try to build a destruction ordering, we should also dump a 180 // dependency graph to "/path/to/context/context-dependencies.dot". 181 if (CommandLine::ForCurrentProcess()->HasSwitch( 182 kDumpBrowserContextDependencyGraphFlag)) { 183 base::FilePath dot_file = 184 context->GetPath().AppendASCII("browser-context-dependencies.dot"); 185 std::string contents = dependency_graph_.DumpAsGraphviz( 186 "BrowserContext", 187 base::Bind(&BrowserContextKeyedBaseFactoryGetNodeName)); 188 base::WriteFile(dot_file, contents.c_str(), contents.size()); 189 } 190} 191#endif // NDEBUG 192