| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "components/keyed_service/core/dependency_manager.h" | 5 #include "components/keyed_service/core/dependency_manager.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/debug/dump_without_crashing.h" |
| 8 #include "base/logging.h" | 9 #include "base/logging.h" |
| 9 #include "base/supports_user_data.h" | 10 #include "base/supports_user_data.h" |
| 10 #include "components/keyed_service/core/keyed_service_base_factory.h" | 11 #include "components/keyed_service/core/keyed_service_base_factory.h" |
| 11 | 12 |
| 12 #ifndef NDEBUG | 13 #ifndef NDEBUG |
| 13 #include "base/files/file_path.h" | 14 #include "base/files/file_path.h" |
| 14 #include "base/files/file_util.h" | 15 #include "base/files/file_util.h" |
| 15 #endif // NDEBUG | 16 #endif // NDEBUG |
| 16 | 17 |
| 17 DependencyManager::DependencyManager() { | 18 DependencyManager::DependencyManager() { |
| (...skipping 25 matching lines...) Expand all Loading... |
| 43 | 44 |
| 44 for (auto* dependency_node : construction_order) { | 45 for (auto* dependency_node : construction_order) { |
| 45 KeyedServiceBaseFactory* factory = | 46 KeyedServiceBaseFactory* factory = |
| 46 static_cast<KeyedServiceBaseFactory*>(dependency_node); | 47 static_cast<KeyedServiceBaseFactory*>(dependency_node); |
| 47 factory->RegisterPrefsIfNecessaryForContext(context, pref_registry); | 48 factory->RegisterPrefsIfNecessaryForContext(context, pref_registry); |
| 48 } | 49 } |
| 49 } | 50 } |
| 50 | 51 |
| 51 void DependencyManager::CreateContextServices(base::SupportsUserData* context, | 52 void DependencyManager::CreateContextServices(base::SupportsUserData* context, |
| 52 bool is_testing_context) { | 53 bool is_testing_context) { |
| 53 #ifndef NDEBUG | 54 MarkContextLive(context); |
| 54 MarkContextLiveForTesting(context); | |
| 55 #endif | |
| 56 | 55 |
| 57 std::vector<DependencyNode*> construction_order; | 56 std::vector<DependencyNode*> construction_order; |
| 58 if (!dependency_graph_.GetConstructionOrder(&construction_order)) { | 57 if (!dependency_graph_.GetConstructionOrder(&construction_order)) { |
| 59 NOTREACHED(); | 58 NOTREACHED(); |
| 60 } | 59 } |
| 61 | 60 |
| 62 #ifndef NDEBUG | 61 #ifndef NDEBUG |
| 63 DumpContextDependencies(context); | 62 DumpContextDependencies(context); |
| 64 #endif | 63 #endif |
| 65 | 64 |
| (...skipping 19 matching lines...) Expand all Loading... |
| 85 #ifndef NDEBUG | 84 #ifndef NDEBUG |
| 86 DumpContextDependencies(context); | 85 DumpContextDependencies(context); |
| 87 #endif | 86 #endif |
| 88 | 87 |
| 89 for (auto* dependency_node : destruction_order) { | 88 for (auto* dependency_node : destruction_order) { |
| 90 KeyedServiceBaseFactory* factory = | 89 KeyedServiceBaseFactory* factory = |
| 91 static_cast<KeyedServiceBaseFactory*>(dependency_node); | 90 static_cast<KeyedServiceBaseFactory*>(dependency_node); |
| 92 factory->ContextShutdown(context); | 91 factory->ContextShutdown(context); |
| 93 } | 92 } |
| 94 | 93 |
| 95 #ifndef NDEBUG | |
| 96 // The context is now dead to the rest of the program. | 94 // The context is now dead to the rest of the program. |
| 97 dead_context_pointers_.insert(context); | 95 dead_context_pointers_.insert(context); |
| 98 #endif | |
| 99 | 96 |
| 100 for (auto* dependency_node : destruction_order) { | 97 for (auto* dependency_node : destruction_order) { |
| 101 KeyedServiceBaseFactory* factory = | 98 KeyedServiceBaseFactory* factory = |
| 102 static_cast<KeyedServiceBaseFactory*>(dependency_node); | 99 static_cast<KeyedServiceBaseFactory*>(dependency_node); |
| 103 factory->ContextDestroyed(context); | 100 factory->ContextDestroyed(context); |
| 104 } | 101 } |
| 105 } | 102 } |
| 106 | 103 |
| 107 #ifndef NDEBUG | |
| 108 void DependencyManager::AssertContextWasntDestroyed( | 104 void DependencyManager::AssertContextWasntDestroyed( |
| 109 base::SupportsUserData* context) { | 105 base::SupportsUserData* context) const { |
| 110 if (dead_context_pointers_.find(context) != dead_context_pointers_.end()) { | 106 if (dead_context_pointers_.find(context) != dead_context_pointers_.end()) { |
| 107 #if DCHECK_IS_ON() |
| 111 NOTREACHED() << "Attempted to access a context that was ShutDown(). " | 108 NOTREACHED() << "Attempted to access a context that was ShutDown(). " |
| 112 << "This is most likely a heap smasher in progress. After " | 109 << "This is most likely a heap smasher in progress. After " |
| 113 << "KeyedService::Shutdown() completes, your service MUST " | 110 << "KeyedService::Shutdown() completes, your service MUST " |
| 114 << "NOT refer to depended services again."; | 111 << "NOT refer to depended services again."; |
| 112 #else // DCHECK_IS_ON() |
| 113 // We want to see all possible use-after-destroy in production environment. |
| 114 base::debug::DumpWithoutCrashing(); |
| 115 #endif // DCHECK_IS_ON() |
| 115 } | 116 } |
| 116 } | 117 } |
| 117 | 118 |
| 118 void DependencyManager::MarkContextLiveForTesting( | 119 void DependencyManager::MarkContextLive(base::SupportsUserData* context) { |
| 119 base::SupportsUserData* context) { | |
| 120 dead_context_pointers_.erase(context); | 120 dead_context_pointers_.erase(context); |
| 121 } | 121 } |
| 122 | 122 |
| 123 #ifndef NDEBUG |
| 123 namespace { | 124 namespace { |
| 124 | 125 |
| 125 std::string KeyedServiceBaseFactoryGetNodeName(DependencyNode* node) { | 126 std::string KeyedServiceBaseFactoryGetNodeName(DependencyNode* node) { |
| 126 return static_cast<KeyedServiceBaseFactory*>(node)->name(); | 127 return static_cast<KeyedServiceBaseFactory*>(node)->name(); |
| 127 } | 128 } |
| 128 | 129 |
| 129 } // namespace | 130 } // namespace |
| 130 | 131 |
| 131 void DependencyManager::DumpDependenciesAsGraphviz( | 132 void DependencyManager::DumpDependenciesAsGraphviz( |
| 132 const std::string& top_level_name, | 133 const std::string& top_level_name, |
| 133 const base::FilePath& dot_file) const { | 134 const base::FilePath& dot_file) const { |
| 134 DCHECK(!dot_file.empty()); | 135 DCHECK(!dot_file.empty()); |
| 135 std::string contents = dependency_graph_.DumpAsGraphviz( | 136 std::string contents = dependency_graph_.DumpAsGraphviz( |
| 136 top_level_name, base::Bind(&KeyedServiceBaseFactoryGetNodeName)); | 137 top_level_name, base::Bind(&KeyedServiceBaseFactoryGetNodeName)); |
| 137 base::WriteFile(dot_file, contents.c_str(), contents.size()); | 138 base::WriteFile(dot_file, contents.c_str(), contents.size()); |
| 138 } | 139 } |
| 139 #endif // NDEBUG | 140 #endif // NDEBUG |
| OLD | NEW |