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

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

Issue 861053004: [Profiles] Send out less profile avatar related notifications (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: mike nit Created 5 years, 10 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
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/files/file_util.h" 8 #include "base/files/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"
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
128 gfx::Image image = gfx::Image::CreateFrom1xPNGBytes( 128 gfx::Image image = gfx::Image::CreateFrom1xPNGBytes(
129 base::RefCountedString::TakeString(&image_data)); 129 base::RefCountedString::TakeString(&image_data));
130 if (image.IsEmpty()) { 130 if (image.IsEmpty()) {
131 LOG(ERROR) << "Failed to decode PNG file."; 131 LOG(ERROR) << "Failed to decode PNG file.";
132 return; 132 return;
133 } 133 }
134 134
135 *out_image = new gfx::Image(image); 135 *out_image = new gfx::Image(image);
136 } 136 }
137 137
138 void RunCallbackIfFileMissing(const base::FilePath& file_path,
139 const base::Closure& callback) {
140 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
141 if (!base::PathExists(file_path))
142 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback);
143 }
144
138 void DeleteBitmap(const base::FilePath& image_path) { 145 void DeleteBitmap(const base::FilePath& image_path) {
139 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 146 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
140 base::DeleteFile(image_path, false); 147 base::DeleteFile(image_path, false);
141 } 148 }
142 149
143 } // namespace 150 } // namespace
144 151
145 ProfileInfoCache::ProfileInfoCache(PrefService* prefs, 152 ProfileInfoCache::ProfileInfoCache(PrefService* prefs,
146 const base::FilePath& user_data_dir) 153 const base::FilePath& user_data_dir)
147 : prefs_(prefs), 154 : prefs_(prefs),
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
207 info->SetBoolean(kIsOmittedFromProfileListKey, !supervised_user_id.empty()); 214 info->SetBoolean(kIsOmittedFromProfileListKey, !supervised_user_id.empty());
208 info->SetBoolean(kProfileIsEphemeral, false); 215 info->SetBoolean(kProfileIsEphemeral, false);
209 info->SetBoolean(kIsUsingDefaultNameKey, IsDefaultProfileName(name)); 216 info->SetBoolean(kIsUsingDefaultNameKey, IsDefaultProfileName(name));
210 // Assume newly created profiles use a default avatar. 217 // Assume newly created profiles use a default avatar.
211 info->SetBoolean(kIsUsingDefaultAvatarKey, true); 218 info->SetBoolean(kIsUsingDefaultAvatarKey, true);
212 cache->SetWithoutPathExpansion(key, info.release()); 219 cache->SetWithoutPathExpansion(key, info.release());
213 220
214 sorted_keys_.insert(FindPositionForProfile(key, name), key); 221 sorted_keys_.insert(FindPositionForProfile(key, name), key);
215 222
216 if (switches::IsNewAvatarMenu()) 223 if (switches::IsNewAvatarMenu())
217 DownloadHighResAvatar(icon_index, profile_path); 224 DownloadHighResAvatarIfNeeded(icon_index, profile_path);
218 225
219 FOR_EACH_OBSERVER(ProfileInfoCacheObserver, 226 FOR_EACH_OBSERVER(ProfileInfoCacheObserver,
220 observer_list_, 227 observer_list_,
221 OnProfileAdded(profile_path)); 228 OnProfileAdded(profile_path));
222 229
223 content::NotificationService::current()->Notify( 230 content::NotificationService::current()->Notify(
224 chrome::NOTIFICATION_PROFILE_CACHED_INFO_CHANGED, 231 chrome::NOTIFICATION_PROFILE_CACHED_INFO_CHANGED,
225 content::NotificationService::AllSources(), 232 content::NotificationService::AllSources(),
226 content::NotificationService::NoDetails()); 233 content::NotificationService::NoDetails());
227 } 234 }
(...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after
529 size_t icon_index) { 536 size_t icon_index) {
530 scoped_ptr<base::DictionaryValue> info( 537 scoped_ptr<base::DictionaryValue> info(
531 GetInfoForProfileAtIndex(index)->DeepCopy()); 538 GetInfoForProfileAtIndex(index)->DeepCopy());
532 info->SetString(kAvatarIconKey, 539 info->SetString(kAvatarIconKey,
533 profiles::GetDefaultAvatarIconUrl(icon_index)); 540 profiles::GetDefaultAvatarIconUrl(icon_index));
534 // This takes ownership of |info|. 541 // This takes ownership of |info|.
535 SetInfoForProfileAtIndex(index, info.release()); 542 SetInfoForProfileAtIndex(index, info.release());
536 543
537 base::FilePath profile_path = GetPathOfProfileAtIndex(index); 544 base::FilePath profile_path = GetPathOfProfileAtIndex(index);
538 545
539 // If needed, start downloading the high-res avatar.
540 if (switches::IsNewAvatarMenu()) 546 if (switches::IsNewAvatarMenu())
541 DownloadHighResAvatar(icon_index, profile_path); 547 DownloadHighResAvatarIfNeeded(icon_index, profile_path);
542 548
543 FOR_EACH_OBSERVER(ProfileInfoCacheObserver, 549 FOR_EACH_OBSERVER(ProfileInfoCacheObserver,
544 observer_list_, 550 observer_list_,
545 OnProfileAvatarChanged(profile_path)); 551 OnProfileAvatarChanged(profile_path));
546 } 552 }
547 553
548 void ProfileInfoCache::SetIsOmittedProfileAtIndex(size_t index, 554 void ProfileInfoCache::SetIsOmittedProfileAtIndex(size_t index,
549 bool is_omitted) { 555 bool is_omitted) {
550 if (IsOmittedProfileAtIndex(index) == is_omitted) 556 if (IsOmittedProfileAtIndex(index) == is_omitted)
551 return; 557 return;
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
686 } 692 }
687 693
688 void ProfileInfoCache::SetIsUsingGAIAPictureOfProfileAtIndex(size_t index, 694 void ProfileInfoCache::SetIsUsingGAIAPictureOfProfileAtIndex(size_t index,
689 bool value) { 695 bool value) {
690 scoped_ptr<base::DictionaryValue> info( 696 scoped_ptr<base::DictionaryValue> info(
691 GetInfoForProfileAtIndex(index)->DeepCopy()); 697 GetInfoForProfileAtIndex(index)->DeepCopy());
692 info->SetBoolean(kUseGAIAPictureKey, value); 698 info->SetBoolean(kUseGAIAPictureKey, value);
693 // This takes ownership of |info|. 699 // This takes ownership of |info|.
694 SetInfoForProfileAtIndex(index, info.release()); 700 SetInfoForProfileAtIndex(index, info.release());
695 701
696 // Retrieve some info to update observers who care about avatar changes.
697 base::FilePath profile_path = GetPathOfProfileAtIndex(index); 702 base::FilePath profile_path = GetPathOfProfileAtIndex(index);
698 FOR_EACH_OBSERVER(ProfileInfoCacheObserver, 703 FOR_EACH_OBSERVER(ProfileInfoCacheObserver,
699 observer_list_, 704 observer_list_,
700 OnProfileAvatarChanged(profile_path)); 705 OnProfileAvatarChanged(profile_path));
701 } 706 }
702 707
703 void ProfileInfoCache::SetProfileSigninRequiredAtIndex(size_t index, 708 void ProfileInfoCache::SetProfileSigninRequiredAtIndex(size_t index,
704 bool value) { 709 bool value) {
705 if (value == ProfileIsSigninRequiredAtIndex(index)) 710 if (value == ProfileIsSigninRequiredAtIndex(index))
706 return; 711 return;
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
841 names.push_back(name); 846 names.push_back(name);
842 } 847 }
843 return names; 848 return names;
844 } 849 }
845 850
846 // static 851 // static
847 void ProfileInfoCache::RegisterPrefs(PrefRegistrySimple* registry) { 852 void ProfileInfoCache::RegisterPrefs(PrefRegistrySimple* registry) {
848 registry->RegisterDictionaryPref(prefs::kProfileInfoCache); 853 registry->RegisterDictionaryPref(prefs::kProfileInfoCache);
849 } 854 }
850 855
851 void ProfileInfoCache::DownloadHighResAvatar( 856 void ProfileInfoCache::DownloadHighResAvatarIfNeeded(
852 size_t icon_index, 857 size_t icon_index,
853 const base::FilePath& profile_path) { 858 const base::FilePath& profile_path) {
854 // Downloading is only supported on desktop. 859 // Downloading is only supported on desktop.
855 #if defined(OS_ANDROID) || defined(OS_IOS) || defined(OS_CHROMEOS) 860 #if defined(OS_ANDROID) || defined(OS_IOS) || defined(OS_CHROMEOS)
856 return; 861 return;
857 #endif 862 #endif
858 863
859 // TODO(noms): We should check whether the file already exists on disk 864 const base::FilePath& file_path =
860 // before trying to re-download it. For now, since this is behind a flag and 865 profiles::GetPathOfHighResAvatarAtIndex(icon_index);
861 // the resources are still changing, re-download it every time the profile 866 base::Closure callback =
862 // avatar changes, to make sure we have the latest copy. 867 base::Bind(&ProfileInfoCache::DownloadHighResAvatar,
863 std::string file_name = profiles::GetDefaultAvatarIconFileNameAtIndex( 868 AsWeakPtr(),
864 icon_index); 869 icon_index,
865 // If the file is already being downloaded, don't start another download. 870 profile_path);
866 if (avatar_images_downloads_in_progress_[file_name]) 871 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
867 return; 872 base::Bind(&RunCallbackIfFileMissing, file_path, callback));
868
869 // Start the download for this file. The cache takes ownership of the
870 // |avatar_downloader|, which will be deleted when the download completes, or
871 // if that never happens, when the ProfileInfoCache is destroyed.
872 ProfileAvatarDownloader* avatar_downloader = new ProfileAvatarDownloader(
873 icon_index,
874 profile_path,
875 this);
876 avatar_images_downloads_in_progress_[file_name] = avatar_downloader;
877 avatar_downloader->Start();
878 } 873 }
879 874
880 void ProfileInfoCache::SaveAvatarImageAtPath( 875 void ProfileInfoCache::SaveAvatarImageAtPath(
881 const gfx::Image* image, 876 const gfx::Image* image,
882 const std::string& key, 877 const std::string& key,
883 const base::FilePath& image_path, 878 const base::FilePath& image_path,
884 const base::FilePath& profile_path) { 879 const base::FilePath& profile_path) {
885 cached_avatar_images_[key] = new gfx::Image(*image); 880 cached_avatar_images_[key] = new gfx::Image(*image);
886 881
887 scoped_ptr<ImageData> data(new ImageData); 882 scoped_ptr<ImageData> data(new ImageData);
888 scoped_refptr<base::RefCountedMemory> png_data = image->As1xPNGBytes(); 883 scoped_refptr<base::RefCountedMemory> png_data = image->As1xPNGBytes();
889 data->assign(png_data->front(), png_data->front() + png_data->size()); 884 data->assign(png_data->front(), png_data->front() + png_data->size());
890 885
886 // Remove the file from the list of downloads in progress. Note that this list
887 // only contains the high resolution avatars, and not the Gaia profile images.
888 if (avatar_images_downloads_in_progress_[key]) {
889 delete avatar_images_downloads_in_progress_[key];
890 avatar_images_downloads_in_progress_[key] = NULL;
891 }
892
891 if (!data->size()) { 893 if (!data->size()) {
892 LOG(ERROR) << "Failed to PNG encode the image."; 894 LOG(ERROR) << "Failed to PNG encode the image.";
893 } else { 895 } else {
894 base::Closure callback = base::Bind(&ProfileInfoCache::OnAvatarPictureSaved, 896 base::Closure callback = base::Bind(&ProfileInfoCache::OnAvatarPictureSaved,
895 AsWeakPtr(), key, profile_path); 897 AsWeakPtr(), key, profile_path);
896
897 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, 898 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
898 base::Bind(&SaveBitmap, base::Passed(&data), image_path, callback)); 899 base::Bind(&SaveBitmap, base::Passed(&data), image_path, callback));
899 } 900 }
900 } 901 }
901 902
902 const base::DictionaryValue* ProfileInfoCache::GetInfoForProfileAtIndex( 903 const base::DictionaryValue* ProfileInfoCache::GetInfoForProfileAtIndex(
903 size_t index) const { 904 size_t index) const {
904 DCHECK_LT(index, GetNumberOfProfiles()); 905 DCHECK_LT(index, GetNumberOfProfiles());
905 const base::DictionaryValue* cache = 906 const base::DictionaryValue* cache =
906 prefs_->GetDictionary(prefs::kProfileInfoCache); 907 prefs_->GetDictionary(prefs::kProfileInfoCache);
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
1008 1009
1009 if (!strcmp(key.c_str(), profiles::GetNoHighResAvatarFileName())) 1010 if (!strcmp(key.c_str(), profiles::GetNoHighResAvatarFileName()))
1010 return NULL; 1011 return NULL;
1011 1012
1012 base::FilePath image_path = 1013 base::FilePath image_path =
1013 profiles::GetPathOfHighResAvatarAtIndex(avatar_index); 1014 profiles::GetPathOfHighResAvatarAtIndex(avatar_index);
1014 return LoadAvatarPictureFromPath(GetPathOfProfileAtIndex(index), 1015 return LoadAvatarPictureFromPath(GetPathOfProfileAtIndex(index),
1015 key, image_path); 1016 key, image_path);
1016 } 1017 }
1017 1018
1019 void ProfileInfoCache::DownloadHighResAvatar(
1020 size_t icon_index,
1021 const base::FilePath& profile_path) {
1022 // Downloading is only supported on desktop.
1023 #if defined(OS_ANDROID) || defined(OS_IOS) || defined(OS_CHROMEOS)
1024 return;
1025 #endif
1026 const std::string file_name =
1027 profiles::GetDefaultAvatarIconFileNameAtIndex(icon_index);
1028 // If the file is already being downloaded, don't start another download.
1029 if (avatar_images_downloads_in_progress_[file_name])
1030 return;
1031
1032 // Start the download for this file. The cache takes ownership of the
1033 // |avatar_downloader|, which will be deleted when the download completes, or
1034 // if that never happens, when the ProfileInfoCache is destroyed.
1035 ProfileAvatarDownloader* avatar_downloader = new ProfileAvatarDownloader(
1036 icon_index,
1037 profile_path,
1038 this);
1039 avatar_images_downloads_in_progress_[file_name] = avatar_downloader;
1040 avatar_downloader->Start();
1041 }
1042
1018 const gfx::Image* ProfileInfoCache::LoadAvatarPictureFromPath( 1043 const gfx::Image* ProfileInfoCache::LoadAvatarPictureFromPath(
1019 const base::FilePath& profile_path, 1044 const base::FilePath& profile_path,
1020 const std::string& key, 1045 const std::string& key,
1021 const base::FilePath& image_path) const { 1046 const base::FilePath& image_path) const {
1022 // If the picture is already loaded then use it. 1047 // If the picture is already loaded then use it.
1023 if (cached_avatar_images_.count(key)) { 1048 if (cached_avatar_images_.count(key)) {
1024 if (cached_avatar_images_[key]->IsEmpty()) 1049 if (cached_avatar_images_[key]->IsEmpty())
1025 return NULL; 1050 return NULL;
1026 return cached_avatar_images_[key]; 1051 return cached_avatar_images_[key];
1027 } 1052 }
(...skipping 28 matching lines...) Expand all
1056 } 1081 }
1057 delete image; 1082 delete image;
1058 1083
1059 content::NotificationService::current()->Notify( 1084 content::NotificationService::current()->Notify(
1060 chrome::NOTIFICATION_PROFILE_CACHED_INFO_CHANGED, 1085 chrome::NOTIFICATION_PROFILE_CACHED_INFO_CHANGED,
1061 content::NotificationService::AllSources(), 1086 content::NotificationService::AllSources(),
1062 content::NotificationService::NoDetails()); 1087 content::NotificationService::NoDetails());
1063 1088
1064 FOR_EACH_OBSERVER(ProfileInfoCacheObserver, 1089 FOR_EACH_OBSERVER(ProfileInfoCacheObserver,
1065 observer_list_, 1090 observer_list_,
1066 OnProfileAvatarChanged(profile_path)); 1091 OnProfileHighResAvatarLoaded(profile_path));
1067 } 1092 }
1068 1093
1069 void ProfileInfoCache::OnAvatarPictureSaved( 1094 void ProfileInfoCache::OnAvatarPictureSaved(
1070 const std::string& file_name, 1095 const std::string& file_name,
1071 const base::FilePath& profile_path) { 1096 const base::FilePath& profile_path) {
1072 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1097 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1073 1098
1074 content::NotificationService::current()->Notify( 1099 content::NotificationService::current()->Notify(
1075 chrome::NOTIFICATION_PROFILE_CACHE_PICTURE_SAVED, 1100 chrome::NOTIFICATION_PROFILE_CACHE_PICTURE_SAVED,
1076 content::NotificationService::AllSources(), 1101 content::NotificationService::AllSources(),
1077 content::NotificationService::NoDetails()); 1102 content::NotificationService::NoDetails());
1078 1103
1079 FOR_EACH_OBSERVER(ProfileInfoCacheObserver, 1104 FOR_EACH_OBSERVER(ProfileInfoCacheObserver,
1080 observer_list_, 1105 observer_list_,
1081 OnProfileAvatarChanged(profile_path)); 1106 OnProfileHighResAvatarLoaded(profile_path));
1082
1083 // Remove the file from the list of downloads in progress. Note that this list
1084 // only contains the high resolution avatars, and not the Gaia profile images.
1085 if (!avatar_images_downloads_in_progress_[file_name])
1086 return;
1087
1088 delete avatar_images_downloads_in_progress_[file_name];
1089 avatar_images_downloads_in_progress_[file_name] = NULL;
1090 } 1107 }
1091 1108
1092 void ProfileInfoCache::MigrateLegacyProfileNamesAndDownloadAvatars() { 1109 void ProfileInfoCache::MigrateLegacyProfileNamesAndDownloadAvatars() {
1093 DCHECK(switches::IsNewAvatarMenu()); 1110 DCHECK(switches::IsNewAvatarMenu());
1094 1111
1095 // Only do this on desktop platforms. 1112 // Only do this on desktop platforms.
1096 #if !defined(OS_ANDROID) && !defined(OS_IOS) && !defined(OS_CHROMEOS) 1113 #if !defined(OS_ANDROID) && !defined(OS_IOS) && !defined(OS_CHROMEOS)
1097 // Migrate any legacy profile names ("First user", "Default Profile") to 1114 // Migrate any legacy profile names ("First user", "Default Profile") to
1098 // new style default names ("Person 1"). The problem here is that every 1115 // new style default names ("Person 1"). The problem here is that every
1099 // time you rename a profile, the ProfileInfoCache sorts itself, so 1116 // time you rename a profile, the ProfileInfoCache sorts itself, so
1100 // whatever you were iterating through is no longer valid. We need to 1117 // whatever you were iterating through is no longer valid. We need to
1101 // save a list of the profile paths (which thankfully do not change) that 1118 // save a list of the profile paths (which thankfully do not change) that
1102 // need to be renamed. We also can't pre-compute the new names, as they 1119 // need to be renamed. We also can't pre-compute the new names, as they
1103 // depend on the names of all the other profiles in the info cache, so they 1120 // depend on the names of all the other profiles in the info cache, so they
1104 // need to be re-computed after each rename. 1121 // need to be re-computed after each rename.
1105 std::vector<base::FilePath> profiles_to_rename; 1122 std::vector<base::FilePath> profiles_to_rename;
1106 1123
1107 const base::string16 default_profile_name = base::i18n::ToLower( 1124 const base::string16 default_profile_name = base::i18n::ToLower(
1108 l10n_util::GetStringUTF16(IDS_DEFAULT_PROFILE_NAME)); 1125 l10n_util::GetStringUTF16(IDS_DEFAULT_PROFILE_NAME));
1109 const base::string16 default_legacy_profile_name = base::i18n::ToLower( 1126 const base::string16 default_legacy_profile_name = base::i18n::ToLower(
1110 l10n_util::GetStringUTF16(IDS_LEGACY_DEFAULT_PROFILE_NAME)); 1127 l10n_util::GetStringUTF16(IDS_LEGACY_DEFAULT_PROFILE_NAME));
1111 1128
1112 for (size_t i = 0; i < GetNumberOfProfiles(); i++) { 1129 for (size_t i = 0; i < GetNumberOfProfiles(); i++) {
1113 // If needed, start downloading the high-res avatar for this profile. 1130 DownloadHighResAvatarIfNeeded(GetAvatarIconIndexOfProfileAtIndex(i),
1114 DownloadHighResAvatar(GetAvatarIconIndexOfProfileAtIndex(i), 1131 GetPathOfProfileAtIndex(i));
1115 GetPathOfProfileAtIndex(i));
1116 1132
1117 base::string16 name = base::i18n::ToLower(GetNameOfProfileAtIndex(i)); 1133 base::string16 name = base::i18n::ToLower(GetNameOfProfileAtIndex(i));
1118 if (name == default_profile_name || name == default_legacy_profile_name) 1134 if (name == default_profile_name || name == default_legacy_profile_name)
1119 profiles_to_rename.push_back(GetPathOfProfileAtIndex(i)); 1135 profiles_to_rename.push_back(GetPathOfProfileAtIndex(i));
1120 } 1136 }
1121 1137
1122 // Rename the necessary profiles. 1138 // Rename the necessary profiles.
1123 std::vector<base::FilePath>::const_iterator it; 1139 std::vector<base::FilePath>::const_iterator it;
1124 for (it = profiles_to_rename.begin(); it != profiles_to_rename.end(); ++it) { 1140 for (it = profiles_to_rename.begin(); it != profiles_to_rename.end(); ++it) {
1125 size_t profile_index = GetIndexOfProfileWithPath(*it); 1141 size_t profile_index = GetIndexOfProfileWithPath(*it);
1126 SetProfileIsUsingDefaultNameAtIndex(profile_index, true); 1142 SetProfileIsUsingDefaultNameAtIndex(profile_index, true);
1127 // This will assign a new "Person %d" type name and re-sort the cache. 1143 // This will assign a new "Person %d" type name and re-sort the cache.
1128 SetNameOfProfileAtIndex(profile_index, ChooseNameForNewProfile( 1144 SetNameOfProfileAtIndex(profile_index, ChooseNameForNewProfile(
1129 GetAvatarIconIndexOfProfileAtIndex(profile_index))); 1145 GetAvatarIconIndexOfProfileAtIndex(profile_index)));
1130 } 1146 }
1131 #endif 1147 #endif
1132 } 1148 }
OLDNEW
« no previous file with comments | « chrome/browser/profiles/profile_info_cache.h ('k') | chrome/browser/profiles/profile_info_cache_observer.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698