browser_context_dependency_manager.cc revision a1401311d1ab56c4ed0a474bd38c108f75cb0cd9
1e62c1185bee05facc25d1d725434f517261d308bChris Lattner// Copyright 2014 The Chromium Authors. All rights reserved. 23da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman// Use of this source code is governed by a BSD-style license that can be 301d45827a1e512f3b19ba857772bf02baa3c0c4eJohn Criswell// found in the LICENSE file. 401d45827a1e512f3b19ba857772bf02baa3c0c4eJohn Criswell 53060910e290949a9ac5eda8726d030790c4d60ffChris Lattner#include "components/keyed_service/content/browser_context_dependency_manager.h" 63060910e290949a9ac5eda8726d030790c4d60ffChris Lattner 73da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman#include <algorithm> 801d45827a1e512f3b19ba857772bf02baa3c0c4eJohn Criswell#include <deque> 9e62c1185bee05facc25d1d725434f517261d308bChris Lattner#include <iterator> 1014d7c59491347a2f8f29e120fd75a4cad42f68e7Chris Lattner 1114d7c59491347a2f8f29e120fd75a4cad42f68e7Chris Lattner#include "base/bind.h" 12e62c1185bee05facc25d1d725434f517261d308bChris Lattner#include "base/debug/trace_event.h" 13e62c1185bee05facc25d1d725434f517261d308bChris Lattner#include "components/keyed_service/content/browser_context_keyed_base_factory.h" 14e62c1185bee05facc25d1d725434f517261d308bChris Lattner#include "content/public/browser/browser_context.h" 15e62c1185bee05facc25d1d725434f517261d308bChris Lattner 16e62c1185bee05facc25d1d725434f517261d308bChris Lattner#ifndef NDEBUG 17e62c1185bee05facc25d1d725434f517261d308bChris Lattner#include "base/command_line.h" 18099e198ae84c1a6cfe2a7c79ee9f47fa67caac8fChris Lattner#include "base/file_util.h" 193cc52ea33c0b96d1682f14fc45c45b57df0f39b6Michael J. Spencer 201a55180238dbcf11113f610aea010447e51f595bDaniel Dunbar// Dumps dependency information about our browser context keyed services 21e62c1185bee05facc25d1d725434f517261d308bChris Lattner// into a dot file in the browser context directory. 22028936ada14335bb04f377d46a6261dc4c66dafdJohn Criswellconst char kDumpBrowserContextDependencyGraphFlag[] = 23d0fde30ce850b78371fd1386338350591f9ff494Brian Gaeke "dump-browser-context-graph"; 241a55180238dbcf11113f610aea010447e51f595bDaniel Dunbar#endif // NDEBUG 2521870411d9c1807526b613d04c2ebae5a43c263bBob Wilson 267dda395004eb962cef1c1554b1e8b2ad069760e0Chris Lattnervoid BrowserContextDependencyManager::AddComponent( 277cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattner BrowserContextKeyedBaseFactory* component) { 287cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattner dependency_graph_.AddNode(component); 297cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattner} 307cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattner 317cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattnervoid BrowserContextDependencyManager::RemoveComponent( 327cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattner BrowserContextKeyedBaseFactory* component) { 3340f71134b9fef0ca06c516f033cc9403394a913cChris Lattner dependency_graph_.RemoveNode(component); 347cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattner} 357cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattner 367dda395004eb962cef1c1554b1e8b2ad069760e0Chris Lattnervoid BrowserContextDependencyManager::AddEdge( 371fca5ff62bb2ecb5bfc8974f4dbfc56e9d3ca721Chris Lattner BrowserContextKeyedBaseFactory* depended, 38e62c1185bee05facc25d1d725434f517261d308bChris Lattner BrowserContextKeyedBaseFactory* dependee) { 39e62c1185bee05facc25d1d725434f517261d308bChris Lattner dependency_graph_.AddEdge(depended, dependee); 40e62c1185bee05facc25d1d725434f517261d308bChris Lattner} 41e62c1185bee05facc25d1d725434f517261d308bChris Lattner 42e62c1185bee05facc25d1d725434f517261d308bChris Lattnervoid BrowserContextDependencyManager::RegisterProfilePrefsForServices( 43e3a1d054483d6e2551a43232f2c968fc7ce523f2Chris Lattner const content::BrowserContext* context, 44e62c1185bee05facc25d1d725434f517261d308bChris Lattner user_prefs::PrefRegistrySyncable* pref_registry) { 45e6c27de069225e1122c78385ad22a2ff656db8e6David Greene std::vector<DependencyNode*> construction_order; 46711e5d96aa648ebe96b09483d0775f3b16283e3dChris Lattner if (!dependency_graph_.GetConstructionOrder(&construction_order)) { 474afc509b7ffe2c4ea234dfd7af5105feb21685d9David Greene NOTREACHED(); 48e62c1185bee05facc25d1d725434f517261d308bChris Lattner } 498e9a9774eb12b5242f74b8ac5b20e0a938ec9c53Chris Lattner 50b45b3b3cd14faaf5a3ea5226af7e1e3cd653e6cbChris Lattner for (std::vector<DependencyNode*>::const_iterator it = 51b45b3b3cd14faaf5a3ea5226af7e1e3cd653e6cbChris Lattner construction_order.begin(); 52a1651900e1772b05afd2280308e9acc5a58cefb8Chris Lattner it != construction_order.end(); 53b45b3b3cd14faaf5a3ea5226af7e1e3cd653e6cbChris Lattner ++it) { 541dba7abdd77e19c230f0426825a5ae4879471dccChris Lattner BrowserContextKeyedBaseFactory* factory = 557cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattner static_cast<BrowserContextKeyedBaseFactory*>(*it); 567dda395004eb962cef1c1554b1e8b2ad069760e0Chris Lattner factory->RegisterProfilePrefsIfNecessaryForContext(context, pref_registry); 57e62c1185bee05facc25d1d725434f517261d308bChris Lattner } 587dda395004eb962cef1c1554b1e8b2ad069760e0Chris Lattner} 59293b13350c2fbae8a64b0b0beb440cb859968c8cBob Wilson 60e62c1185bee05facc25d1d725434f517261d308bChris Lattnervoid BrowserContextDependencyManager::CreateBrowserContextServices( 61e62c1185bee05facc25d1d725434f517261d308bChris Lattner content::BrowserContext* context) { 62e62c1185bee05facc25d1d725434f517261d308bChris Lattner DoCreateBrowserContextServices(context, false); 63e62c1185bee05facc25d1d725434f517261d308bChris Lattner} 64e62c1185bee05facc25d1d725434f517261d308bChris Lattner 65e62c1185bee05facc25d1d725434f517261d308bChris Lattnervoid BrowserContextDependencyManager::CreateBrowserContextServicesForTest( 66e62c1185bee05facc25d1d725434f517261d308bChris Lattner content::BrowserContext* context) { 67e62c1185bee05facc25d1d725434f517261d308bChris Lattner DoCreateBrowserContextServices(context, true); 6899ba1f7b8deaf2a296c98600dbf593754cbd43a2Chris Lattner} 691a55180238dbcf11113f610aea010447e51f595bDaniel Dunbar 707cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattnervoid BrowserContextDependencyManager::DoCreateBrowserContextServices( 717cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattner content::BrowserContext* context, 727cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattner bool is_testing_context) { 737cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattner TRACE_EVENT0( 747cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattner "browser", 757cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattner "BrowserContextDependencyManager::DoCreateBrowserContextServices") 767cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattner#ifndef NDEBUG 77e62c1185bee05facc25d1d725434f517261d308bChris Lattner MarkBrowserContextLiveForTesting(context); 78e62c1185bee05facc25d1d725434f517261d308bChris Lattner#endif 79e62c1185bee05facc25d1d725434f517261d308bChris Lattner 80e62c1185bee05facc25d1d725434f517261d308bChris Lattner std::vector<DependencyNode*> construction_order; 81e62c1185bee05facc25d1d725434f517261d308bChris Lattner if (!dependency_graph_.GetConstructionOrder(&construction_order)) { 82e62c1185bee05facc25d1d725434f517261d308bChris Lattner NOTREACHED(); 83e6c27de069225e1122c78385ad22a2ff656db8e6David Greene } 84e6c27de069225e1122c78385ad22a2ff656db8e6David Greene 85e6c27de069225e1122c78385ad22a2ff656db8e6David Greene#ifndef NDEBUG 86e8cf21e8e3db64dd49777d6bf6c867d47e9f5407David Greene DumpBrowserContextDependencies(context); 87e8cf21e8e3db64dd49777d6bf6c867d47e9f5407David Greene#endif 88e8cf21e8e3db64dd49777d6bf6c867d47e9f5407David Greene 894afc509b7ffe2c4ea234dfd7af5105feb21685d9David Greene for (size_t i = 0; i < construction_order.size(); i++) { 904afc509b7ffe2c4ea234dfd7af5105feb21685d9David Greene BrowserContextKeyedBaseFactory* factory = 914afc509b7ffe2c4ea234dfd7af5105feb21685d9David Greene static_cast<BrowserContextKeyedBaseFactory*>(construction_order[i]); 92e3a1d054483d6e2551a43232f2c968fc7ce523f2Chris Lattner if (is_testing_context && factory->ServiceIsNULLWhileTesting()) { 93e62c1185bee05facc25d1d725434f517261d308bChris Lattner factory->SetEmptyTestingFactory(context); 94e62c1185bee05facc25d1d725434f517261d308bChris Lattner } else if (factory->ServiceIsCreatedWithBrowserContext()) { 958e9a9774eb12b5242f74b8ac5b20e0a938ec9c53Chris Lattner // Create the service. 96b45b3b3cd14faaf5a3ea5226af7e1e3cd653e6cbChris Lattner factory->CreateServiceNow(context); 97b45b3b3cd14faaf5a3ea5226af7e1e3cd653e6cbChris Lattner } 98b45b3b3cd14faaf5a3ea5226af7e1e3cd653e6cbChris Lattner } 99b45b3b3cd14faaf5a3ea5226af7e1e3cd653e6cbChris Lattner} 100b45b3b3cd14faaf5a3ea5226af7e1e3cd653e6cbChris Lattner 101b45b3b3cd14faaf5a3ea5226af7e1e3cd653e6cbChris Lattnervoid BrowserContextDependencyManager::DestroyBrowserContextServices( 102b45b3b3cd14faaf5a3ea5226af7e1e3cd653e6cbChris Lattner content::BrowserContext* context) { 103e62c1185bee05facc25d1d725434f517261d308bChris Lattner std::vector<DependencyNode*> destruction_order; 1047cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattner if (!dependency_graph_.GetDestructionOrder(&destruction_order)) { 1057cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattner NOTREACHED(); 1067cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattner } 1077cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattner 1087cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattner#ifndef NDEBUG 1097cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattner DumpBrowserContextDependencies(context); 1107cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattner#endif 1117cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattner 1127cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattner for (size_t i = 0; i < destruction_order.size(); i++) { 11340f71134b9fef0ca06c516f033cc9403394a913cChris Lattner BrowserContextKeyedBaseFactory* factory = 1147cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattner static_cast<BrowserContextKeyedBaseFactory*>(destruction_order[i]); 115e62c1185bee05facc25d1d725434f517261d308bChris Lattner factory->BrowserContextShutdown(context); 116e62c1185bee05facc25d1d725434f517261d308bChris Lattner } 1171a55180238dbcf11113f610aea010447e51f595bDaniel Dunbar 118e62c1185bee05facc25d1d725434f517261d308bChris Lattner#ifndef NDEBUG 119e62c1185bee05facc25d1d725434f517261d308bChris Lattner // The context is now dead to the rest of the program. 120e62c1185bee05facc25d1d725434f517261d308bChris Lattner dead_context_pointers_.insert(context); 121e62c1185bee05facc25d1d725434f517261d308bChris Lattner#endif 12207278e48dc27d8ac64b5ff7ed6361536c2f38ea1Chris Lattner 12307278e48dc27d8ac64b5ff7ed6361536c2f38ea1Chris Lattner for (size_t i = 0; i < destruction_order.size(); i++) { 12407278e48dc27d8ac64b5ff7ed6361536c2f38ea1Chris Lattner BrowserContextKeyedBaseFactory* factory = 1251fca5ff62bb2ecb5bfc8974f4dbfc56e9d3ca721Chris Lattner static_cast<BrowserContextKeyedBaseFactory*>(destruction_order[i]); 1261fca5ff62bb2ecb5bfc8974f4dbfc56e9d3ca721Chris Lattner factory->BrowserContextDestroyed(context); 127ead87b671278379f92890fddd859a301bb68f462Reid Spencer } 128ead87b671278379f92890fddd859a301bb68f462Reid Spencer} 129ead87b671278379f92890fddd859a301bb68f462Reid Spencer 130ead87b671278379f92890fddd859a301bb68f462Reid Spencer#ifndef NDEBUG 131ead87b671278379f92890fddd859a301bb68f462Reid Spencervoid BrowserContextDependencyManager::AssertBrowserContextWasntDestroyed( 132ead87b671278379f92890fddd859a301bb68f462Reid Spencer content::BrowserContext* context) { 133ead87b671278379f92890fddd859a301bb68f462Reid Spencer if (dead_context_pointers_.find(context) != dead_context_pointers_.end()) { 134ead87b671278379f92890fddd859a301bb68f462Reid Spencer NOTREACHED() << "Attempted to access a BrowserContext that was ShutDown(). " 135ead87b671278379f92890fddd859a301bb68f462Reid Spencer << "This is most likely a heap smasher in progress. After " 136ead87b671278379f92890fddd859a301bb68f462Reid Spencer << "KeyedService::Shutdown() completes, your " 137e6c27de069225e1122c78385ad22a2ff656db8e6David Greene << "service MUST NOT refer to depended BrowserContext " 138e8cf21e8e3db64dd49777d6bf6c867d47e9f5407David Greene << "services again."; 1394afc509b7ffe2c4ea234dfd7af5105feb21685d9David Greene } 140ead87b671278379f92890fddd859a301bb68f462Reid Spencer} 141ead87b671278379f92890fddd859a301bb68f462Reid Spencer 142ead87b671278379f92890fddd859a301bb68f462Reid Spencervoid BrowserContextDependencyManager::MarkBrowserContextLiveForTesting( 143e62c1185bee05facc25d1d725434f517261d308bChris Lattner content::BrowserContext* context) { 14499ba1f7b8deaf2a296c98600dbf593754cbd43a2Chris Lattner dead_context_pointers_.erase(context); 1457cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattner} 1467cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattner#endif 1477cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattner 1487cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattner// static 149ead87b671278379f92890fddd859a301bb68f462Reid SpencerBrowserContextDependencyManager* 150ead87b671278379f92890fddd859a301bb68f462Reid SpencerBrowserContextDependencyManager::GetInstance() { 151ead87b671278379f92890fddd859a301bb68f462Reid Spencer return Singleton<BrowserContextDependencyManager>::get(); 152ead87b671278379f92890fddd859a301bb68f462Reid Spencer} 153ead87b671278379f92890fddd859a301bb68f462Reid Spencer 154ead87b671278379f92890fddd859a301bb68f462Reid SpencerBrowserContextDependencyManager::BrowserContextDependencyManager() {} 155ead87b671278379f92890fddd859a301bb68f462Reid Spencer 156ead87b671278379f92890fddd859a301bb68f462Reid SpencerBrowserContextDependencyManager::~BrowserContextDependencyManager() {} 157ead87b671278379f92890fddd859a301bb68f462Reid Spencer 158e62c1185bee05facc25d1d725434f517261d308bChris Lattner#ifndef NDEBUG 159e62c1185bee05facc25d1d725434f517261d308bChris Lattnernamespace { 16007278e48dc27d8ac64b5ff7ed6361536c2f38ea1Chris Lattner 161234b3ec8795e0661af56aa1d1a978a41d80686c5Misha Brukmanstd::string BrowserContextKeyedBaseFactoryGetNodeName(DependencyNode* node) { 162234b3ec8795e0661af56aa1d1a978a41d80686c5Misha Brukman return static_cast<BrowserContextKeyedBaseFactory*>(node)->name(); 16307278e48dc27d8ac64b5ff7ed6361536c2f38ea1Chris Lattner} 164e62c1185bee05facc25d1d725434f517261d308bChris Lattner 165e62c1185bee05facc25d1d725434f517261d308bChris Lattner} // namespace 166e62c1185bee05facc25d1d725434f517261d308bChris Lattner 1671002c0203450620594a85454c6a095ca94b87cb2Dan Gohmanvoid BrowserContextDependencyManager::DumpBrowserContextDependencies( 168e62c1185bee05facc25d1d725434f517261d308bChris Lattner content::BrowserContext* context) { 169e62c1185bee05facc25d1d725434f517261d308bChris Lattner // Whenever we try to build a destruction ordering, we should also dump a 170e62c1185bee05facc25d1d725434f517261d308bChris Lattner // dependency graph to "/path/to/context/context-dependencies.dot". 171ead87b671278379f92890fddd859a301bb68f462Reid Spencer if (CommandLine::ForCurrentProcess()->HasSwitch( 172ead87b671278379f92890fddd859a301bb68f462Reid Spencer kDumpBrowserContextDependencyGraphFlag)) { 173ead87b671278379f92890fddd859a301bb68f462Reid Spencer base::FilePath dot_file = 174ead87b671278379f92890fddd859a301bb68f462Reid Spencer context->GetPath().AppendASCII("browser-context-dependencies.dot"); 175ead87b671278379f92890fddd859a301bb68f462Reid Spencer std::string contents = dependency_graph_.DumpAsGraphviz( 176ead87b671278379f92890fddd859a301bb68f462Reid Spencer "BrowserContext", 177ead87b671278379f92890fddd859a301bb68f462Reid Spencer base::Bind(&BrowserContextKeyedBaseFactoryGetNodeName)); 178ead87b671278379f92890fddd859a301bb68f462Reid Spencer base::WriteFile(dot_file, contents.c_str(), contents.size()); 179ead87b671278379f92890fddd859a301bb68f462Reid Spencer } 180ead87b671278379f92890fddd859a301bb68f462Reid Spencer} 181e6c27de069225e1122c78385ad22a2ff656db8e6David Greene#endif // NDEBUG 182e8cf21e8e3db64dd49777d6bf6c867d47e9f5407David Greene