Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(34)

Side by Side Diff: chrome/browser/profiles/profile_info_cache.cc

Issue 8539043: Refactor ProfileInfoCache (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 9 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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 "chrome/browser/profiles/profile_info_cache.h" 5 #include "chrome/browser/profiles/profile_info_cache.h"
6 6
7 #include "base/format_macros.h"
8 #include "base/logging.h" 7 #include "base/logging.h"
9 #include "base/memory/scoped_ptr.h" 8 #include "base/memory/scoped_ptr.h"
10 #include "base/rand_util.h"
11 #include "base/string_number_conversions.h"
12 #include "base/stringprintf.h"
13 #include "base/utf_string_conversions.h"
14 #include "base/values.h" 9 #include "base/values.h"
15 #include "chrome/browser/prefs/pref_service.h" 10 #include "chrome/browser/prefs/pref_service.h"
16 #include "chrome/browser/prefs/scoped_user_pref_update.h" 11 #include "chrome/browser/prefs/scoped_user_pref_update.h"
12 #include "chrome/browser/profiles/profile_info_util.h"
17 #include "chrome/common/chrome_notification_types.h" 13 #include "chrome/common/chrome_notification_types.h"
18 #include "chrome/common/pref_names.h" 14 #include "chrome/common/pref_names.h"
19 #include "content/public/browser/notification_service.h" 15 #include "content/public/browser/notification_service.h"
20 #include "grit/generated_resources.h"
21 #include "grit/theme_resources.h"
22 #include "ui/base/l10n/l10n_util.h"
23 #include "ui/base/resource/resource_bundle.h"
24
25 namespace {
26
27 const char kNameKey[] = "name";
28 const char kUserNameKey[] = "user_name";
29 const char kAvatarIconKey[] = "avatar_icon";
30 const char kBackgroundAppsKey[] = "background_apps";
31 const char kDefaultUrlPrefix[] = "chrome://theme/IDR_PROFILE_AVATAR_";
32
33 const int kDefaultAvatarIconResources[] = {
34 IDR_PROFILE_AVATAR_0,
35 IDR_PROFILE_AVATAR_1,
36 IDR_PROFILE_AVATAR_2,
37 IDR_PROFILE_AVATAR_3,
38 IDR_PROFILE_AVATAR_4,
39 IDR_PROFILE_AVATAR_5,
40 IDR_PROFILE_AVATAR_6,
41 IDR_PROFILE_AVATAR_7,
42 IDR_PROFILE_AVATAR_8,
43 IDR_PROFILE_AVATAR_9,
44 IDR_PROFILE_AVATAR_10,
45 IDR_PROFILE_AVATAR_11,
46 IDR_PROFILE_AVATAR_12,
47 IDR_PROFILE_AVATAR_13,
48 IDR_PROFILE_AVATAR_14,
49 IDR_PROFILE_AVATAR_15,
50 IDR_PROFILE_AVATAR_16,
51 IDR_PROFILE_AVATAR_17,
52 IDR_PROFILE_AVATAR_18,
53 IDR_PROFILE_AVATAR_19,
54 IDR_PROFILE_AVATAR_20,
55 IDR_PROFILE_AVATAR_21,
56 IDR_PROFILE_AVATAR_22,
57 IDR_PROFILE_AVATAR_23,
58 IDR_PROFILE_AVATAR_24,
59 IDR_PROFILE_AVATAR_25,
60 };
61
62 const size_t kDefaultAvatarIconsCount = arraysize(kDefaultAvatarIconResources);
63
64 // The first 8 icons are generic.
65 const size_t kGenericIconCount = 8;
66
67 // First eight are generic icons, which use IDS_NUMBERED_PROFILE_NAME.
68 const int kDefaultNames[] = {
69 IDS_DEFAULT_AVATAR_NAME_8,
70 IDS_DEFAULT_AVATAR_NAME_9,
71 IDS_DEFAULT_AVATAR_NAME_10,
72 IDS_DEFAULT_AVATAR_NAME_11,
73 IDS_DEFAULT_AVATAR_NAME_12,
74 IDS_DEFAULT_AVATAR_NAME_13,
75 IDS_DEFAULT_AVATAR_NAME_14,
76 IDS_DEFAULT_AVATAR_NAME_15,
77 IDS_DEFAULT_AVATAR_NAME_16,
78 IDS_DEFAULT_AVATAR_NAME_17,
79 IDS_DEFAULT_AVATAR_NAME_18,
80 IDS_DEFAULT_AVATAR_NAME_19,
81 IDS_DEFAULT_AVATAR_NAME_20,
82 IDS_DEFAULT_AVATAR_NAME_21,
83 IDS_DEFAULT_AVATAR_NAME_22,
84 IDS_DEFAULT_AVATAR_NAME_23,
85 IDS_DEFAULT_AVATAR_NAME_24,
86 IDS_DEFAULT_AVATAR_NAME_25
87 };
88
89 } // namespace
90 16
91 ProfileInfoCache::ProfileInfoCache(PrefService* prefs, 17 ProfileInfoCache::ProfileInfoCache(PrefService* prefs,
92 const FilePath& user_data_dir) 18 const FilePath& user_data_dir)
93 : prefs_(prefs), 19 : prefs_(prefs),
94 user_data_dir_(user_data_dir) { 20 user_data_dir_(user_data_dir) {
95 // Populate the cache 21 // Populate the cache
96 const DictionaryValue* cache = 22 const DictionaryValue* cache =
97 prefs_->GetDictionary(prefs::kProfileInfoCache); 23 prefs_->GetDictionary(prefs::kProfileInfoCache);
98 for (DictionaryValue::key_iterator it = cache->begin_keys(); 24 for (DictionaryValue::key_iterator it = cache->begin_keys();
99 it != cache->end_keys(); ++it) { 25 it != cache->end_keys(); ++it) {
100 std::string key = *it; 26 std::string key = *it;
101 DictionaryValue* info = NULL; 27 DictionaryValue* info = NULL;
102 cache->GetDictionary(key, &info); 28 if (cache->GetDictionary(key, &info)) {
103 string16 name; 29 FilePath path = user_data_dir.AppendASCII(key);
104 info->GetString(kNameKey, &name); 30 cached_entries_[key] = ProfileInfoEntry(path, *info);
105 sorted_keys_.insert(FindPositionForProfile(key, name), key); 31 }
106 } 32 }
107 } 33 }
108 34
109 ProfileInfoCache::~ProfileInfoCache() { 35 ProfileInfoCache::~ProfileInfoCache() {
110 } 36 }
111 37
112 void ProfileInfoCache::AddProfileToCache(const FilePath& profile_path, 38 size_t ProfileInfoCache::GetNumberOfProfiles() const {
113 const string16& name, 39 return cached_entries_.size();
114 const string16& username, 40 }
115 size_t icon_index) { 41
42 std::vector<ProfileInfoEntry> ProfileInfoCache::GetProfilesSortedByName()
43 const {
44 std::vector<ProfileInfoEntry> entries;
45 for (std::map<std::string, ProfileInfoEntry>::const_iterator it =
46 cached_entries_.begin(); it != cached_entries_.end(); ++it) {
47 entries.push_back(it->second);
48 }
49 std::sort(entries.begin(), entries.end());
50 return entries;
51 }
52
53 bool ProfileInfoCache::GetInfoForProfile(const FilePath& path,
54 ProfileInfoEntry* entry) const {
55 // If the info is not in the cache then the profile was deleted.
56 std::string key = CacheKeyFromProfilePath(path);
57 std::map<std::string, ProfileInfoEntry>::const_iterator it =
58 cached_entries_.find(key);
59 if (it == cached_entries_.end())
60 return false;
61
62 *entry = it->second;
63 return true;
64 }
65
66 void ProfileInfoCache::DeleteProfileFromCache(const FilePath& profile_path) {
116 std::string key = CacheKeyFromProfilePath(profile_path); 67 std::string key = CacheKeyFromProfilePath(profile_path);
68 if (cached_entries_.count(key))
69 cached_entries_.erase(key);
70
117 DictionaryPrefUpdate update(prefs_, prefs::kProfileInfoCache); 71 DictionaryPrefUpdate update(prefs_, prefs::kProfileInfoCache);
118 DictionaryValue* cache = update.Get(); 72 DictionaryValue* cache = update.Get();
119 73 cache->Remove(key, NULL);
120 scoped_ptr<DictionaryValue> info(new DictionaryValue);
121 info->SetString(kNameKey, name);
122 info->SetString(kUserNameKey, username);
123 info->SetString(kAvatarIconKey, GetDefaultAvatarIconUrl(icon_index));
124 // Default value for whether background apps are running is false.
125 info->SetBoolean(kBackgroundAppsKey, false);
126 cache->Set(key, info.release());
127
128 sorted_keys_.insert(FindPositionForProfile(key, name), key);
129 74
130 content::NotificationService::current()->Notify( 75 content::NotificationService::current()->Notify(
131 chrome::NOTIFICATION_PROFILE_CACHED_INFO_CHANGED, 76 chrome::NOTIFICATION_PROFILE_CACHED_INFO_CHANGED,
132 content::NotificationService::AllSources(),
133 content::NotificationService::NoDetails());
134 }
135
136 void ProfileInfoCache::DeleteProfileFromCache(const FilePath& profile_path) {
137 DictionaryPrefUpdate update(prefs_, prefs::kProfileInfoCache);
138 DictionaryValue* cache = update.Get();
139
140 std::string key = CacheKeyFromProfilePath(profile_path);
141 cache->Remove(key, NULL);
142 sorted_keys_.erase(std::find(sorted_keys_.begin(), sorted_keys_.end(), key));
143
144 content::NotificationService::current()->Notify(
145 chrome::NOTIFICATION_PROFILE_CACHED_INFO_CHANGED,
146 content::NotificationService::AllSources(), 77 content::NotificationService::AllSources(),
147 content::NotificationService::NoDetails()); 78 content::NotificationService::NoDetails());
148 } 79 }
149 80
150 size_t ProfileInfoCache::GetNumberOfProfiles() const { 81 void ProfileInfoCache::SetInfoForProfile(const ProfileInfoEntry& info) {
151 return sorted_keys_.size(); 82 std::string key = CacheKeyFromProfilePath(info.path());
152 } 83 cached_entries_[key] = info;
153 84
154 size_t ProfileInfoCache::GetIndexOfProfileWithPath( 85 DictionaryPrefUpdate update(prefs_, prefs::kProfileInfoCache);
155 const FilePath& profile_path) const { 86 DictionaryValue* cache = update.Get();
156 if (profile_path.DirName() != user_data_dir_) 87 cache->Set(key, info.GetEntryAsDictionary());
157 return std::string::npos;
158 std::string search_key = CacheKeyFromProfilePath(profile_path);
159 for (size_t i = 0; i < sorted_keys_.size(); ++i) {
160 if (sorted_keys_[i] == search_key)
161 return i;
162 }
163 return std::string::npos;
164 }
165
166 string16 ProfileInfoCache::GetNameOfProfileAtIndex(size_t index) const {
167 string16 name;
168 GetInfoForProfileAtIndex(index)->GetString(kNameKey, &name);
169 return name;
170 }
171
172 FilePath ProfileInfoCache::GetPathOfProfileAtIndex(size_t index) const {
173 FilePath::StringType base_name;
174 #if defined(OS_POSIX)
175 base_name = sorted_keys_[index];
176 #elif defined(OS_WIN)
177 base_name = ASCIIToWide(sorted_keys_[index]);
178 #endif
179 return user_data_dir_.Append(base_name);
180 }
181
182 string16 ProfileInfoCache::GetUserNameOfProfileAtIndex(size_t index) const {
183 string16 user_name;
184 GetInfoForProfileAtIndex(index)->GetString(kUserNameKey, &user_name);
185 return user_name;
186 }
187
188 const gfx::Image& ProfileInfoCache::GetAvatarIconOfProfileAtIndex(
189 size_t index) const {
190 int resource_id = GetDefaultAvatarIconResourceIDAtIndex(
191 GetAvatarIconIndexOfProfileAtIndex(index));
192 return ResourceBundle::GetSharedInstance().GetImageNamed(resource_id);
193 }
194
195 bool ProfileInfoCache::GetBackgroundStatusOfProfileAtIndex(
196 size_t index) const {
197 bool background_app_status;
198 GetInfoForProfileAtIndex(index)->GetBoolean(kBackgroundAppsKey,
199 &background_app_status);
200 return background_app_status;
201 }
202
203 size_t ProfileInfoCache::GetAvatarIconIndexOfProfileAtIndex(size_t index)
204 const {
205 std::string icon_url;
206 GetInfoForProfileAtIndex(index)->GetString(kAvatarIconKey, &icon_url);
207 size_t icon_index = 0;
208 if (IsDefaultAvatarIconUrl(icon_url, &icon_index))
209 return icon_index;
210
211 DLOG(WARNING) << "Unknown avatar icon: " << icon_url;
212 return GetDefaultAvatarIconResourceIDAtIndex(0);
213 }
214
215 void ProfileInfoCache::SetNameOfProfileAtIndex(size_t index,
216 const string16& name) {
217 scoped_ptr<DictionaryValue> info(GetInfoForProfileAtIndex(index)->DeepCopy());
218 info->SetString(kNameKey, name);
219 // This takes ownership of |info|.
220 SetInfoForProfileAtIndex(index, info.release());
221
222 // Remove and reinsert key in |sorted_keys_| to alphasort.
223 std::string key = CacheKeyFromProfilePath(GetPathOfProfileAtIndex(index));
224 std::vector<std::string>::iterator key_it =
225 std::find(sorted_keys_.begin(), sorted_keys_.end(), key);
226 DCHECK(key_it != sorted_keys_.end());
227 sorted_keys_.erase(key_it);
228 sorted_keys_.insert(FindPositionForProfile(key, name), key);
229 88
230 content::NotificationService::current()->Notify( 89 content::NotificationService::current()->Notify(
231 chrome::NOTIFICATION_PROFILE_CACHED_INFO_CHANGED, 90 chrome::NOTIFICATION_PROFILE_CACHED_INFO_CHANGED,
232 content::NotificationService::AllSources(), 91 content::NotificationService::AllSources(),
233 content::NotificationService::NoDetails()); 92 content::NotificationService::NoDetails());
234 } 93 }
235 94
236 void ProfileInfoCache::SetUserNameOfProfileAtIndex(size_t index,
237 const string16& user_name) {
238 string16 old_user_name;
239 const base::DictionaryValue* old_info = GetInfoForProfileAtIndex(index);
240 old_info->GetString(kUserNameKey, &old_user_name);
241 if (old_user_name == user_name)
242 return;
243
244 scoped_ptr<DictionaryValue> info(old_info->DeepCopy());
245 info->SetString(kUserNameKey, user_name);
246 // This takes ownership of |info|.
247 SetInfoForProfileAtIndex(index, info.release());
248 }
249
250 void ProfileInfoCache::SetAvatarIconOfProfileAtIndex(size_t index,
251 size_t icon_index) {
252 scoped_ptr<DictionaryValue> info(GetInfoForProfileAtIndex(index)->DeepCopy());
253 info->SetString(kAvatarIconKey, GetDefaultAvatarIconUrl(icon_index));
254 // This takes ownership of |info|.
255 SetInfoForProfileAtIndex(index, info.release());
256 }
257
258 void ProfileInfoCache::SetBackgroundStatusOfProfileAtIndex(
259 size_t index,
260 bool running_background_apps) {
261 if (GetBackgroundStatusOfProfileAtIndex(index) == running_background_apps)
262 return;
263 scoped_ptr<DictionaryValue> info(GetInfoForProfileAtIndex(index)->DeepCopy());
264 info->SetBoolean(kBackgroundAppsKey, running_background_apps);
265 // This takes ownership of |info|.
266 SetInfoForProfileAtIndex(index, info.release());
267 }
268
269 string16 ProfileInfoCache::ChooseNameForNewProfile(size_t icon_index) {
270 string16 name;
271 for (int name_index = 1; ; ++name_index) {
272 if (icon_index < kGenericIconCount) {
273 name = l10n_util::GetStringFUTF16Int(IDS_NUMBERED_PROFILE_NAME,
274 name_index);
275 } else {
276 name = l10n_util::GetStringUTF16(
277 kDefaultNames[icon_index - kGenericIconCount]);
278 if (name_index > 1)
279 name.append(UTF8ToUTF16(base::IntToString(name_index)));
280 }
281
282 // Loop through previously named profiles to ensure we're not duplicating.
283 bool name_found = false;
284 for (size_t i = 0; i < GetNumberOfProfiles(); ++i) {
285 if (GetNameOfProfileAtIndex(i) == name) {
286 name_found = true;
287 break;
288 }
289 }
290 if (!name_found)
291 return name;
292 }
293 }
294
295 bool ProfileInfoCache::IconIndexIsUnique(size_t icon_index) const {
296 for (size_t i = 0; i < GetNumberOfProfiles(); ++i) {
297 if (GetAvatarIconIndexOfProfileAtIndex(i) == icon_index)
298 return false;
299 }
300 return true;
301 }
302
303 bool ProfileInfoCache::ChooseAvatarIconIndexForNewProfile(
304 bool allow_generic_icon,
305 bool must_be_unique,
306 size_t* out_icon_index) const {
307 size_t start = allow_generic_icon ? 0 : kGenericIconCount;
308 size_t end = GetDefaultAvatarIconCount();
309 size_t count = end - start;
310
311 int rand = base::RandInt(0, count);
312 for (size_t i = 0; i < count; ++i) {
313 size_t icon_index = start + (rand + i) % count;
314 if (!must_be_unique || IconIndexIsUnique(icon_index)) {
315 *out_icon_index = icon_index;
316 return true;
317 }
318 }
319
320 return false;
321 }
322
323 size_t ProfileInfoCache::ChooseAvatarIconIndexForNewProfile() const {
324 size_t icon_index = 0;
325 // Try to find a unique, non-generic icon.
326 if (ChooseAvatarIconIndexForNewProfile(false, true, &icon_index))
327 return icon_index;
328 // Try to find any unique icon.
329 if (ChooseAvatarIconIndexForNewProfile(true, true, &icon_index))
330 return icon_index;
331 // Settle for any random icon, even if it's not unique.
332 if (ChooseAvatarIconIndexForNewProfile(true, false, &icon_index))
333 return icon_index;
334
335 NOTREACHED();
336 return 0;
337 }
338
339 const FilePath& ProfileInfoCache::GetUserDataDir() const { 95 const FilePath& ProfileInfoCache::GetUserDataDir() const {
340 return user_data_dir_; 96 return user_data_dir_;
341 } 97 }
342 98
343 // static
344 size_t ProfileInfoCache::GetDefaultAvatarIconCount() {
345 return kDefaultAvatarIconsCount;
346 }
347
348 // static
349 int ProfileInfoCache::GetDefaultAvatarIconResourceIDAtIndex(size_t index) {
350 DCHECK_LT(index, GetDefaultAvatarIconCount());
351 return kDefaultAvatarIconResources[index];
352 }
353
354 // static
355 std::string ProfileInfoCache::GetDefaultAvatarIconUrl(size_t index) {
356 DCHECK_LT(index, kDefaultAvatarIconsCount);
357 return StringPrintf("%s%" PRIuS, kDefaultUrlPrefix, index);
358 }
359
360 // static
361 bool ProfileInfoCache::IsDefaultAvatarIconUrl(const std::string& url,
362 size_t* icon_index) {
363 DCHECK(icon_index);
364 if (url.find(kDefaultUrlPrefix) != 0)
365 return false;
366
367 int int_value = -1;
368 if (base::StringToInt(url.begin() + strlen(kDefaultUrlPrefix),
369 url.end(),
370 &int_value)) {
371 if (int_value < 0 ||
372 int_value >= static_cast<int>(kDefaultAvatarIconsCount))
373 return false;
374 *icon_index = int_value;
375 return true;
376 }
377
378 return false;
379 }
380
381 const DictionaryValue* ProfileInfoCache::GetInfoForProfileAtIndex(
382 size_t index) const {
383 DCHECK_LT(index, GetNumberOfProfiles());
384 const DictionaryValue* cache =
385 prefs_->GetDictionary(prefs::kProfileInfoCache);
386 DictionaryValue* info = NULL;
387 cache->GetDictionary(sorted_keys_[index], &info);
388 return info;
389 }
390
391 void ProfileInfoCache::SetInfoForProfileAtIndex(size_t index,
392 DictionaryValue* info) {
393 DictionaryPrefUpdate update(prefs_, prefs::kProfileInfoCache);
394 DictionaryValue* cache = update.Get();
395 cache->Set(sorted_keys_[index], info);
396
397 content::NotificationService::current()->Notify(
398 chrome::NOTIFICATION_PROFILE_CACHED_INFO_CHANGED,
399 content::NotificationService::AllSources(),
400 content::NotificationService::NoDetails());
401 }
402
403 std::string ProfileInfoCache::CacheKeyFromProfilePath( 99 std::string ProfileInfoCache::CacheKeyFromProfilePath(
404 const FilePath& profile_path) const { 100 const FilePath& profile_path) const {
405 DCHECK(user_data_dir_ == profile_path.DirName()); 101 DCHECK(user_data_dir_ == profile_path.DirName());
406 FilePath base_name = profile_path.BaseName(); 102 FilePath base_name = profile_path.BaseName();
407 return base_name.MaybeAsASCII(); 103 return base_name.MaybeAsASCII();
408 } 104 }
409 105
410 std::vector<std::string>::iterator ProfileInfoCache::FindPositionForProfile(
411 std::string search_key,
412 const string16& search_name) {
413 for (size_t i = 0; i < GetNumberOfProfiles(); ++i) {
414 int name_compare = search_name.compare(GetNameOfProfileAtIndex(i));
415 if (name_compare < 0)
416 return sorted_keys_.begin() + i;
417 if (name_compare == 0) {
418 int key_compare = search_key.compare(sorted_keys_[i]);
419 if (key_compare < 0)
420 return sorted_keys_.begin() + i;
421 }
422 }
423 return sorted_keys_.end();
424 }
425
426 void ProfileInfoCache::RegisterPrefs(PrefService* prefs) { 106 void ProfileInfoCache::RegisterPrefs(PrefService* prefs) {
427 prefs->RegisterDictionaryPref(prefs::kProfileInfoCache); 107 prefs->RegisterDictionaryPref(prefs::kProfileInfoCache);
428 } 108 }
OLDNEW
« no previous file with comments | « chrome/browser/profiles/profile_info_cache.h ('k') | chrome/browser/profiles/profile_info_entry.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698