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