diff options
| author | erg@chromium.org <erg@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-07-22 08:17:08 +0000 | 
|---|---|---|
| committer | erg@chromium.org <erg@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-07-22 08:17:08 +0000 | 
| commit | 50cd994072d4156e2fb1fafa948e58baf49b6f75 (patch) | |
| tree | 2e81a07124173dd46f503e0d2d93bf7030909e6f | |
| parent | 3240c4c924ad029cf1b06a74531cdfaa53d58718 (diff) | |
| download | chromium_src-50cd994072d4156e2fb1fafa948e58baf49b6f75.zip chromium_src-50cd994072d4156e2fb1fafa948e58baf49b6f75.tar.gz chromium_src-50cd994072d4156e2fb1fafa948e58baf49b6f75.tar.bz2 | |
Profiles: There should be an equivalent profile creation message to the ProfileDependencyManager for non-lazy initialization of services that need to be started with the profile.
BUG=77155
TEST=none
Review URL: http://codereview.chromium.org/7285014
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@93574 0039d316-1c4b-4281-b951-d872f2087c98
15 files changed, 118 insertions, 31 deletions
| diff --git a/chrome/browser/background/background_contents_service_factory.cc b/chrome/browser/background/background_contents_service_factory.cc index 51b5ffd..d9139dc 100644 --- a/chrome/browser/background/background_contents_service_factory.cc +++ b/chrome/browser/background/background_contents_service_factory.cc @@ -38,3 +38,11 @@ ProfileKeyedService* BackgroundContentsServiceFactory::BuildServiceInstanceFor(  bool BackgroundContentsServiceFactory::ServiceHasOwnInstanceInIncognito() {    return true;  } + +bool BackgroundContentsServiceFactory::ServiceIsCreatedWithProfile() { +  return true; +} + +bool BackgroundContentsServiceFactory::ServiceIsNULLWhileTesting() { +  return true; +} diff --git a/chrome/browser/background/background_contents_service_factory.h b/chrome/browser/background/background_contents_service_factory.h index 18973a4..131f617 100644 --- a/chrome/browser/background/background_contents_service_factory.h +++ b/chrome/browser/background/background_contents_service_factory.h @@ -32,6 +32,8 @@ class BackgroundContentsServiceFactory : public ProfileKeyedServiceFactory {        Profile* profile) const OVERRIDE;    // Use a separate background contents service for incognito.    virtual bool ServiceHasOwnInstanceInIncognito() OVERRIDE; +  virtual bool ServiceIsCreatedWithProfile() OVERRIDE; +  virtual bool ServiceIsNULLWhileTesting() OVERRIDE;  };  #endif  // CHROME_BROWSER_BACKGROUND_BACKGROUND_CONTENTS_SERVICE_FACTORY_H_ diff --git a/chrome/browser/profiles/profile.cc b/chrome/browser/profiles/profile.cc index 24a14d8..86f7a79 100644 --- a/chrome/browser/profiles/profile.cc +++ b/chrome/browser/profiles/profile.cc @@ -222,15 +222,11 @@ class OffTheRecordProfileImpl : public Profile,          prefs_(real_profile->GetOffTheRecordPrefs()),          ALLOW_THIS_IN_INITIALIZER_LIST(io_data_(this)),          start_time_(Time::Now()) { -#ifndef NDEBUG -    ProfileDependencyManager::GetInstance()->ProfileNowExists(this); -#endif -      extension_process_manager_.reset(ExtensionProcessManager::Create(this));      BrowserList::AddObserver(this); -    BackgroundContentsServiceFactory::GetForProfile(this); +    ProfileDependencyManager::GetInstance()->CreateProfileServices(this, false);      DCHECK(real_profile->GetPrefs()->GetBoolean(prefs::kIncognitoEnabled)); diff --git a/chrome/browser/profiles/profile_dependency_manager.cc b/chrome/browser/profiles/profile_dependency_manager.cc index e6479ad..154a332 100644 --- a/chrome/browser/profiles/profile_dependency_manager.cc +++ b/chrome/browser/profiles/profile_dependency_manager.cc @@ -8,12 +8,42 @@  #include <deque>  #include <iterator> +#include "chrome/browser/background/background_contents_service_factory.h"  #include "chrome/browser/profiles/profile_keyed_service.h"  #include "chrome/browser/profiles/profile_keyed_service_factory.h" +#include "chrome/browser/search_engines/template_url_service_factory.h" +#include "chrome/browser/sessions/session_service_factory.h" +#include "chrome/browser/sessions/tab_restore_service_factory.h"  #include "content/common/notification_service.h"  class Profile; +namespace { + +bool g_initialized = false; + +// This method gets the instance of each ServiceFactory. We do this so that +// each ServiceFactory initializes iteslf and registers its dependencies with +// the global PreferenceDependencyManager. We need to have a complete +// dependency graph when we create a profile so we can dispatch the profile +// creation message to the services that want to create their services at +// profile creation time. +// +// TODO(erg): This needs to be something else. I don't think putting every +// FooServiceFactory here will scale or is desireable long term. +void AssertFactoriesBuilt() { +  if (!g_initialized) { +    BackgroundContentsServiceFactory::GetInstance(); +    SessionServiceFactory::GetInstance(); +    TabRestoreServiceFactory::GetInstance(); +    TemplateURLServiceFactory::GetInstance(); + +    g_initialized = true; +  } +} + +}  // namespace +  void ProfileDependencyManager::AddComponent(      ProfileKeyedServiceFactory* component) {    all_components_.push_back(component); @@ -46,6 +76,33 @@ void ProfileDependencyManager::AddEdge(ProfileKeyedServiceFactory* depended,    destruction_order_.clear();  } +void ProfileDependencyManager::CreateProfileServices(Profile* profile, +                                                     bool is_testing_profile) { +#ifndef NDEBUG +  // Unmark |profile| as dead. This exists because of unit tests, which will +  // often have similar stack structures. 0xWhatever might be created, go out +  // of scope, and then a new Profile object might be created at 0xWhatever. +  dead_profile_pointers_.erase(profile); +#endif + +  AssertFactoriesBuilt(); + +  if (destruction_order_.empty()) +    BuildDestructionOrder(); + +  // Iterate in reverse destruction order for creation. +  for (std::vector<ProfileKeyedServiceFactory*>::reverse_iterator rit = +           destruction_order_.rbegin(); rit != destruction_order_.rend(); +       ++rit) { +    if (is_testing_profile && (*rit)->ServiceIsNULLWhileTesting()) { +      (*rit)->SetTestingFactory(profile, NULL); +    } else if ((*rit)->ServiceIsCreatedWithProfile()) { +      // Create the service. +      (*rit)->GetServiceForProfile(profile, true); +    } +  } +} +  void ProfileDependencyManager::DestroyProfileServices(Profile* profile) {    if (destruction_order_.empty())      BuildDestructionOrder(); @@ -67,10 +124,6 @@ void ProfileDependencyManager::DestroyProfileServices(Profile* profile) {  }  #ifndef NDEBUG -void ProfileDependencyManager::ProfileNowExists(Profile* profile) { -  dead_profile_pointers_.erase(profile); -} -  void ProfileDependencyManager::AssertProfileWasntDestroyed(Profile* profile) {    if (dead_profile_pointers_.find(profile) != dead_profile_pointers_.end()) {      NOTREACHED() << "Attempted to access a Profile that was ShutDown(). This " diff --git a/chrome/browser/profiles/profile_dependency_manager.h b/chrome/browser/profiles/profile_dependency_manager.h index b477bb7..6dc5c9f 100644 --- a/chrome/browser/profiles/profile_dependency_manager.h +++ b/chrome/browser/profiles/profile_dependency_manager.h @@ -31,6 +31,13 @@ class ProfileDependencyManager {    void AddEdge(ProfileKeyedServiceFactory* depended,                 ProfileKeyedServiceFactory* dependee); +  // Called by each Profile to alert us of its creation. Several services want +  // to be started when a profile is created. Testing configuration is also +  // done at this time. (If you want your ProfileKeyedService to be started +  // with the Profile, override ProfileKeyedServiceFactory:: +  // ServiceIsCreatedWithProfile() to return true.) +  void CreateProfileServices(Profile* profile, bool is_testing_profile); +    // Called by each Profile to alert us that we should destroy services    // associated with it.    // @@ -44,11 +51,6 @@ class ProfileDependencyManager {    void DestroyProfileServices(Profile* profile);  #ifndef NDEBUG -  // Unmark |profile| as dead. This exists because of unit tests, which will -  // often have similar stack structures. 0xWhatever might be created, go out -  // of scope, and then a new Profile object might be created at 0xWhatever. -  void ProfileNowExists(Profile* profile); -    // Debugging assertion called as part of GetServiceForProfile in debug    // mode. This will NOTREACHED() whenever the user is trying to access a stale    // Profile*. diff --git a/chrome/browser/profiles/profile_impl.cc b/chrome/browser/profiles/profile_impl.cc index 91165fc..b5c8c49 100644 --- a/chrome/browser/profiles/profile_impl.cc +++ b/chrome/browser/profiles/profile_impl.cc @@ -303,10 +303,6 @@ ProfileImpl::ProfileImpl(const FilePath& path,    DCHECK(!path.empty()) << "Using an empty path will attempt to write " <<                              "profile files to the root directory!"; -#ifndef NDEBUG -    ProfileDependencyManager::GetInstance()->ProfileNowExists(this); -#endif -    create_session_service_timer_.Start(        TimeDelta::FromMilliseconds(kCreateSessionServiceDelayMS), this,        &ProfileImpl::EnsureSessionServiceCreated); @@ -379,8 +375,6 @@ void ProfileImpl::DoFinalInit() {      g_browser_process->background_mode_manager()->RegisterProfile(this);  #endif -  BackgroundContentsServiceFactory::GetForProfile(this); -    extension_info_map_ = new ExtensionInfoMap();    InitRegisteredProtocolHandlers(); @@ -873,6 +867,8 @@ void ProfileImpl::OnPrefsLoaded(bool success) {        GetPath().AppendASCII(ExtensionService::kInstallDirectoryName),        GetExtensionPrefValueMap())); +  ProfileDependencyManager::GetInstance()->CreateProfileServices(this, false); +    DCHECK(!net_pref_observer_.get());    net_pref_observer_.reset(        new NetPrefObserver(prefs_.get(), GetPrerenderManager())); diff --git a/chrome/browser/profiles/profile_keyed_service_factory.cc b/chrome/browser/profiles/profile_keyed_service_factory.cc index e13fbf5..7ded5bf 100644 --- a/chrome/browser/profiles/profile_keyed_service_factory.cc +++ b/chrome/browser/profiles/profile_keyed_service_factory.cc @@ -107,6 +107,14 @@ bool ProfileKeyedServiceFactory::ServiceHasOwnInstanceInIncognito() {    return false;  } +bool ProfileKeyedServiceFactory::ServiceIsCreatedWithProfile() { +  return false; +} + +bool ProfileKeyedServiceFactory::ServiceIsNULLWhileTesting() { +  return false; +} +  void ProfileKeyedServiceFactory::ProfileShutdown(Profile* profile) {    std::map<Profile*, ProfileKeyedService*>::iterator it =        mapping_.find(profile); diff --git a/chrome/browser/profiles/profile_keyed_service_factory.h b/chrome/browser/profiles/profile_keyed_service_factory.h index f805db7..90c4308 100644 --- a/chrome/browser/profiles/profile_keyed_service_factory.h +++ b/chrome/browser/profiles/profile_keyed_service_factory.h @@ -75,6 +75,18 @@ class ProfileKeyedServiceFactory {    virtual bool ServiceRedirectedInIncognito();    virtual bool ServiceHasOwnInstanceInIncognito(); +  // By default, we create instances of a service lazily and wait until +  // GetForProfile() is called on our subclass. Some services need to be +  // created as soon as the Profile has been brought up. +  virtual bool ServiceIsCreatedWithProfile(); + +  // By default, TestingProfiles will be treated like normal profiles. You can +  // override this so that by default, the service associated with the +  // TestingProfile is NULL. (This is just a shortcut around +  // SetTestingFactory() to make sure our profiles don't directly refer to the +  // services they use.) +  virtual bool ServiceIsNULLWhileTesting(); +    // A helper object actually listens for notifications about Profile    // destruction, calculates the order in which things are destroyed and then    // does a two pass shutdown. diff --git a/chrome/browser/search_engines/template_url_service_factory.cc b/chrome/browser/search_engines/template_url_service_factory.cc index e344163..ddbe5a5 100644 --- a/chrome/browser/search_engines/template_url_service_factory.cc +++ b/chrome/browser/search_engines/template_url_service_factory.cc @@ -36,6 +36,10 @@ bool TemplateURLServiceFactory::ServiceRedirectedInIncognito() {    return true;  } +bool TemplateURLServiceFactory::ServiceIsNULLWhileTesting() { +  return true; +} +  void TemplateURLServiceFactory::ProfileShutdown(Profile* profile) {    // We shutdown AND destroy the TemplateURLService during this pass.    // TemplateURLService schedules a task on the WebDataService from its diff --git a/chrome/browser/search_engines/template_url_service_factory.h b/chrome/browser/search_engines/template_url_service_factory.h index 703d586..8d3dbe2 100644 --- a/chrome/browser/search_engines/template_url_service_factory.h +++ b/chrome/browser/search_engines/template_url_service_factory.h @@ -29,6 +29,7 @@ class TemplateURLServiceFactory : public ProfileKeyedServiceFactory {    // ProfileKeyedServiceFactory:    virtual ProfileKeyedService* BuildServiceInstanceFor(Profile* profile) const;    virtual bool ServiceRedirectedInIncognito(); +  virtual bool ServiceIsNULLWhileTesting();    virtual void ProfileShutdown(Profile* profile);    virtual void ProfileDestroyed(Profile* profile);  }; diff --git a/chrome/browser/sessions/session_service_factory.cc b/chrome/browser/sessions/session_service_factory.cc index 3a93dfb..8f1ba30 100644 --- a/chrome/browser/sessions/session_service_factory.cc +++ b/chrome/browser/sessions/session_service_factory.cc @@ -54,3 +54,11 @@ ProfileKeyedService* SessionServiceFactory::BuildServiceInstanceFor(    service->ResetFromCurrentBrowsers();    return service;  } + +bool SessionServiceFactory::ServiceIsCreatedWithProfile() { +  return true; +} + +bool SessionServiceFactory::ServiceIsNULLWhileTesting() { +  return true; +} diff --git a/chrome/browser/sessions/session_service_factory.h b/chrome/browser/sessions/session_service_factory.h index 213d2b6..eb46e653 100644 --- a/chrome/browser/sessions/session_service_factory.h +++ b/chrome/browser/sessions/session_service_factory.h @@ -55,6 +55,8 @@ class SessionServiceFactory : public ProfileKeyedServiceFactory {    // ProfileKeyedServiceFactory:    virtual ProfileKeyedService* BuildServiceInstanceFor(Profile* profile) const; +  virtual bool ServiceIsCreatedWithProfile(); +  virtual bool ServiceIsNULLWhileTesting();  };  #endif  // CHROME_BROWSER_SESSIONS_SESSION_SERVICE_FACTORY_H_ diff --git a/chrome/browser/sessions/tab_restore_service_factory.cc b/chrome/browser/sessions/tab_restore_service_factory.cc index 73f793f..b35ffab 100644 --- a/chrome/browser/sessions/tab_restore_service_factory.cc +++ b/chrome/browser/sessions/tab_restore_service_factory.cc @@ -38,3 +38,7 @@ ProfileKeyedService* TabRestoreServiceFactory::BuildServiceInstanceFor(    service = new TabRestoreService(profile);    return service;  } + +bool TabRestoreServiceFactory::ServiceIsNULLWhileTesting() { +  return true; +} diff --git a/chrome/browser/sessions/tab_restore_service_factory.h b/chrome/browser/sessions/tab_restore_service_factory.h index d20720f9..b46ea96 100644 --- a/chrome/browser/sessions/tab_restore_service_factory.h +++ b/chrome/browser/sessions/tab_restore_service_factory.h @@ -30,6 +30,7 @@ class TabRestoreServiceFactory : public ProfileKeyedServiceFactory {    // ProfileKeyedServiceFactory:    virtual ProfileKeyedService* BuildServiceInstanceFor(Profile* profile) const; +  virtual bool ServiceIsNULLWhileTesting();  };  #endif  // CHROME_BROWSER_SESSIONS_TAB_RESTORE_SERVICE_FACTORY_H_ diff --git a/chrome/test/testing_profile.cc b/chrome/test/testing_profile.cc index 4778a98..3a47753 100644 --- a/chrome/test/testing_profile.cc +++ b/chrome/test/testing_profile.cc @@ -13,7 +13,6 @@  #include "base/path_service.h"  #include "base/string_number_conversions.h"  #include "chrome/browser/autocomplete/autocomplete_classifier.h" -#include "chrome/browser/background/background_contents_service_factory.h"  #include "chrome/browser/bookmarks/bookmark_model.h"  #include "chrome/browser/browser_process.h"  #include "chrome/browser/content_settings/host_content_settings_map.h" @@ -38,8 +37,6 @@  #include "chrome/browser/search_engines/template_url_fetcher.h"  #include "chrome/browser/search_engines/template_url_service.h"  #include "chrome/browser/search_engines/template_url_service_factory.h" -#include "chrome/browser/sessions/session_service_factory.h" -#include "chrome/browser/sessions/tab_restore_service_factory.h"  #include "chrome/browser/sync/profile_sync_service_mock.h"  #include "chrome/browser/ui/find_bar/find_bar_state.h"  #include "chrome/browser/ui/webui/chrome_url_data_manager.h" @@ -129,9 +126,7 @@ TestingProfile::TestingProfile()        incognito_(false),        last_session_exited_cleanly_(true),        profile_dependency_manager_(ProfileDependencyManager::GetInstance()) { -#ifndef NDEBUG -    profile_dependency_manager_->ProfileNowExists(this); -#endif +  profile_dependency_manager_->CreateProfileServices(this, true);    if (!temp_dir_.CreateUniqueTempDir()) {      LOG(ERROR) << "Failed to create unique temporary directory."; @@ -158,13 +153,8 @@ TestingProfile::TestingProfile()    }    // Install profile keyed service factory hooks for dummy/test services -  BackgroundContentsServiceFactory::GetInstance()->SetTestingFactory( -      this, NULL);    DesktopNotificationServiceFactory::GetInstance()->SetTestingFactory(        this, CreateTestDesktopNotificationService); -  SessionServiceFactory::GetInstance()->SetTestingFactory(this, NULL); -  TabRestoreServiceFactory::GetInstance()->SetTestingFactory(this, NULL); -  TemplateURLServiceFactory::GetInstance()->SetTestingFactory(this, NULL);    NotificationService::current()->Notify(        chrome::NOTIFICATION_PROFILE_CREATED, | 
