summaryrefslogtreecommitdiffstats
path: root/chrome/browser/profiles
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser/profiles')
-rw-r--r--chrome/browser/profiles/profile_dependency_manager.cc71
-rw-r--r--chrome/browser/profiles/profile_dependency_manager.h8
-rw-r--r--chrome/browser/profiles/profile_dependency_manager_unittest.cc4
-rw-r--r--chrome/browser/profiles/profile_keyed_service_factory.cc8
-rw-r--r--chrome/browser/profiles/profile_keyed_service_factory.h16
5 files changed, 98 insertions, 9 deletions
diff --git a/chrome/browser/profiles/profile_dependency_manager.cc b/chrome/browser/profiles/profile_dependency_manager.cc
index d6617e5..0d53c7b 100644
--- a/chrome/browser/profiles/profile_dependency_manager.cc
+++ b/chrome/browser/profiles/profile_dependency_manager.cc
@@ -32,6 +32,12 @@
#include "chrome/browser/ui/global_error_service_factory.h"
#include "chrome/browser/ui/webui/ntp/ntp_resource_cache_factory.h"
+#ifndef NDEBUG
+#include "base/command_line.h"
+#include "base/file_util.h"
+#include "chrome/common/chrome_switches.h"
+#endif
+
class Profile;
void ProfileDependencyManager::AddComponent(
@@ -78,7 +84,7 @@ void ProfileDependencyManager::CreateProfileServices(Profile* profile,
AssertFactoriesBuilt();
if (destruction_order_.empty())
- BuildDestructionOrder();
+ BuildDestructionOrder(profile);
// Iterate in reverse destruction order for creation.
for (std::vector<ProfileKeyedServiceFactory*>::reverse_iterator rit =
@@ -101,7 +107,7 @@ void ProfileDependencyManager::CreateProfileServices(Profile* profile,
void ProfileDependencyManager::DestroyProfileServices(Profile* profile) {
if (destruction_order_.empty())
- BuildDestructionOrder();
+ BuildDestructionOrder(profile);
for (std::vector<ProfileKeyedServiceFactory*>::const_iterator it =
destruction_order_.begin(); it != destruction_order_.end(); ++it) {
@@ -182,7 +188,19 @@ void ProfileDependencyManager::AssertFactoriesBuilt() {
built_factories_ = true;
}
-void ProfileDependencyManager::BuildDestructionOrder() {
+void ProfileDependencyManager::BuildDestructionOrder(Profile* profile) {
+#if !defined(NDEBUG)
+ // Whenever we try to build a destruction ordering, we should also dump a
+ // dependency graph to "/path/to/profile/profile-dependencies.dot".
+ if (CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kDumpProfileDependencyGraph)) {
+ FilePath dot_file =
+ profile->GetPath().AppendASCII("profile-dependencies.dot");
+ std::string contents = DumpGraphvizDependency();
+ file_util::WriteFile(dot_file, contents.c_str(), contents.size());
+ }
+#endif
+
// Step 1: Build a set of nodes with no incoming edges.
std::deque<ProfileKeyedServiceFactory*> queue;
std::copy(all_components_.begin(),
@@ -233,3 +251,50 @@ void ProfileDependencyManager::BuildDestructionOrder() {
std::reverse(output.begin(), output.end());
destruction_order_ = output;
}
+
+#if !defined(NDEBUG)
+
+std::string ProfileDependencyManager::DumpGraphvizDependency() {
+ std::string result("digraph {\n");
+
+ // Make a copy of all components.
+ std::deque<ProfileKeyedServiceFactory*> components;
+ std::copy(all_components_.begin(),
+ all_components_.end(),
+ std::back_inserter(components));
+
+ // State all dependencies and remove |second| so we don't generate an
+ // implicit dependency on the Profile hard coded node.
+ std::deque<ProfileKeyedServiceFactory*>::iterator components_end =
+ components.end();
+ result.append(" /* Dependencies */\n");
+ for (EdgeMap::const_iterator it = edges_.begin(); it != edges_.end(); ++it) {
+ result.append(" ");
+ result.append(it->second->name());
+ result.append(" -> ");
+ result.append(it->first->name());
+ result.append(";\n");
+
+ components_end = std::remove(components.begin(), components_end,
+ it->second);
+ }
+ components.erase(components_end, components.end());
+
+ // Every node that doesn't depend on anything else will implicitly depend on
+ // the Profile.
+ result.append("\n /* Toplevel attachments */\n");
+ for (std::deque<ProfileKeyedServiceFactory*>::const_iterator it =
+ components.begin(); it != components.end(); ++it) {
+ result.append(" ");
+ result.append((*it)->name());
+ result.append(" -> Profile;\n");
+ }
+
+ result.append("\n /* Toplevel profile */\n");
+ result.append(" Profile [shape=box];\n");
+
+ result.append("}\n");
+ return result;
+}
+
+#endif
diff --git a/chrome/browser/profiles/profile_dependency_manager.h b/chrome/browser/profiles/profile_dependency_manager.h
index b0b3ec9..3ad0634 100644
--- a/chrome/browser/profiles/profile_dependency_manager.h
+++ b/chrome/browser/profiles/profile_dependency_manager.h
@@ -12,6 +12,7 @@
#ifndef NDEBUG
#include <set>
+#include <string>
#endif
class Profile;
@@ -75,7 +76,12 @@ class ProfileDependencyManager {
// Using the dependency graph defined in |edges_|, fills |destruction_order_|
// so that Observe() can notify each ProfileKeyedServiceFactory in order.
- void BuildDestructionOrder();
+ void BuildDestructionOrder(Profile* profile);
+
+#ifndef NDEBUG
+ // Creates a dot file with our dependency information.
+ std::string DumpGraphvizDependency();
+#endif
std::vector<ProfileKeyedServiceFactory*> all_components_;
diff --git a/chrome/browser/profiles/profile_dependency_manager_unittest.cc b/chrome/browser/profiles/profile_dependency_manager_unittest.cc
index 3b99963..3a113ea 100644
--- a/chrome/browser/profiles/profile_dependency_manager_unittest.cc
+++ b/chrome/browser/profiles/profile_dependency_manager_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -36,7 +36,7 @@ class TestService : public ProfileKeyedServiceFactory {
TestService(const std::string& name,
std::vector<std::string>* fill_on_shutdown,
ProfileDependencyManager* manager)
- : ProfileKeyedServiceFactory(manager),
+ : ProfileKeyedServiceFactory("TestService", manager),
name_(name),
fill_on_shutdown_(fill_on_shutdown) {
}
diff --git a/chrome/browser/profiles/profile_keyed_service_factory.cc b/chrome/browser/profiles/profile_keyed_service_factory.cc
index 886308d..88b187e 100644
--- a/chrome/browser/profiles/profile_keyed_service_factory.cc
+++ b/chrome/browser/profiles/profile_keyed_service_factory.cc
@@ -72,8 +72,12 @@ void ProfileKeyedServiceFactory::RegisterUserPrefsOnProfile(Profile* profile) {
}
ProfileKeyedServiceFactory::ProfileKeyedServiceFactory(
- ProfileDependencyManager* manager)
- : dependency_manager_(manager) {
+ const char* name, ProfileDependencyManager* manager)
+ : dependency_manager_(manager)
+#ifndef NDEBUG
+ , service_name_(name)
+#endif
+{
dependency_manager_->AddComponent(this);
}
diff --git a/chrome/browser/profiles/profile_keyed_service_factory.h b/chrome/browser/profiles/profile_keyed_service_factory.h
index ab5eceb..30c99c1 100644
--- a/chrome/browser/profiles/profile_keyed_service_factory.h
+++ b/chrome/browser/profiles/profile_keyed_service_factory.h
@@ -46,6 +46,11 @@ class ProfileKeyedServiceFactory {
// attached to a single |profile|.
void RegisterUserPrefsOnProfile(Profile* profile);
+#ifndef NDEBUG
+ // Returns our name. We don't keep track of this in release mode.
+ const char* name() const { return service_name_; }
+#endif
+
protected:
// ProfileKeyedServiceFactories must communicate with a
// ProfileDependencyManager. For all non-test code, write your subclass
@@ -53,9 +58,11 @@ class ProfileKeyedServiceFactory {
//
// MyServiceFactory::MyServiceFactory()
// : ProfileKeyedServiceFactory(
+ // "MyService",
// ProfileDependencyManager::GetInstance())
// {}
- explicit ProfileKeyedServiceFactory(ProfileDependencyManager* manager);
+ explicit ProfileKeyedServiceFactory(const char* name,
+ ProfileDependencyManager* manager);
virtual ~ProfileKeyedServiceFactory();
// Common implementation that maps |profile| to some service object. Deals
@@ -132,6 +139,13 @@ class ProfileKeyedServiceFactory {
// this will always be ProfileDependencyManager::GetInstance(), but unit
// tests will want to use their own copy.
ProfileDependencyManager* dependency_manager_;
+
+#if !defined(NDEBUG)
+ // A static string passed in to our constructor. Should be unique across all
+ // services. This is used only for debugging in debug mode. (We can print
+ // pretty graphs with GraphViz with this information.)
+ const char* service_name_;
+#endif
};
#endif // CHROME_BROWSER_PROFILES_PROFILE_KEYED_SERVICE_FACTORY_H_