| 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 |