OLD | NEW |
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/bind.h" |
| 8 #include "base/file_util.h" |
7 #include "base/format_macros.h" | 9 #include "base/format_macros.h" |
| 10 #include "base/i18n/case_conversion.h" |
8 #include "base/logging.h" | 11 #include "base/logging.h" |
9 #include "base/memory/scoped_ptr.h" | 12 #include "base/memory/scoped_ptr.h" |
10 #include "base/rand_util.h" | 13 #include "base/rand_util.h" |
| 14 #include "base/stl_util.h" |
11 #include "base/string_number_conversions.h" | 15 #include "base/string_number_conversions.h" |
12 #include "base/stringprintf.h" | 16 #include "base/stringprintf.h" |
13 #include "base/utf_string_conversions.h" | 17 #include "base/utf_string_conversions.h" |
14 #include "base/values.h" | 18 #include "base/values.h" |
15 #include "chrome/browser/browser_process.h" | 19 #include "chrome/browser/browser_process.h" |
16 #include "chrome/browser/prefs/pref_service.h" | 20 #include "chrome/browser/prefs/pref_service.h" |
17 #include "chrome/browser/prefs/scoped_user_pref_update.h" | 21 #include "chrome/browser/prefs/scoped_user_pref_update.h" |
18 #include "chrome/common/chrome_notification_types.h" | 22 #include "chrome/common/chrome_notification_types.h" |
19 #include "chrome/common/pref_names.h" | 23 #include "chrome/common/pref_names.h" |
| 24 #include "content/public/browser/browser_thread.h" |
20 #include "content/public/browser/notification_service.h" | 25 #include "content/public/browser/notification_service.h" |
21 #include "grit/generated_resources.h" | 26 #include "grit/generated_resources.h" |
22 #include "grit/theme_resources.h" | 27 #include "grit/theme_resources.h" |
| 28 #include "third_party/skia/include/core/SkBitmap.h" |
23 #include "ui/base/l10n/l10n_util.h" | 29 #include "ui/base/l10n/l10n_util.h" |
24 #include "ui/base/resource/resource_bundle.h" | 30 #include "ui/base/resource/resource_bundle.h" |
| 31 #include "ui/gfx/image/image.h" |
| 32 #include "ui/gfx/image/image_util.h" |
| 33 |
| 34 using content::BrowserThread; |
25 | 35 |
26 namespace { | 36 namespace { |
27 | 37 |
28 const char kNameKey[] = "name"; | 38 const char kNameKey[] = "name"; |
| 39 const char kGAIANameKey[] = "gaia_name"; |
| 40 const char kUseGAIANameKey[] = "use_gaia_name"; |
29 const char kUserNameKey[] = "user_name"; | 41 const char kUserNameKey[] = "user_name"; |
30 const char kAvatarIconKey[] = "avatar_icon"; | 42 const char kAvatarIconKey[] = "avatar_icon"; |
| 43 const char kUseGAIAPictureKey[] = "use_gaia_picture"; |
31 const char kBackgroundAppsKey[] = "background_apps"; | 44 const char kBackgroundAppsKey[] = "background_apps"; |
| 45 const char kHasMigratedToGAIAInfoKey[] = "has_migrated_to_gaia_info"; |
32 const char kDefaultUrlPrefix[] = "chrome://theme/IDR_PROFILE_AVATAR_"; | 46 const char kDefaultUrlPrefix[] = "chrome://theme/IDR_PROFILE_AVATAR_"; |
| 47 const char kGAIAPictureFileName[] = "Google Profile Picture.png"; |
33 | 48 |
34 const int kDefaultAvatarIconResources[] = { | 49 const int kDefaultAvatarIconResources[] = { |
35 IDR_PROFILE_AVATAR_0, | 50 IDR_PROFILE_AVATAR_0, |
36 IDR_PROFILE_AVATAR_1, | 51 IDR_PROFILE_AVATAR_1, |
37 IDR_PROFILE_AVATAR_2, | 52 IDR_PROFILE_AVATAR_2, |
38 IDR_PROFILE_AVATAR_3, | 53 IDR_PROFILE_AVATAR_3, |
39 IDR_PROFILE_AVATAR_4, | 54 IDR_PROFILE_AVATAR_4, |
40 IDR_PROFILE_AVATAR_5, | 55 IDR_PROFILE_AVATAR_5, |
41 IDR_PROFILE_AVATAR_6, | 56 IDR_PROFILE_AVATAR_6, |
42 IDR_PROFILE_AVATAR_7, | 57 IDR_PROFILE_AVATAR_7, |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
80 IDS_DEFAULT_AVATAR_NAME_18, | 95 IDS_DEFAULT_AVATAR_NAME_18, |
81 IDS_DEFAULT_AVATAR_NAME_19, | 96 IDS_DEFAULT_AVATAR_NAME_19, |
82 IDS_DEFAULT_AVATAR_NAME_20, | 97 IDS_DEFAULT_AVATAR_NAME_20, |
83 IDS_DEFAULT_AVATAR_NAME_21, | 98 IDS_DEFAULT_AVATAR_NAME_21, |
84 IDS_DEFAULT_AVATAR_NAME_22, | 99 IDS_DEFAULT_AVATAR_NAME_22, |
85 IDS_DEFAULT_AVATAR_NAME_23, | 100 IDS_DEFAULT_AVATAR_NAME_23, |
86 IDS_DEFAULT_AVATAR_NAME_24, | 101 IDS_DEFAULT_AVATAR_NAME_24, |
87 IDS_DEFAULT_AVATAR_NAME_25 | 102 IDS_DEFAULT_AVATAR_NAME_25 |
88 }; | 103 }; |
89 | 104 |
| 105 typedef std::vector<unsigned char> ImageData; |
| 106 |
| 107 // Writes |data| to disk and takes ownership of the pointer. On completion |
| 108 // |success| is set to true on success and false on failure. |
| 109 void SaveBitmap(ImageData* data, |
| 110 FilePath image_path, |
| 111 bool* success) { |
| 112 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 113 scoped_ptr<ImageData> data_owner(data); |
| 114 *success = false; |
| 115 |
| 116 // Make sure the destination directory exists. |
| 117 FilePath dir = image_path.DirName(); |
| 118 if (!file_util::DirectoryExists(dir) && !file_util::CreateDirectory(dir)) { |
| 119 LOG(ERROR) << "Failed to create parent directory."; |
| 120 return; |
| 121 } |
| 122 |
| 123 if (file_util::WriteFile(image_path, |
| 124 reinterpret_cast<char*>(&(*data)[0]), |
| 125 data->size()) == -1) { |
| 126 LOG(ERROR) << "Failed to save image to file."; |
| 127 return; |
| 128 } |
| 129 |
| 130 *success = true; |
| 131 } |
| 132 |
| 133 // Reads a PNG from disk and decodes it. If the bitmap was successfully read |
| 134 // from disk the then |out_image| will contain the bitmap image, otherwise it |
| 135 // will be NULL. |
| 136 void ReadBitmap(FilePath image_path, |
| 137 gfx::Image** out_image) { |
| 138 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 139 *out_image = NULL; |
| 140 |
| 141 std::string image_data; |
| 142 if (!file_util::ReadFileToString(image_path, &image_data)) { |
| 143 LOG(ERROR) << "Failed to read PNG file from disk."; |
| 144 return; |
| 145 } |
| 146 |
| 147 const unsigned char* data = |
| 148 reinterpret_cast<const unsigned char*>(image_data.data()); |
| 149 gfx::Image* image = gfx::ImageFromPNGEncodedData(data, image_data.length()); |
| 150 if (image == NULL) { |
| 151 LOG(ERROR) << "Failed to decode PNG file."; |
| 152 return; |
| 153 } |
| 154 |
| 155 *out_image = image; |
| 156 } |
| 157 |
90 } // namespace | 158 } // namespace |
91 | 159 |
92 ProfileInfoCache::ProfileInfoCache(PrefService* prefs, | 160 ProfileInfoCache::ProfileInfoCache(PrefService* prefs, |
93 const FilePath& user_data_dir) | 161 const FilePath& user_data_dir) |
94 : prefs_(prefs), | 162 : prefs_(prefs), |
95 user_data_dir_(user_data_dir) { | 163 user_data_dir_(user_data_dir) { |
96 // Populate the cache | 164 // Populate the cache |
97 const DictionaryValue* cache = | 165 const DictionaryValue* cache = |
98 prefs_->GetDictionary(prefs::kProfileInfoCache); | 166 prefs_->GetDictionary(prefs::kProfileInfoCache); |
99 for (DictionaryValue::key_iterator it = cache->begin_keys(); | 167 for (DictionaryValue::key_iterator it = cache->begin_keys(); |
100 it != cache->end_keys(); ++it) { | 168 it != cache->end_keys(); ++it) { |
101 std::string key = *it; | 169 std::string key = *it; |
102 DictionaryValue* info = NULL; | 170 DictionaryValue* info = NULL; |
103 cache->GetDictionary(key, &info); | 171 cache->GetDictionary(key, &info); |
104 string16 name; | 172 string16 name; |
105 info->GetString(kNameKey, &name); | 173 info->GetString(kNameKey, &name); |
106 sorted_keys_.insert(FindPositionForProfile(key, name), key); | 174 sorted_keys_.insert(FindPositionForProfile(key, name), key); |
107 } | 175 } |
108 } | 176 } |
109 | 177 |
110 ProfileInfoCache::~ProfileInfoCache() { | 178 ProfileInfoCache::~ProfileInfoCache() { |
| 179 STLDeleteContainerPairSecondPointers( |
| 180 gaia_pictures_.begin(), gaia_pictures_.end()); |
111 } | 181 } |
112 | 182 |
113 void ProfileInfoCache::AddProfileToCache(const FilePath& profile_path, | 183 void ProfileInfoCache::AddProfileToCache(const FilePath& profile_path, |
114 const string16& name, | 184 const string16& name, |
115 const string16& username, | 185 const string16& username, |
116 size_t icon_index) { | 186 size_t icon_index) { |
117 std::string key = CacheKeyFromProfilePath(profile_path); | 187 std::string key = CacheKeyFromProfilePath(profile_path); |
118 DictionaryPrefUpdate update(prefs_, prefs::kProfileInfoCache); | 188 DictionaryPrefUpdate update(prefs_, prefs::kProfileInfoCache); |
119 DictionaryValue* cache = update.Get(); | 189 DictionaryValue* cache = update.Get(); |
120 | 190 |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
179 return std::string::npos; | 249 return std::string::npos; |
180 std::string search_key = CacheKeyFromProfilePath(profile_path); | 250 std::string search_key = CacheKeyFromProfilePath(profile_path); |
181 for (size_t i = 0; i < sorted_keys_.size(); ++i) { | 251 for (size_t i = 0; i < sorted_keys_.size(); ++i) { |
182 if (sorted_keys_[i] == search_key) | 252 if (sorted_keys_[i] == search_key) |
183 return i; | 253 return i; |
184 } | 254 } |
185 return std::string::npos; | 255 return std::string::npos; |
186 } | 256 } |
187 | 257 |
188 string16 ProfileInfoCache::GetNameOfProfileAtIndex(size_t index) const { | 258 string16 ProfileInfoCache::GetNameOfProfileAtIndex(size_t index) const { |
| 259 if (IsUsingGAIANameOfProfileAtIndex(index)) |
| 260 return GetGAIANameOfProfileAtIndex(index); |
| 261 |
189 string16 name; | 262 string16 name; |
190 GetInfoForProfileAtIndex(index)->GetString(kNameKey, &name); | 263 GetInfoForProfileAtIndex(index)->GetString(kNameKey, &name); |
191 return name; | 264 return name; |
192 } | 265 } |
193 | 266 |
194 FilePath ProfileInfoCache::GetPathOfProfileAtIndex(size_t index) const { | 267 FilePath ProfileInfoCache::GetPathOfProfileAtIndex(size_t index) const { |
195 FilePath::StringType base_name; | 268 return user_data_dir_.AppendASCII(sorted_keys_[index]); |
196 #if defined(OS_POSIX) | |
197 base_name = sorted_keys_[index]; | |
198 #elif defined(OS_WIN) | |
199 base_name = ASCIIToWide(sorted_keys_[index]); | |
200 #endif | |
201 return user_data_dir_.Append(base_name); | |
202 } | 269 } |
203 | 270 |
204 string16 ProfileInfoCache::GetUserNameOfProfileAtIndex(size_t index) const { | 271 string16 ProfileInfoCache::GetUserNameOfProfileAtIndex(size_t index) const { |
205 string16 user_name; | 272 string16 user_name; |
206 GetInfoForProfileAtIndex(index)->GetString(kUserNameKey, &user_name); | 273 GetInfoForProfileAtIndex(index)->GetString(kUserNameKey, &user_name); |
207 return user_name; | 274 return user_name; |
208 } | 275 } |
209 | 276 |
210 const gfx::Image& ProfileInfoCache::GetAvatarIconOfProfileAtIndex( | 277 const gfx::Image& ProfileInfoCache::GetAvatarIconOfProfileAtIndex( |
211 size_t index) const { | 278 size_t index) const { |
| 279 if (IsUsingGAIAPictureOfProfileAtIndex(index)) |
| 280 return GetGAIAPictureOfProfileAtIndex(index); |
| 281 |
212 int resource_id = GetDefaultAvatarIconResourceIDAtIndex( | 282 int resource_id = GetDefaultAvatarIconResourceIDAtIndex( |
213 GetAvatarIconIndexOfProfileAtIndex(index)); | 283 GetAvatarIconIndexOfProfileAtIndex(index)); |
214 return ResourceBundle::GetSharedInstance().GetImageNamed(resource_id); | 284 return ResourceBundle::GetSharedInstance().GetImageNamed(resource_id); |
215 } | 285 } |
216 | 286 |
217 bool ProfileInfoCache::GetBackgroundStatusOfProfileAtIndex( | 287 bool ProfileInfoCache::GetBackgroundStatusOfProfileAtIndex( |
218 size_t index) const { | 288 size_t index) const { |
219 bool background_app_status; | 289 bool background_app_status; |
220 GetInfoForProfileAtIndex(index)->GetBoolean(kBackgroundAppsKey, | 290 GetInfoForProfileAtIndex(index)->GetBoolean(kBackgroundAppsKey, |
221 &background_app_status); | 291 &background_app_status); |
222 return background_app_status; | 292 return background_app_status; |
223 } | 293 } |
224 | 294 |
| 295 string16 ProfileInfoCache::GetGAIANameOfProfileAtIndex(size_t index) const { |
| 296 string16 name; |
| 297 GetInfoForProfileAtIndex(index)->GetString(kGAIANameKey, &name); |
| 298 return name; |
| 299 } |
| 300 |
| 301 bool ProfileInfoCache::IsUsingGAIANameOfProfileAtIndex(size_t index) const { |
| 302 bool value = false; |
| 303 GetInfoForProfileAtIndex(index)->GetBoolean(kUseGAIANameKey, &value); |
| 304 return value; |
| 305 } |
| 306 |
| 307 const gfx::Image& ProfileInfoCache::GetGAIAPictureOfProfileAtIndex( |
| 308 size_t index) const { |
| 309 FilePath path = GetPathOfProfileAtIndex(index); |
| 310 std::string key = CacheKeyFromProfilePath(path); |
| 311 if (gaia_pictures_.count(key)) { |
| 312 return *gaia_pictures_[key]; |
| 313 } |
| 314 |
| 315 // The GAIA picture is not in the cache yet. Load it from disk and return |
| 316 // a blank picture for now. |
| 317 gaia_pictures_[key] = new gfx::Image(new SkBitmap()); |
| 318 |
| 319 FilePath image_path = path.AppendASCII(kGAIAPictureFileName); |
| 320 gfx::Image** image = new gfx::Image*; |
| 321 bool success = BrowserThread::PostTaskAndReply(BrowserThread::FILE, FROM_HERE, |
| 322 base::Bind(&ReadBitmap, image_path, image), |
| 323 base::Bind(&ProfileInfoCache::OnGAIAPictureLoaded, |
| 324 const_cast<ProfileInfoCache*>(this)->AsWeakPtr(), path, image)); |
| 325 CHECK(success); |
| 326 |
| 327 return *gaia_pictures_[key]; |
| 328 } |
| 329 |
| 330 void ProfileInfoCache::OnGAIAPictureLoaded(FilePath path, |
| 331 gfx::Image** image) const { |
| 332 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 333 |
| 334 if (*image) { |
| 335 std::string key = CacheKeyFromProfilePath(path); |
| 336 delete gaia_pictures_[key]; |
| 337 gaia_pictures_[key] = *image; |
| 338 } |
| 339 delete image; |
| 340 |
| 341 content::NotificationService::current()->Notify( |
| 342 chrome::NOTIFICATION_PROFILE_CACHED_INFO_CHANGED, |
| 343 content::NotificationService::AllSources(), |
| 344 content::NotificationService::NoDetails()); |
| 345 } |
| 346 |
| 347 void ProfileInfoCache::OnGAIAPictureSaved(FilePath path, bool* success) const { |
| 348 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 349 |
| 350 if (*success) { |
| 351 content::NotificationService::current()->Notify( |
| 352 chrome::NOTIFICATION_PROFILE_CACHE_PICTURE_SAVED, |
| 353 content::NotificationService::AllSources(), |
| 354 content::NotificationService::NoDetails()); |
| 355 } |
| 356 delete success; |
| 357 } |
| 358 |
| 359 bool ProfileInfoCache::IsUsingGAIAPictureOfProfileAtIndex( |
| 360 size_t index) const { |
| 361 bool value = false; |
| 362 GetInfoForProfileAtIndex(index)->GetBoolean(kUseGAIAPictureKey, &value); |
| 363 return value; |
| 364 } |
| 365 |
225 size_t ProfileInfoCache::GetAvatarIconIndexOfProfileAtIndex(size_t index) | 366 size_t ProfileInfoCache::GetAvatarIconIndexOfProfileAtIndex(size_t index) |
226 const { | 367 const { |
227 std::string icon_url; | 368 std::string icon_url; |
228 GetInfoForProfileAtIndex(index)->GetString(kAvatarIconKey, &icon_url); | 369 GetInfoForProfileAtIndex(index)->GetString(kAvatarIconKey, &icon_url); |
229 size_t icon_index = 0; | 370 size_t icon_index = 0; |
230 if (IsDefaultAvatarIconUrl(icon_url, &icon_index)) | 371 if (IsDefaultAvatarIconUrl(icon_url, &icon_index)) |
231 return icon_index; | 372 return icon_index; |
232 | 373 |
233 DLOG(WARNING) << "Unknown avatar icon: " << icon_url; | 374 DLOG(WARNING) << "Unknown avatar icon: " << icon_url; |
234 return GetDefaultAvatarIconResourceIDAtIndex(0); | 375 return GetDefaultAvatarIconResourceIDAtIndex(0); |
235 } | 376 } |
236 | 377 |
237 void ProfileInfoCache::SetNameOfProfileAtIndex(size_t index, | 378 void ProfileInfoCache::SetNameOfProfileAtIndex(size_t index, |
238 const string16& name) { | 379 const string16& name) { |
| 380 if (name == GetNameOfProfileAtIndex(index)) |
| 381 return; |
| 382 |
239 scoped_ptr<DictionaryValue> info(GetInfoForProfileAtIndex(index)->DeepCopy()); | 383 scoped_ptr<DictionaryValue> info(GetInfoForProfileAtIndex(index)->DeepCopy()); |
240 string16 old_name; | 384 string16 old_name; |
241 info->GetString(kNameKey, &old_name); | 385 info->GetString(kNameKey, &old_name); |
242 info->SetString(kNameKey, name); | 386 info->SetString(kNameKey, name); |
243 // This takes ownership of |info|. | 387 // This takes ownership of |info|. |
244 SetInfoForProfileAtIndex(index, info.release()); | 388 SetInfoForProfileAtIndex(index, info.release()); |
245 | 389 UpdateSortForProfileIndex(index); |
246 // Remove and reinsert key in |sorted_keys_| to alphasort. | |
247 std::string key = CacheKeyFromProfilePath(GetPathOfProfileAtIndex(index)); | |
248 std::vector<std::string>::iterator key_it = | |
249 std::find(sorted_keys_.begin(), sorted_keys_.end(), key); | |
250 DCHECK(key_it != sorted_keys_.end()); | |
251 sorted_keys_.erase(key_it); | |
252 sorted_keys_.insert(FindPositionForProfile(key, name), key); | |
253 | 390 |
254 FOR_EACH_OBSERVER(ProfileInfoCacheObserver, | 391 FOR_EACH_OBSERVER(ProfileInfoCacheObserver, |
255 observer_list_, | 392 observer_list_, |
256 OnProfileNameChanged(old_name, name)); | 393 OnProfileNameChanged(old_name, name)); |
257 | |
258 content::NotificationService::current()->Notify( | |
259 chrome::NOTIFICATION_PROFILE_CACHED_INFO_CHANGED, | |
260 content::NotificationService::AllSources(), | |
261 content::NotificationService::NoDetails()); | |
262 } | 394 } |
263 | 395 |
264 void ProfileInfoCache::SetUserNameOfProfileAtIndex(size_t index, | 396 void ProfileInfoCache::SetUserNameOfProfileAtIndex(size_t index, |
265 const string16& user_name) { | 397 const string16& user_name) { |
266 string16 old_user_name; | 398 if (user_name == GetUserNameOfProfileAtIndex(index)) |
267 const base::DictionaryValue* old_info = GetInfoForProfileAtIndex(index); | |
268 old_info->GetString(kUserNameKey, &old_user_name); | |
269 if (old_user_name == user_name) | |
270 return; | 399 return; |
271 | 400 |
272 scoped_ptr<DictionaryValue> info(old_info->DeepCopy()); | 401 scoped_ptr<DictionaryValue> info(GetInfoForProfileAtIndex(index)->DeepCopy()); |
273 info->SetString(kUserNameKey, user_name); | 402 info->SetString(kUserNameKey, user_name); |
274 // This takes ownership of |info|. | 403 // This takes ownership of |info|. |
275 SetInfoForProfileAtIndex(index, info.release()); | 404 SetInfoForProfileAtIndex(index, info.release()); |
276 } | 405 } |
277 | 406 |
278 void ProfileInfoCache::SetAvatarIconOfProfileAtIndex(size_t index, | 407 void ProfileInfoCache::SetAvatarIconOfProfileAtIndex(size_t index, |
279 size_t icon_index) { | 408 size_t icon_index) { |
280 scoped_ptr<DictionaryValue> info(GetInfoForProfileAtIndex(index)->DeepCopy()); | 409 scoped_ptr<DictionaryValue> info(GetInfoForProfileAtIndex(index)->DeepCopy()); |
281 info->SetString(kAvatarIconKey, GetDefaultAvatarIconUrl(icon_index)); | 410 info->SetString(kAvatarIconKey, GetDefaultAvatarIconUrl(icon_index)); |
282 // This takes ownership of |info|. | 411 // This takes ownership of |info|. |
283 SetInfoForProfileAtIndex(index, info.release()); | 412 SetInfoForProfileAtIndex(index, info.release()); |
284 } | 413 } |
285 | 414 |
286 void ProfileInfoCache::SetBackgroundStatusOfProfileAtIndex( | 415 void ProfileInfoCache::SetBackgroundStatusOfProfileAtIndex( |
287 size_t index, | 416 size_t index, |
288 bool running_background_apps) { | 417 bool running_background_apps) { |
289 if (GetBackgroundStatusOfProfileAtIndex(index) == running_background_apps) | 418 if (GetBackgroundStatusOfProfileAtIndex(index) == running_background_apps) |
290 return; | 419 return; |
291 scoped_ptr<DictionaryValue> info(GetInfoForProfileAtIndex(index)->DeepCopy()); | 420 scoped_ptr<DictionaryValue> info(GetInfoForProfileAtIndex(index)->DeepCopy()); |
292 info->SetBoolean(kBackgroundAppsKey, running_background_apps); | 421 info->SetBoolean(kBackgroundAppsKey, running_background_apps); |
293 // This takes ownership of |info|. | 422 // This takes ownership of |info|. |
294 SetInfoForProfileAtIndex(index, info.release()); | 423 SetInfoForProfileAtIndex(index, info.release()); |
295 } | 424 } |
296 | 425 |
| 426 void ProfileInfoCache::SetGAIANameOfProfileAtIndex(size_t index, |
| 427 const string16& name) { |
| 428 if (name == GetGAIANameOfProfileAtIndex(index)) |
| 429 return; |
| 430 |
| 431 scoped_ptr<DictionaryValue> info(GetInfoForProfileAtIndex(index)->DeepCopy()); |
| 432 info->SetString(kGAIANameKey, name); |
| 433 // This takes ownership of |info|. |
| 434 SetInfoForProfileAtIndex(index, info.release()); |
| 435 UpdateSortForProfileIndex(index); |
| 436 } |
| 437 |
| 438 void ProfileInfoCache::SetIsUsingGAIANameOfProfileAtIndex(size_t index, |
| 439 bool value) { |
| 440 if (value == IsUsingGAIANameOfProfileAtIndex(index)) |
| 441 return; |
| 442 |
| 443 scoped_ptr<DictionaryValue> info(GetInfoForProfileAtIndex(index)->DeepCopy()); |
| 444 info->SetBoolean(kUseGAIANameKey, value); |
| 445 // This takes ownership of |info|. |
| 446 SetInfoForProfileAtIndex(index, info.release()); |
| 447 UpdateSortForProfileIndex(index); |
| 448 } |
| 449 |
| 450 void ProfileInfoCache::SetGAIAPictureOfProfileAtIndex(size_t index, |
| 451 const gfx::Image& image) { |
| 452 FilePath path = GetPathOfProfileAtIndex(index); |
| 453 std::string key = CacheKeyFromProfilePath(path); |
| 454 |
| 455 delete gaia_pictures_[key]; |
| 456 gaia_pictures_[key] = new gfx::Image(image); |
| 457 |
| 458 scoped_ptr<ImageData> data(new ImageData); |
| 459 if (!gfx::PNGEncodedDataFromImage(image, data.get())) { |
| 460 LOG(ERROR) << "Failed to PNG encode the image."; |
| 461 } else { |
| 462 FilePath image_path = path.AppendASCII(kGAIAPictureFileName); |
| 463 bool* success = new bool; |
| 464 bool post = BrowserThread::PostTaskAndReply(BrowserThread::FILE, FROM_HERE, |
| 465 base::Bind(&SaveBitmap, data.release(), image_path, success), |
| 466 base::Bind(&ProfileInfoCache::OnGAIAPictureSaved, AsWeakPtr(), |
| 467 path, success)); |
| 468 CHECK(post); |
| 469 } |
| 470 |
| 471 content::NotificationService::current()->Notify( |
| 472 chrome::NOTIFICATION_PROFILE_CACHED_INFO_CHANGED, |
| 473 content::NotificationService::AllSources(), |
| 474 content::NotificationService::NoDetails()); |
| 475 } |
| 476 |
| 477 void ProfileInfoCache::SetIsUsingGAIAPictureOfProfileAtIndex(size_t index, |
| 478 bool value) { |
| 479 scoped_ptr<DictionaryValue> info(GetInfoForProfileAtIndex(index)->DeepCopy()); |
| 480 info->SetBoolean(kUseGAIAPictureKey, value); |
| 481 // This takes ownership of |info|. |
| 482 SetInfoForProfileAtIndex(index, info.release()); |
| 483 } |
| 484 |
297 string16 ProfileInfoCache::ChooseNameForNewProfile(size_t icon_index) { | 485 string16 ProfileInfoCache::ChooseNameForNewProfile(size_t icon_index) { |
298 string16 name; | 486 string16 name; |
299 for (int name_index = 1; ; ++name_index) { | 487 for (int name_index = 1; ; ++name_index) { |
300 if (icon_index < kGenericIconCount) { | 488 if (icon_index < kGenericIconCount) { |
301 name = l10n_util::GetStringFUTF16Int(IDS_NUMBERED_PROFILE_NAME, | 489 name = l10n_util::GetStringFUTF16Int(IDS_NUMBERED_PROFILE_NAME, |
302 name_index); | 490 name_index); |
303 } else { | 491 } else { |
304 name = l10n_util::GetStringUTF16( | 492 name = l10n_util::GetStringUTF16( |
305 kDefaultNames[icon_index - kGenericIconCount]); | 493 kDefaultNames[icon_index - kGenericIconCount]); |
306 if (name_index > 1) | 494 if (name_index > 1) |
307 name.append(UTF8ToUTF16(base::IntToString(name_index))); | 495 name.append(UTF8ToUTF16(base::IntToString(name_index))); |
308 } | 496 } |
309 | 497 |
310 // Loop through previously named profiles to ensure we're not duplicating. | 498 // Loop through previously named profiles to ensure we're not duplicating. |
311 bool name_found = false; | 499 bool name_found = false; |
312 for (size_t i = 0; i < GetNumberOfProfiles(); ++i) { | 500 for (size_t i = 0; i < GetNumberOfProfiles(); ++i) { |
313 if (GetNameOfProfileAtIndex(i) == name) { | 501 if (GetNameOfProfileAtIndex(i) == name) { |
314 name_found = true; | 502 name_found = true; |
315 break; | 503 break; |
316 } | 504 } |
317 } | 505 } |
318 if (!name_found) | 506 if (!name_found) |
319 return name; | 507 return name; |
320 } | 508 } |
321 } | 509 } |
322 | 510 |
| 511 bool ProfileInfoCache::GetHasMigratedToGAIAInfoOfProfileAtIndex( |
| 512 size_t index) const { |
| 513 bool value = false; |
| 514 GetInfoForProfileAtIndex(index)->GetBoolean( |
| 515 kHasMigratedToGAIAInfoKey, &value); |
| 516 return value; |
| 517 } |
| 518 |
| 519 void ProfileInfoCache::SetHasMigratedToGAIAInfoOfProfileAtIndex( |
| 520 size_t index, bool value) { |
| 521 scoped_ptr<DictionaryValue> info(GetInfoForProfileAtIndex(index)->DeepCopy()); |
| 522 info->SetBoolean(kHasMigratedToGAIAInfoKey, value); |
| 523 // This takes ownership of |info|. |
| 524 SetInfoForProfileAtIndex(index, info.release()); |
| 525 } |
| 526 |
323 bool ProfileInfoCache::IconIndexIsUnique(size_t icon_index) const { | 527 bool ProfileInfoCache::IconIndexIsUnique(size_t icon_index) const { |
324 for (size_t i = 0; i < GetNumberOfProfiles(); ++i) { | 528 for (size_t i = 0; i < GetNumberOfProfiles(); ++i) { |
325 if (GetAvatarIconIndexOfProfileAtIndex(i) == icon_index) | 529 if (GetAvatarIconIndexOfProfileAtIndex(i) == icon_index) |
326 return false; | 530 return false; |
327 } | 531 } |
328 return true; | 532 return true; |
329 } | 533 } |
330 | 534 |
331 bool ProfileInfoCache::ChooseAvatarIconIndexForNewProfile( | 535 bool ProfileInfoCache::ChooseAvatarIconIndexForNewProfile( |
332 bool allow_generic_icon, | 536 bool allow_generic_icon, |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
431 std::string ProfileInfoCache::CacheKeyFromProfilePath( | 635 std::string ProfileInfoCache::CacheKeyFromProfilePath( |
432 const FilePath& profile_path) const { | 636 const FilePath& profile_path) const { |
433 DCHECK(user_data_dir_ == profile_path.DirName()); | 637 DCHECK(user_data_dir_ == profile_path.DirName()); |
434 FilePath base_name = profile_path.BaseName(); | 638 FilePath base_name = profile_path.BaseName(); |
435 return base_name.MaybeAsASCII(); | 639 return base_name.MaybeAsASCII(); |
436 } | 640 } |
437 | 641 |
438 std::vector<std::string>::iterator ProfileInfoCache::FindPositionForProfile( | 642 std::vector<std::string>::iterator ProfileInfoCache::FindPositionForProfile( |
439 std::string search_key, | 643 std::string search_key, |
440 const string16& search_name) { | 644 const string16& search_name) { |
| 645 string16 search_name_l = base::i18n::ToLower(search_name); |
441 for (size_t i = 0; i < GetNumberOfProfiles(); ++i) { | 646 for (size_t i = 0; i < GetNumberOfProfiles(); ++i) { |
442 int name_compare = search_name.compare(GetNameOfProfileAtIndex(i)); | 647 string16 name_l = base::i18n::ToLower(GetNameOfProfileAtIndex(i)); |
| 648 int name_compare = search_name_l.compare(name_l); |
443 if (name_compare < 0) | 649 if (name_compare < 0) |
444 return sorted_keys_.begin() + i; | 650 return sorted_keys_.begin() + i; |
445 if (name_compare == 0) { | 651 if (name_compare == 0) { |
446 int key_compare = search_key.compare(sorted_keys_[i]); | 652 int key_compare = search_key.compare(sorted_keys_[i]); |
447 if (key_compare < 0) | 653 if (key_compare < 0) |
448 return sorted_keys_.begin() + i; | 654 return sorted_keys_.begin() + i; |
449 } | 655 } |
450 } | 656 } |
451 return sorted_keys_.end(); | 657 return sorted_keys_.end(); |
452 } | 658 } |
453 | 659 |
| 660 void ProfileInfoCache::UpdateSortForProfileIndex(size_t index) { |
| 661 string16 name = GetNameOfProfileAtIndex(index); |
| 662 |
| 663 // Remove and reinsert key in |sorted_keys_| to alphasort. |
| 664 std::string key = CacheKeyFromProfilePath(GetPathOfProfileAtIndex(index)); |
| 665 std::vector<std::string>::iterator key_it = |
| 666 std::find(sorted_keys_.begin(), sorted_keys_.end(), key); |
| 667 DCHECK(key_it != sorted_keys_.end()); |
| 668 sorted_keys_.erase(key_it); |
| 669 sorted_keys_.insert(FindPositionForProfile(key, name), key); |
| 670 |
| 671 content::NotificationService::current()->Notify( |
| 672 chrome::NOTIFICATION_PROFILE_CACHED_INFO_CHANGED, |
| 673 content::NotificationService::AllSources(), |
| 674 content::NotificationService::NoDetails()); |
| 675 } |
| 676 |
454 // static | 677 // static |
455 std::vector<string16> ProfileInfoCache::GetProfileNames() { | 678 std::vector<string16> ProfileInfoCache::GetProfileNames() { |
456 std::vector<string16> names; | 679 std::vector<string16> names; |
457 PrefService* local_state = g_browser_process->local_state(); | 680 PrefService* local_state = g_browser_process->local_state(); |
458 const DictionaryValue* cache = local_state->GetDictionary( | 681 const DictionaryValue* cache = local_state->GetDictionary( |
459 prefs::kProfileInfoCache); | 682 prefs::kProfileInfoCache); |
460 string16 name; | 683 string16 name; |
461 for (base::DictionaryValue::key_iterator it = cache->begin_keys(); | 684 for (base::DictionaryValue::key_iterator it = cache->begin_keys(); |
462 it != cache->end_keys(); | 685 it != cache->end_keys(); |
463 ++it) { | 686 ++it) { |
464 base::DictionaryValue* info = NULL; | 687 base::DictionaryValue* info = NULL; |
465 cache->GetDictionary(*it, &info); | 688 cache->GetDictionary(*it, &info); |
466 info->GetString(kNameKey, &name); | 689 info->GetString(kNameKey, &name); |
467 names.push_back(name); | 690 names.push_back(name); |
468 } | 691 } |
469 return names; | 692 return names; |
470 } | 693 } |
471 | 694 |
472 // static | 695 // static |
473 void ProfileInfoCache::RegisterPrefs(PrefService* prefs) { | 696 void ProfileInfoCache::RegisterPrefs(PrefService* prefs) { |
474 prefs->RegisterDictionaryPref(prefs::kProfileInfoCache); | 697 prefs->RegisterDictionaryPref(prefs::kProfileInfoCache); |
475 } | 698 } |
OLD | NEW |