diff options
author | sail@chromium.org <sail@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-06-27 19:43:39 +0000 |
---|---|---|
committer | sail@chromium.org <sail@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-06-27 19:43:39 +0000 |
commit | dee810ea1b9b58410399bbc42637ffba79fde1c6 (patch) | |
tree | aaeccd263306f734357cf557aba40f3113c5e4cd | |
parent | c8f5778ea91dc9c5c21e1007661237c6e26399ad (diff) | |
download | chromium_src-dee810ea1b9b58410399bbc42637ffba79fde1c6.zip chromium_src-dee810ea1b9b58410399bbc42637ffba79fde1c6.tar.gz chromium_src-dee810ea1b9b58410399bbc42637ffba79fde1c6.tar.bz2 |
Store profile avatar to preferences
This change adds a preference to store avatar icons.
For this change I extended the idea of kProfileAvatarIconMap pref into a full blown class. The class is responsible for mantaining a list of sorted profiles that can be displayed without having to load profiles from disk.
Once this is chcked in there are several TODOs:
- remove the ProfileManager::GetNumberOfProfiles(), etc... functions that I added earlier
- add UI to customize the avatar icon
- create a single instance of the new ProfileInfoCache object some where. Maybe from ProfileManager?
BUG=
TEST=
Review URL: http://codereview.chromium.org/7155015
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@90622 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/app/theme/theme_resources.grd | 5 | ||||
-rw-r--r-- | chrome/browser/prefs/browser_prefs.cc | 2 | ||||
-rw-r--r-- | chrome/browser/profiles/profile_info_cache.cc | 209 | ||||
-rw-r--r-- | chrome/browser/profiles/profile_info_cache.h | 71 | ||||
-rw-r--r-- | chrome/browser/profiles/profile_info_cache_unittest.cc | 99 | ||||
-rw-r--r-- | chrome/chrome_browser.gypi | 2 | ||||
-rw-r--r-- | chrome/chrome_tests.gypi | 1 | ||||
-rw-r--r-- | chrome/common/pref_names.cc | 5 | ||||
-rw-r--r-- | chrome/common/pref_names.h | 1 |
9 files changed, 394 insertions, 1 deletions
diff --git a/chrome/app/theme/theme_resources.grd b/chrome/app/theme/theme_resources.grd index 83dd3b3..df9c012 100644 --- a/chrome/app/theme/theme_resources.grd +++ b/chrome/app/theme/theme_resources.grd @@ -217,7 +217,10 @@ <!-- NOTE: product_logo_*.* files beyond what's listed above are referenced by installer code; don't remove them unless you know what you're doing! --> - <include name="IDR_PROFILE_AVATAR_1" file="avatar_cupcake.png" type="BINDATA" /> + <include name="IDR_PROFILE_AVATAR_0" file="avatar_cupcake.png" type="BINDATA" /> + <include name="IDR_PROFILE_AVATAR_1" file="avatar_beaker.png" type="BINDATA" /> + <include name="IDR_PROFILE_AVATAR_2" file="avatar_bee.png" type="BINDATA" /> + <include name="IDR_PROFILE_AVATAR_3" file="avatar_briefcase.png" type="BINDATA" /> <include name="IDR_RESTORE_BUTTON_MASK" file="restore_button_mask.png" type="BINDATA" /> <include name="IDR_SAD_FAVICON" file="sadfavicon.png" type="BINDATA" /> <include name="IDR_SAD_TAB" file="sadtab.png" type="BINDATA" /> diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc index 1d9f0ed..4bc2f817 100644 --- a/chrome/browser/prefs/browser_prefs.cc +++ b/chrome/browser/prefs/browser_prefs.cc @@ -38,6 +38,7 @@ #include "chrome/browser/prefs/session_startup_pref.h" #include "chrome/browser/printing/print_job_manager.h" #include "chrome/browser/profiles/profile_impl.h" +#include "chrome/browser/profiles/profile_info_cache.h" #include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/renderer_host/web_cache_manager.h" #include "chrome/browser/safe_browsing/safe_browsing_service.h" @@ -110,6 +111,7 @@ void RegisterLocalState(PrefService* local_state) { NotificationUIManager::RegisterPrefs(local_state); PrefProxyConfigService::RegisterPrefs(local_state); policy::CloudPolicySubsystem::RegisterPrefs(local_state); + ProfileInfoCache::RegisterPrefs(local_state); ProfileManager::RegisterPrefs(local_state); #if defined(OS_CHROMEOS) chromeos::AudioMixerAlsa::RegisterPrefs(local_state); diff --git a/chrome/browser/profiles/profile_info_cache.cc b/chrome/browser/profiles/profile_info_cache.cc new file mode 100644 index 0000000..4a71e02 --- /dev/null +++ b/chrome/browser/profiles/profile_info_cache.cc @@ -0,0 +1,209 @@ +// Copyright (c) 2011 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. + +#include "chrome/browser/profiles/profile_info_cache.h" + +#include "base/logging.h" +#include "base/memory/scoped_ptr.h" +#include "base/string_number_conversions.h" +#include "base/stringprintf.h" +#include "base/utf_string_conversions.h" +#include "base/values.h" +#include "chrome/browser/prefs/pref_service.h" +#include "chrome/browser/prefs/scoped_user_pref_update.h" +#include "chrome/common/pref_names.h" +#include "grit/theme_resources.h" +#include "ui/base/resource/resource_bundle.h" + +namespace { + +const char kNameKey[] = "name"; +const char kAvatarIconKey[] = "avatar_icon"; +const char kDefaultUrlPrefix[] = "chrome://theme/IDR_PROFILE_AVATAR_"; + +const int kDefaultAvatarIconResources[] = { + IDR_PROFILE_AVATAR_0, + IDR_PROFILE_AVATAR_1, + IDR_PROFILE_AVATAR_2, + IDR_PROFILE_AVATAR_3, +}; + +const int kDefaultAvatarIconsCount = arraysize(kDefaultAvatarIconResources); + +// Checks if the given URL points to one of the default avatar icons. if it is, +// returns true and its index through |icon_index|. If not, returns false. +bool IsDefaultAvatarIconUrl(const std::string& url, size_t* icon_index) { + DCHECK(icon_index); + if (url.find(kDefaultUrlPrefix) != 0) + return false; + + int int_value = -1; + if (base::StringToInt(url.begin() + strlen(kDefaultUrlPrefix), + url.end(), + &int_value)) { + if (int_value < 0 || int_value >= kDefaultAvatarIconsCount) + return false; + *icon_index = int_value; + return true; + } + + return false; +} + +// Returns a URL for the default avatar icon with specified index. +std::string GetDefaultAvatarIconUrl(int icon_index) { + DCHECK_LT(icon_index, kDefaultAvatarIconsCount); + return StringPrintf("%s%d", kDefaultUrlPrefix, icon_index); +} + +} // namespace + +ProfileInfoCache::ProfileInfoCache(PrefService* prefs, + const FilePath& user_data_dir) + : prefs_(prefs), + user_data_dir_(user_data_dir) { + // Populate the cache + const DictionaryValue* cache = + prefs_->GetDictionary(prefs::kProfileInfoCache); + for (DictionaryValue::key_iterator it = cache->begin_keys(); + it != cache->end_keys(); ++it) { + std::string key = *it; + DictionaryValue* info = NULL; + cache->GetDictionary(key, &info); + string16 name; + info->GetString(kNameKey, &name); + sorted_keys_.insert(FindPositionForProfile(key, name), key); + } +} + +ProfileInfoCache::~ProfileInfoCache() { +} + +void ProfileInfoCache::AddProfileToCache(const FilePath& profile_path, + const string16& name, + size_t icon_index) { + std::string key = CacheKeyFromProfilePath(profile_path); + DictionaryPrefUpdate update(prefs_, prefs::kProfileInfoCache); + DictionaryValue* cache = update.Get(); + + scoped_ptr<DictionaryValue> info(new DictionaryValue); + info->SetString(kNameKey, name); + info->SetString(kAvatarIconKey, GetDefaultAvatarIconUrl(icon_index)); + cache->Set(key, info.release()); + + sorted_keys_.insert(FindPositionForProfile(key, name), key); +} + +void ProfileInfoCache::DeleteProfileFromCache(const FilePath& profile_path) { + DictionaryPrefUpdate update(prefs_, prefs::kProfileInfoCache); + DictionaryValue* cache = update.Get(); + + std::string key = CacheKeyFromProfilePath(profile_path); + cache->Remove(key, NULL); + sorted_keys_.erase(std::find(sorted_keys_.begin(), sorted_keys_.end(), key)); +} + +size_t ProfileInfoCache::GetNumberOfProfiles() const { + return sorted_keys_.size(); +} + +string16 ProfileInfoCache::GetNameOfProfileAtIndex(size_t index) const { + string16 name; + GetInfoForProfileAtIndex(index)->GetString(kNameKey, &name); + return name; +} + +FilePath ProfileInfoCache::GetPathOfProfileAtIndex(size_t index) const { + FilePath::StringType base_name; +#if defined(OS_POSIX) + base_name = sorted_keys_[index]; +#elif defined(OS_WIN) + base_name = ASCIIToWide(sorted_keys_[index]); +#endif + return user_data_dir_.Append(base_name); +} + +const gfx::Image& ProfileInfoCache::GetAvatarIconOfProfileAtIndex( + size_t index) const { + std::string icon_url; + GetInfoForProfileAtIndex(index)->GetString(kAvatarIconKey, &icon_url); + size_t icon_index = 0; + if (IsDefaultAvatarIconUrl(icon_url, &icon_index)) { + int resource_id = GetDefaultAvatarIconResourceIDAtIndex(icon_index); + return ResourceBundle::GetSharedInstance().GetImageNamed(resource_id); + } + + DLOG(WARNING) << "Unknown avatar icon: " << icon_url; + return ResourceBundle::GetSharedInstance().GetImageNamed( + GetDefaultAvatarIconResourceIDAtIndex(0)); +} + +void ProfileInfoCache::SetNameOfProfileAtIndex(size_t index, + const string16& name) { + scoped_ptr<DictionaryValue> info(GetInfoForProfileAtIndex(index)->DeepCopy()); + info->SetString(kNameKey, name); + // This takes ownership of |info|. + SetInfoForProfileAtIndex(index, info.release()); +} + +void ProfileInfoCache::SetAvatarIconOfProfileAtIndex(size_t index, + size_t icon_index) { + scoped_ptr<DictionaryValue> info(GetInfoForProfileAtIndex(index)->DeepCopy()); + info->SetString(kAvatarIconKey, GetDefaultAvatarIconUrl(icon_index)); + // This takes ownership of |info|. + SetInfoForProfileAtIndex(index, info.release()); +} + +size_t ProfileInfoCache::GetDefaultAvatarIconCount() { + return kDefaultAvatarIconsCount; +} + +int ProfileInfoCache::GetDefaultAvatarIconResourceIDAtIndex(size_t index) { + DCHECK_LT(index, GetDefaultAvatarIconCount()); + return kDefaultAvatarIconResources[index]; +} + +const DictionaryValue* ProfileInfoCache::GetInfoForProfileAtIndex( + size_t index) const { + DCHECK_LT(index, GetNumberOfProfiles()); + const DictionaryValue* cache = + prefs_->GetDictionary(prefs::kProfileInfoCache); + DictionaryValue* info = NULL; + cache->GetDictionary(sorted_keys_[index], &info); + return info; +} + +void ProfileInfoCache::SetInfoForProfileAtIndex(size_t index, + DictionaryValue* info) { + DictionaryPrefUpdate update(prefs_, prefs::kProfileInfoCache); + DictionaryValue* cache = update.Get(); + cache->Set(sorted_keys_[index], info); +} + +std::string ProfileInfoCache::CacheKeyFromProfilePath( + const FilePath& profile_path) const { + DCHECK(user_data_dir_ == profile_path.DirName()); + FilePath base_name = profile_path.BaseName(); + return base_name.MaybeAsASCII(); +} + +std::vector<std::string>::iterator ProfileInfoCache::FindPositionForProfile( + std::string search_key, + const string16& search_name) { + for (size_t i = 0; i < GetNumberOfProfiles(); ++i) { + int name_compare = search_name.compare(GetNameOfProfileAtIndex(i)); + if (name_compare < 0) + return sorted_keys_.begin() + i; + if (name_compare == 0) { + int key_compare = search_key.compare(sorted_keys_[i]); + if (key_compare < 0) + return sorted_keys_.begin() + i; + } + } + return sorted_keys_.end(); +} + +void ProfileInfoCache::RegisterPrefs(PrefService* prefs) { + prefs->RegisterDictionaryPref(prefs::kProfileInfoCache); +} diff --git a/chrome/browser/profiles/profile_info_cache.h b/chrome/browser/profiles/profile_info_cache.h new file mode 100644 index 0000000..e6ca12a --- /dev/null +++ b/chrome/browser/profiles/profile_info_cache.h @@ -0,0 +1,71 @@ +// Copyright (c) 2011 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. + +#ifndef CHROME_BROWSER_PROFILES_PROFILE_INFO_CACHE_H_ +#define CHROME_BROWSER_PROFILES_PROFILE_INFO_CACHE_H_ +#pragma once + +#include <string> +#include <vector> + +#include "base/basictypes.h" +#include "base/file_path.h" +#include "base/string16.h" + +namespace gfx { +class Image; +} + +class DictionaryValue; +class PrefService; + + +// This class saves various information about profiles to local preferences. +// This cache can be used to display a list of profiles without having to +// actually load the profiles from disk. +class ProfileInfoCache { + public: + ProfileInfoCache(PrefService* prefs, const FilePath& user_data_dir); + ~ProfileInfoCache(); + + void AddProfileToCache(const FilePath& profile_path, + const string16& name, + size_t icon_index); + void DeleteProfileFromCache(const FilePath& profile_path); + + size_t GetNumberOfProfiles() const; + string16 GetNameOfProfileAtIndex(size_t index) const; + FilePath GetPathOfProfileAtIndex(size_t index) const; + const gfx::Image& GetAvatarIconOfProfileAtIndex(size_t index) const; + + void SetNameOfProfileAtIndex(size_t index, const string16& name); + void SetAvatarIconOfProfileAtIndex(size_t index, size_t icon_index); + + // Gets the number of default avatar icons that exist. + static size_t GetDefaultAvatarIconCount(); + // Gets the resource ID of the default avatar icon at |index|. + static int GetDefaultAvatarIconResourceIDAtIndex(size_t index); + + // Register cache related preferences in Local State. + static void RegisterPrefs(PrefService* prefs); + + private: + const DictionaryValue* GetInfoForProfileAtIndex(size_t index) const; + // Saves the profile info to a cache and takes ownership of |info|. + // Currently the only information that is cached is the profiles name and + // avatar icon. + void SetInfoForProfileAtIndex(size_t index, DictionaryValue* info); + std::string CacheKeyFromProfilePath(const FilePath& profile_path) const; + std::vector<std::string>::iterator FindPositionForProfile( + std::string search_key, + const string16& search_name); + + PrefService* prefs_; + std::vector<std::string> sorted_keys_; + FilePath user_data_dir_; + + DISALLOW_COPY_AND_ASSIGN(ProfileInfoCache); +}; + +#endif // CHROME_BROWSER_PROFILES_PROFILE_INFO_CACHE_H_ diff --git a/chrome/browser/profiles/profile_info_cache_unittest.cc b/chrome/browser/profiles/profile_info_cache_unittest.cc new file mode 100644 index 0000000..b270566 --- /dev/null +++ b/chrome/browser/profiles/profile_info_cache_unittest.cc @@ -0,0 +1,99 @@ +// Copyright (c) 2011 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. + +#include "chrome/browser/profiles/profile_info_cache.h" + +#include "base/stringprintf.h" +#include "base/utf_string_conversions.h" +#include "chrome/test/testing_browser_process_test.h" +#include "chrome/test/testing_pref_service.h" +#include "third_party/skia/include/core/SkBitmap.h" +#include "ui/base/resource/resource_bundle.h" +#include "ui/gfx/image/image.h" + +namespace { + +class ProfileInfoCacheUnittests : public TestingBrowserProcessTest { + protected: + ProfileInfoCacheUnittests() : local_state_(testing_browser_process_.get()) { + cache_.reset(new ProfileInfoCache(local_state_.Get(), GetUserDataDir())); + } + + FilePath GetUserDataDir() { + return StringToFilePath("usr").Append(StringToFilePath("profile")); + } + + FilePath StringToFilePath(std::string string_path) { +#if defined(OS_POSIX) + return FilePath(string_path); +#elif defined(OS_WIN) + return FilePath(ASCIIToWide(string_path)); +#endif + } + + scoped_ptr<ProfileInfoCache> cache_; + ScopedTestingLocalState local_state_; +}; + +TEST_F(ProfileInfoCacheUnittests, AddProfiles) { + EXPECT_EQ(0u, cache_->GetNumberOfProfiles()); + + for (uint32 i = 0; i < 4; ++i) { + std::string base_name = StringPrintf("path_%ud", i); + FilePath profile_path = + GetUserDataDir().Append(StringToFilePath(base_name)); + string16 profile_name = ASCIIToUTF16(StringPrintf("name_%ud", i)); + const SkBitmap& icon = ResourceBundle::GetSharedInstance().GetImageNamed( + ProfileInfoCache::GetDefaultAvatarIconResourceIDAtIndex(i)); + + cache_->AddProfileToCache(profile_path, profile_name, 0); + + EXPECT_EQ(i + 1, cache_->GetNumberOfProfiles()); + EXPECT_EQ(profile_name, cache_->GetNameOfProfileAtIndex(i)); + EXPECT_EQ(profile_path, cache_->GetPathOfProfileAtIndex(i)); + const SkBitmap& actual_icon = cache_->GetAvatarIconOfProfileAtIndex(i); + EXPECT_EQ(icon.width(), actual_icon.width()); + EXPECT_EQ(icon.height(), actual_icon.height()); + } +} + +TEST_F(ProfileInfoCacheUnittests, DeleteProfile) { + EXPECT_EQ(0u, cache_->GetNumberOfProfiles()); + + FilePath path_1 = GetUserDataDir().Append(StringToFilePath("path_1")); + cache_->AddProfileToCache(path_1, ASCIIToUTF16("name_1"), + 0); + EXPECT_EQ(1u, cache_->GetNumberOfProfiles()); + + FilePath path_2 = GetUserDataDir().Append(StringToFilePath("path_2")); + string16 name_2 = ASCIIToUTF16("name_2"); + cache_->AddProfileToCache(path_2, name_2, 0); + EXPECT_EQ(2u, cache_->GetNumberOfProfiles()); + + cache_->DeleteProfileFromCache(path_1); + EXPECT_EQ(1u, cache_->GetNumberOfProfiles()); + EXPECT_EQ(name_2, cache_->GetNameOfProfileAtIndex(0)); + + cache_->DeleteProfileFromCache(path_2); + EXPECT_EQ(0u, cache_->GetNumberOfProfiles()); +} + +TEST_F(ProfileInfoCacheUnittests, MutateProfile) { + cache_->AddProfileToCache(GetUserDataDir().Append(StringToFilePath("path_1")), + ASCIIToUTF16("name_1"), 0); + cache_->AddProfileToCache(GetUserDataDir().Append(StringToFilePath("path_2")), + ASCIIToUTF16("name_2"), 0); + + string16 new_name = ASCIIToUTF16("new_name"); + cache_->SetNameOfProfileAtIndex(1, new_name); + EXPECT_EQ(new_name, cache_->GetNameOfProfileAtIndex(1)); + EXPECT_NE(new_name, cache_->GetNameOfProfileAtIndex(0)); + + size_t new_icon_index = 3; + cache_->SetAvatarIconOfProfileAtIndex(1, new_icon_index); + // Not much to test. + cache_->GetAvatarIconOfProfileAtIndex(1); +} + +} // namespace diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index 1499e75..5e62e81 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -1751,6 +1751,8 @@ 'browser/profiles/profile_impl.h', 'browser/profiles/profile_impl_io_data.cc', 'browser/profiles/profile_impl_io_data.h', + 'browser/profiles/profile_info_cache.cc', + 'browser/profiles/profile_info_cache.h', 'browser/profiles/profile_io_data.cc', 'browser/profiles/profile_io_data.h', 'browser/profiles/profile_keyed_service_factory.cc', diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi index 1214adb..39d2122 100644 --- a/chrome/chrome_tests.gypi +++ b/chrome/chrome_tests.gypi @@ -1555,6 +1555,7 @@ 'browser/process_info_snapshot_mac_unittest.cc', 'browser/process_singleton_mac_unittest.cc', 'browser/profiles/profile_dependency_manager_unittest.cc', + 'browser/profiles/profile_info_cache_unittest.cc', 'browser/profiles/profile_manager_unittest.cc', 'browser/renderer_host/accelerated_plugin_view_mac_unittest.mm', 'browser/renderer_host/gtk_key_bindings_handler_unittest.cc', diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc index 6020631..3c762bc 100644 --- a/chrome/common/pref_names.cc +++ b/chrome/common/pref_names.cc @@ -729,6 +729,11 @@ const char kProfileDirectoryMap[] = "profile.directory_map"; // directories. const char kProfilesNumCreated[] = "profile.profiles_created"; +// A map of profile data directory to cached information. This cache can be +// used to display information about profiles without actually having to load +// them. +const char kProfileInfoCache[] = "profile.info_cache"; + // Prefs for SSLConfigServicePref. const char kCertRevocationCheckingEnabled[] = "ssl.rev_checking.enabled"; const char kSSL3Enabled[] = "ssl.ssl3.enabled"; diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h index d49d346..9140483 100644 --- a/chrome/common/pref_names.h +++ b/chrome/common/pref_names.h @@ -265,6 +265,7 @@ extern const char kMetricsOngoingLogs[]; extern const char kProfileLastUsed[]; extern const char kProfileDirectoryMap[]; extern const char kProfilesNumCreated[]; +extern const char kProfileInfoCache[]; extern const char kProfileMetrics[]; extern const char kProfilePrefix[]; |