diff options
Diffstat (limited to 'chrome/browser/profiles')
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_ |