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

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

Issue 222313005: [Profiles] Download high-res avatars using the --new-profile-management flag (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 8 months 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) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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" 7 #include "base/bind.h"
8 #include "base/file_util.h" 8 #include "base/file_util.h"
9 #include "base/i18n/case_conversion.h" 9 #include "base/i18n/case_conversion.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
11 #include "base/memory/scoped_ptr.h" 11 #include "base/memory/scoped_ptr.h"
12 #include "base/path_service.h"
13 #include "base/prefs/pref_registry_simple.h" 12 #include "base/prefs/pref_registry_simple.h"
14 #include "base/prefs/pref_service.h" 13 #include "base/prefs/pref_service.h"
15 #include "base/prefs/scoped_user_pref_update.h" 14 #include "base/prefs/scoped_user_pref_update.h"
16 #include "base/rand_util.h" 15 #include "base/rand_util.h"
17 #include "base/stl_util.h" 16 #include "base/stl_util.h"
18 #include "base/strings/string_number_conversions.h" 17 #include "base/strings/string_number_conversions.h"
19 #include "base/strings/string_piece.h" 18 #include "base/strings/string_piece.h"
20 #include "base/strings/utf_string_conversions.h" 19 #include "base/strings/utf_string_conversions.h"
21 #include "base/values.h" 20 #include "base/values.h"
22 #include "chrome/browser/browser_process.h" 21 #include "chrome/browser/browser_process.h"
23 #include "chrome/browser/chrome_notification_types.h" 22 #include "chrome/browser/chrome_notification_types.h"
23 #include "chrome/browser/profiles/profile_avatar_downloader.h"
24 #include "chrome/browser/profiles/profile_avatar_icon_util.h" 24 #include "chrome/browser/profiles/profile_avatar_icon_util.h"
25 #include "chrome/common/chrome_paths.h" 25 #include "chrome/browser/profiles/profiles_state.h"
26 #include "chrome/common/pref_names.h" 26 #include "chrome/common/pref_names.h"
27 #include "chrome/common/profile_management_switches.h" 27 #include "chrome/common/profile_management_switches.h"
28 #include "content/public/browser/browser_thread.h" 28 #include "content/public/browser/browser_thread.h"
29 #include "content/public/browser/notification_service.h" 29 #include "content/public/browser/notification_service.h"
30 #include "grit/generated_resources.h" 30 #include "grit/generated_resources.h"
31 #include "grit/theme_resources.h" 31 #include "grit/theme_resources.h"
32 #include "third_party/skia/include/core/SkBitmap.h" 32 #include "third_party/skia/include/core/SkBitmap.h"
33 #include "ui/base/l10n/l10n_util.h" 33 #include "ui/base/l10n/l10n_util.h"
34 #include "ui/base/resource/resource_bundle.h" 34 #include "ui/base/resource/resource_bundle.h"
35 #include "ui/gfx/image/image.h" 35 #include "ui/gfx/image/image.h"
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
185 info->Remove(kIsManagedKey, NULL); 185 info->Remove(kIsManagedKey, NULL);
186 info->SetString(kManagedUserId, is_managed ? "DUMMY_ID" : std::string()); 186 info->SetString(kManagedUserId, is_managed ? "DUMMY_ID" : std::string());
187 } 187 }
188 info->SetBoolean(kIsUsingDefaultName, IsDefaultName(name)); 188 info->SetBoolean(kIsUsingDefaultName, IsDefaultName(name));
189 } 189 }
190 } 190 }
191 191
192 ProfileInfoCache::~ProfileInfoCache() { 192 ProfileInfoCache::~ProfileInfoCache() {
193 STLDeleteContainerPairSecondPointers( 193 STLDeleteContainerPairSecondPointers(
194 cached_avatar_images_.begin(), cached_avatar_images_.end()); 194 cached_avatar_images_.begin(), cached_avatar_images_.end());
195 STLDeleteContainerPairSecondPointers(
196 avatar_images_downloads_in_progress_.begin(),
197 avatar_images_downloads_in_progress_.end());
195 } 198 }
196 199
197 void ProfileInfoCache::AddProfileToCache(const base::FilePath& profile_path, 200 void ProfileInfoCache::AddProfileToCache(const base::FilePath& profile_path,
198 const base::string16& name, 201 const base::string16& name,
199 const base::string16& username, 202 const base::string16& username,
200 size_t icon_index, 203 size_t icon_index,
201 const std::string& managed_user_id) { 204 const std::string& managed_user_id) {
202 std::string key = CacheKeyFromProfilePath(profile_path); 205 std::string key = CacheKeyFromProfilePath(profile_path);
203 DictionaryPrefUpdate update(prefs_, prefs::kProfileInfoCache); 206 DictionaryPrefUpdate update(prefs_, prefs::kProfileInfoCache);
204 base::DictionaryValue* cache = update.Get(); 207 base::DictionaryValue* cache = update.Get();
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
323 } 326 }
324 327
325 const gfx::Image& ProfileInfoCache::GetAvatarIconOfProfileAtIndex( 328 const gfx::Image& ProfileInfoCache::GetAvatarIconOfProfileAtIndex(
326 size_t index) const { 329 size_t index) const {
327 if (IsUsingGAIAPictureOfProfileAtIndex(index)) { 330 if (IsUsingGAIAPictureOfProfileAtIndex(index)) {
328 const gfx::Image* image = GetGAIAPictureOfProfileAtIndex(index); 331 const gfx::Image* image = GetGAIAPictureOfProfileAtIndex(index);
329 if (image) 332 if (image)
330 return *image; 333 return *image;
331 } 334 }
332 335
333 // Use the high resolution version of the avatar if it exists. 336 // Use the high resolution version of the avatar if it exists.
334 if (switches::IsNewProfileManagement()) { 337 if (switches::IsNewProfileManagement()) {
335 const gfx::Image* image = GetHighResAvatarOfProfileAtIndex(index); 338 const gfx::Image* image = GetHighResAvatarOfProfileAtIndex(index);
336 if (image) 339 if (image)
337 return *image; 340 return *image;
338 } 341 }
339 342
340 int resource_id = profiles::GetDefaultAvatarIconResourceIDAtIndex( 343 int resource_id = profiles::GetDefaultAvatarIconResourceIDAtIndex(
341 GetAvatarIconIndexOfProfileAtIndex(index)); 344 GetAvatarIconIndexOfProfileAtIndex(index));
342 return ResourceBundle::GetSharedInstance().GetNativeImageNamed(resource_id); 345 return ResourceBundle::GetSharedInstance().GetNativeImageNamed(resource_id);
343 } 346 }
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
383 kGAIAPictureFileNameKey, &file_name); 386 kGAIAPictureFileNameKey, &file_name);
384 387
385 // If the picture is not on disk then return NULL. 388 // If the picture is not on disk then return NULL.
386 if (file_name.empty()) 389 if (file_name.empty())
387 return NULL; 390 return NULL;
388 391
389 base::FilePath image_path = path.AppendASCII(file_name); 392 base::FilePath image_path = path.AppendASCII(file_name);
390 return LoadAvatarPictureFromPath(key, image_path); 393 return LoadAvatarPictureFromPath(key, image_path);
391 } 394 }
392 395
393 const gfx::Image* ProfileInfoCache::GetHighResAvatarOfProfileAtIndex(
394 size_t index) const {
395 int avatar_index = GetAvatarIconIndexOfProfileAtIndex(index);
396 std::string key = profiles::GetDefaultAvatarIconFileNameAtIndex(avatar_index);
397
398 base::FilePath user_data_dir;
399 PathService::Get(chrome::DIR_USER_DATA, &user_data_dir);
400 base::FilePath image_path = user_data_dir.
401 AppendASCII(profiles::kHighResAvatarFolderName).AppendASCII(key);
402 return LoadAvatarPictureFromPath(key, image_path);
403 }
404
405 const gfx::Image* ProfileInfoCache::LoadAvatarPictureFromPath(
406 const std::string& key,
407 const base::FilePath& image_path) const {
408 // If the picture is already loaded then use it.
409 if (cached_avatar_images_.count(key)) {
410 if (cached_avatar_images_[key]->IsEmpty())
411 return NULL;
412 return cached_avatar_images_[key];
413 }
414
415 // If the picture is already being loaded then don't try loading it again.
416 if (cached_avatar_images_loading_[key])
417 return NULL;
418 cached_avatar_images_loading_[key] = true;
419
420 gfx::Image** image = new gfx::Image*;
421 BrowserThread::PostTaskAndReply(BrowserThread::FILE, FROM_HERE,
422 base::Bind(&ReadBitmap, image_path, image),
423 base::Bind(&ProfileInfoCache::OnAvatarPictureLoaded,
424 const_cast<ProfileInfoCache*>(this)->AsWeakPtr(), key, image));
425 return NULL;
426 }
427
428 bool ProfileInfoCache::ProfileIsManagedAtIndex(size_t index) const { 396 bool ProfileInfoCache::ProfileIsManagedAtIndex(size_t index) const {
429 return !GetManagedUserIdOfProfileAtIndex(index).empty(); 397 return !GetManagedUserIdOfProfileAtIndex(index).empty();
430 } 398 }
431 399
432 bool ProfileInfoCache::IsOmittedProfileAtIndex(size_t index) const { 400 bool ProfileInfoCache::IsOmittedProfileAtIndex(size_t index) const {
433 bool value = false; 401 bool value = false;
434 GetInfoForProfileAtIndex(index)->GetBoolean(kIsOmittedFromProfileListKey, 402 GetInfoForProfileAtIndex(index)->GetBoolean(kIsOmittedFromProfileListKey,
435 &value); 403 &value);
436 return value; 404 return value;
437 } 405 }
(...skipping 16 matching lines...) Expand all
454 GetInfoForProfileAtIndex(index)->GetBoolean(kProfileIsEphemeral, &value); 422 GetInfoForProfileAtIndex(index)->GetBoolean(kProfileIsEphemeral, &value);
455 return value; 423 return value;
456 } 424 }
457 425
458 bool ProfileInfoCache::ProfileIsUsingDefaultNameAtIndex(size_t index) const { 426 bool ProfileInfoCache::ProfileIsUsingDefaultNameAtIndex(size_t index) const {
459 bool value = false; 427 bool value = false;
460 GetInfoForProfileAtIndex(index)->GetBoolean(kIsUsingDefaultName, &value); 428 GetInfoForProfileAtIndex(index)->GetBoolean(kIsUsingDefaultName, &value);
461 return value; 429 return value;
462 } 430 }
463 431
464 void ProfileInfoCache::OnAvatarPictureLoaded(const std::string& key,
465 gfx::Image** image) const {
466 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
467
468 cached_avatar_images_loading_[key] = false;
469
470 delete cached_avatar_images_[key];
471 if (*image) {
472 cached_avatar_images_[key] = *image;
473 } else {
474 // Place an empty image in the cache to avoid reloading it again.
475 cached_avatar_images_[key] = new gfx::Image();
476 }
477 delete image;
478
479 content::NotificationService::current()->Notify(
480 chrome::NOTIFICATION_PROFILE_CACHED_INFO_CHANGED,
481 content::NotificationService::AllSources(),
482 content::NotificationService::NoDetails());
483 }
484
485 void ProfileInfoCache::OnGAIAPictureSaved(const base::FilePath& path,
486 bool* success) const {
487 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
488
489 if (*success) {
490 content::NotificationService::current()->Notify(
491 chrome::NOTIFICATION_PROFILE_CACHE_PICTURE_SAVED,
492 content::NotificationService::AllSources(),
493 content::NotificationService::NoDetails());
494 }
495 delete success;
496 }
497
498 bool ProfileInfoCache::IsUsingGAIAPictureOfProfileAtIndex( 432 bool ProfileInfoCache::IsUsingGAIAPictureOfProfileAtIndex(
499 size_t index) const { 433 size_t index) const {
500 bool value = false; 434 bool value = false;
501 GetInfoForProfileAtIndex(index)->GetBoolean(kUseGAIAPictureKey, &value); 435 GetInfoForProfileAtIndex(index)->GetBoolean(kUseGAIAPictureKey, &value);
502 return value; 436 return value;
503 } 437 }
504 438
505 size_t ProfileInfoCache::GetAvatarIconIndexOfProfileAtIndex(size_t index) 439 size_t ProfileInfoCache::GetAvatarIconIndexOfProfileAtIndex(size_t index)
506 const { 440 const {
507 std::string icon_url; 441 std::string icon_url;
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after
684 618
685 if (!image) { 619 if (!image) {
686 // Delete the old bitmap from disk. 620 // Delete the old bitmap from disk.
687 if (!old_file_name.empty()) { 621 if (!old_file_name.empty()) {
688 base::FilePath image_path = path.AppendASCII(old_file_name); 622 base::FilePath image_path = path.AppendASCII(old_file_name);
689 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, 623 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
690 base::Bind(&DeleteBitmap, image_path)); 624 base::Bind(&DeleteBitmap, image_path));
691 } 625 }
692 } else { 626 } else {
693 // Save the new bitmap to disk. 627 // Save the new bitmap to disk.
694 cached_avatar_images_[key] = new gfx::Image(*image); 628 new_file_name =
695 scoped_ptr<ImageData> data(new ImageData); 629 old_file_name.empty() ? profiles::kGAIAPictureFileName : old_file_name;
696 scoped_refptr<base::RefCountedMemory> png_data = image->As1xPNGBytes(); 630 base::FilePath image_path = path.AppendASCII(new_file_name);
697 data->assign(png_data->front(), png_data->front() + png_data->size()); 631 SaveAvatarImageAtPath(image, key, image_path);
698 if (!data->size()) {
699 LOG(ERROR) << "Failed to PNG encode the image.";
700 } else {
701 new_file_name = old_file_name.empty() ?
702 profiles::kGAIAPictureFileName : old_file_name;
703 base::FilePath image_path = path.AppendASCII(new_file_name);
704 bool* success = new bool;
705 BrowserThread::PostTaskAndReply(BrowserThread::FILE, FROM_HERE,
706 base::Bind(&SaveBitmap, data.release(), image_path, success),
707 base::Bind(&ProfileInfoCache::OnGAIAPictureSaved, AsWeakPtr(),
708 path, success));
709 }
710 } 632 }
711 633
712 scoped_ptr<base::DictionaryValue> info( 634 scoped_ptr<base::DictionaryValue> info(
713 GetInfoForProfileAtIndex(index)->DeepCopy()); 635 GetInfoForProfileAtIndex(index)->DeepCopy());
714 info->SetString(kGAIAPictureFileNameKey, new_file_name); 636 info->SetString(kGAIAPictureFileNameKey, new_file_name);
715 // This takes ownership of |info|. 637 // This takes ownership of |info|.
716 SetInfoForProfileAtIndex(index, info.release()); 638 SetInfoForProfileAtIndex(index, info.release());
717 639
718 FOR_EACH_OBSERVER(ProfileInfoCacheObserver, 640 FOR_EACH_OBSERVER(ProfileInfoCacheObserver,
719 observer_list_, 641 observer_list_,
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after
920 DCHECK(key_it != sorted_keys_.end()); 842 DCHECK(key_it != sorted_keys_.end());
921 sorted_keys_.erase(key_it); 843 sorted_keys_.erase(key_it);
922 sorted_keys_.insert(FindPositionForProfile(key, name), key); 844 sorted_keys_.insert(FindPositionForProfile(key, name), key);
923 845
924 content::NotificationService::current()->Notify( 846 content::NotificationService::current()->Notify(
925 chrome::NOTIFICATION_PROFILE_CACHED_INFO_CHANGED, 847 chrome::NOTIFICATION_PROFILE_CACHED_INFO_CHANGED,
926 content::NotificationService::AllSources(), 848 content::NotificationService::AllSources(),
927 content::NotificationService::NoDetails()); 849 content::NotificationService::NoDetails());
928 } 850 }
929 851
852 const gfx::Image* ProfileInfoCache::GetHighResAvatarOfProfileAtIndex(
853 size_t index) const {
854 int avatar_index = GetAvatarIconIndexOfProfileAtIndex(index);
855 std::string key = profiles::GetDefaultAvatarIconFileNameAtIndex(avatar_index);
856 base::FilePath image_path =
857 profiles::GetPathOfHighResAvatarAtIndex(avatar_index);
858 return LoadAvatarPictureFromPath(key, image_path);
859 }
860
861 const gfx::Image* ProfileInfoCache::LoadAvatarPictureFromPath(
862 const std::string& key,
863 const base::FilePath& image_path) const {
864 // If the picture is already loaded then use it.
865 if (cached_avatar_images_.count(key)) {
866 if (cached_avatar_images_[key]->IsEmpty())
867 return NULL;
868 return cached_avatar_images_[key];
869 }
870
871 // If the picture is already being loaded then don't try loading it again.
872 if (cached_avatar_images_loading_[key])
873 return NULL;
874 cached_avatar_images_loading_[key] = true;
875
876 gfx::Image** image = new gfx::Image*;
877 BrowserThread::PostTaskAndReply(BrowserThread::FILE, FROM_HERE,
878 base::Bind(&ReadBitmap, image_path, image),
879 base::Bind(&ProfileInfoCache::OnAvatarPictureLoaded,
880 const_cast<ProfileInfoCache*>(this)->AsWeakPtr(), key, image));
881 return NULL;
882 }
883
884 void ProfileInfoCache::OnAvatarPictureLoaded(const std::string& key,
885 gfx::Image** image) const {
886 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
887
888 cached_avatar_images_loading_[key] = false;
889 delete cached_avatar_images_[key];
890
891 if (*image) {
892 cached_avatar_images_[key] = *image;
893 } else {
894 // Place an empty image in the cache to avoid reloading it again.
895 cached_avatar_images_[key] = new gfx::Image();
896 }
897 delete image;
898
899 content::NotificationService::current()->Notify(
900 chrome::NOTIFICATION_PROFILE_CACHED_INFO_CHANGED,
901 content::NotificationService::AllSources(),
902 content::NotificationService::NoDetails());
903 }
904
905 void ProfileInfoCache::OnAvatarPictureSaved(const std::string& file_name,
906 bool* success) {
907
908 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
909
910 // Remove the file from the list of downloads in progress. Note that this list
911 // only contains the high resolution avatars, and not the Gaia profile images.
912 if (!avatar_images_downloads_in_progress_[file_name])
913 return;
914
915 delete avatar_images_downloads_in_progress_[file_name];
916 avatar_images_downloads_in_progress_[file_name] = NULL;
917
918 if (*success) {
919 content::NotificationService::current()->Notify(
920 chrome::NOTIFICATION_PROFILE_CACHED_INFO_CHANGED,
921 content::NotificationService::AllSources(),
922 content::NotificationService::NoDetails());
923 }
924 delete success;
925 }
926
930 // static 927 // static
931 std::vector<base::string16> ProfileInfoCache::GetProfileNames() { 928 std::vector<base::string16> ProfileInfoCache::GetProfileNames() {
932 std::vector<base::string16> names; 929 std::vector<base::string16> names;
933 PrefService* local_state = g_browser_process->local_state(); 930 PrefService* local_state = g_browser_process->local_state();
934 const base::DictionaryValue* cache = local_state->GetDictionary( 931 const base::DictionaryValue* cache = local_state->GetDictionary(
935 prefs::kProfileInfoCache); 932 prefs::kProfileInfoCache);
936 base::string16 name; 933 base::string16 name;
937 for (base::DictionaryValue::Iterator it(*cache); !it.IsAtEnd(); 934 for (base::DictionaryValue::Iterator it(*cache); !it.IsAtEnd();
938 it.Advance()) { 935 it.Advance()) {
939 const base::DictionaryValue* info = NULL; 936 const base::DictionaryValue* info = NULL;
940 it.value().GetAsDictionary(&info); 937 it.value().GetAsDictionary(&info);
941 info->GetString(kNameKey, &name); 938 info->GetString(kNameKey, &name);
942 names.push_back(name); 939 names.push_back(name);
943 } 940 }
944 return names; 941 return names;
945 } 942 }
946 943
947 // static 944 // static
948 void ProfileInfoCache::RegisterPrefs(PrefRegistrySimple* registry) { 945 void ProfileInfoCache::RegisterPrefs(PrefRegistrySimple* registry) {
949 registry->RegisterDictionaryPref(prefs::kProfileInfoCache); 946 registry->RegisterDictionaryPref(prefs::kProfileInfoCache);
950 } 947 }
948
949 void ProfileInfoCache::DownloadHighResAvatar(
950 ProfileAvatarDownloader* avatar_downloader,
951 size_t icon_index) {
952 std::string file_name = profiles::GetDefaultAvatarIconFileNameAtIndex(
953 icon_index);
954 // If the file is already being downloaded, don't start another download.
955 if (avatar_images_downloads_in_progress_[file_name])
956 return;
957 avatar_images_downloads_in_progress_[file_name] = avatar_downloader;
958 avatar_downloader->Start();
959 }
960
961 void ProfileInfoCache::SaveAvatarImageAtPath(
962 const gfx::Image* image,
963 const std::string& key,
964 const base::FilePath& image_path) {
965
966 cached_avatar_images_[key] = new gfx::Image(*image);
967
968 scoped_ptr<ImageData> data(new ImageData);
969 scoped_refptr<base::RefCountedMemory> png_data = image->As1xPNGBytes();
970 data->assign(png_data->front(), png_data->front() + png_data->size());
971
972 if (!data->size()) {
973 LOG(ERROR) << "Failed to PNG encode the image.";
974 } else {
975 bool* success = new bool;
976 BrowserThread::PostTaskAndReply(BrowserThread::FILE, FROM_HERE,
977 base::Bind(&SaveBitmap, data.release(), image_path, success),
978 base::Bind(&ProfileInfoCache::OnAvatarPictureSaved, AsWeakPtr(),
979 key, success));
980 }
981 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698