Chromium Code Reviews| Index: chrome/browser/profiles/profile_shortcut_manager_win.cc |
| =================================================================== |
| --- chrome/browser/profiles/profile_shortcut_manager_win.cc (revision 152316) |
| +++ chrome/browser/profiles/profile_shortcut_manager_win.cc (working copy) |
| @@ -15,7 +15,7 @@ |
| #include "chrome/browser/app_icon_win.h" |
| #include "chrome/browser/browser_process.h" |
| #include "chrome/browser/prefs/pref_service.h" |
| -#include "chrome/browser/profiles/profile_info_cache.h" |
| +#include "chrome/browser/profiles/profile_info_cache_observer.h" |
| #include "chrome/browser/profiles/profile_info_util.h" |
| #include "chrome/browser/profiles/profile_manager.h" |
| #include "chrome/common/chrome_constants.h" |
| @@ -48,9 +48,8 @@ |
| // Use index 0 when assigning the resulting file as the icon. |
| FilePath CreateChromeDesktopShortcutIconForProfile( |
| const FilePath& profile_path, |
| - const gfx::Image& avatar_image) { |
| + const SkBitmap& avatar_bitmap) { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| - const SkBitmap* avatar_bitmap = avatar_image.ToSkBitmap(); |
| HICON app_icon_handle = GetAppIconForSize(kShortcutIconSize); |
| scoped_ptr<SkBitmap> app_icon_bitmap( |
| IconUtil::CreateSkBitmapFromHICON(app_icon_handle)); |
| @@ -62,16 +61,16 @@ |
| // avatar_menu_button::DrawTaskBarDecoration. |
| const SkBitmap* source_bitmap = NULL; |
| SkBitmap squarer_bitmap; |
| - if ((avatar_bitmap->width() == profiles::kAvatarIconWidth) && |
| - (avatar_bitmap->height() == profiles::kAvatarIconHeight)) { |
| + if ((avatar_bitmap.width() == profiles::kAvatarIconWidth) && |
| + (avatar_bitmap.height() == profiles::kAvatarIconHeight)) { |
| // Shave a couple of columns so the bitmap is more square. So when |
| // resized to a square aspect ratio it looks pretty. |
| int x = 2; |
| - avatar_bitmap->extractSubset(&squarer_bitmap, SkIRect::MakeXYWH(x, 0, |
| + avatar_bitmap.extractSubset(&squarer_bitmap, SkIRect::MakeXYWH(x, 0, |
| profiles::kAvatarIconWidth - x * 2, profiles::kAvatarIconHeight)); |
| source_bitmap = &squarer_bitmap; |
| } else { |
| - source_bitmap = avatar_bitmap; |
| + source_bitmap = &avatar_bitmap; |
| } |
| SkBitmap sk_icon = skia::ImageOperations::Resize( |
| *source_bitmap, |
| @@ -108,51 +107,86 @@ |
| profile_path.BaseName().value().c_str()); |
| } |
| -// Wrap a ShellUtil function that returns a bool so it can be posted in a |
| -// task to the FILE thread. |
| -void CallShellUtilBoolFunction( |
| +// Wrap a ShellUtil/FileUtil function that returns a bool so it can be posted |
| +// in a task to the FILE thread. |
| +void CallBoolFunction( |
| const base::Callback<bool(void)>& bool_function) { |
| bool_function.Run(); |
| } |
| +// Renames an existing Chrome desktop profile shortcut. Must be called on the |
| +// FILE thread. |
| +void RenameChromeDesktopShortcutForProfile( |
| + const string16& old_shortcut_file, |
| + const string16& new_shortcut_file) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| + FilePath shortcut_path; |
| + if (ShellUtil::GetDesktopPath(false, // User's directory instead of system. |
| + &shortcut_path)) { |
| + FilePath old_shortcut_path = shortcut_path.Append(old_shortcut_file); |
| + FilePath new_shortcut_path = shortcut_path.Append(new_shortcut_file); |
| + if (!file_util::Move(old_shortcut_path, new_shortcut_path)) |
| + LOG(ERROR) << "Could not rename Windows profile desktop shortcut."; |
| + } |
| +} |
| + |
| +// Create or update a profile desktop shortcut. Must be called on the FILE |
| +// thread. |
| +void CreateOrUpdateProfileDesktopShortcut( |
| + const FilePath& profile_path, |
| + const string16& profile_name, |
| + const SkBitmap& avatar_image, |
| + bool create) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| + FilePath shortcut_icon = CreateChromeDesktopShortcutIconForProfile( |
| + profile_path, avatar_image); |
| + |
| + FilePath chrome_exe; |
| + if (!PathService::Get(base::FILE_EXE, &chrome_exe)) |
| + return; |
| + BrowserDistribution* dist = BrowserDistribution::GetDistribution(); |
| + if (!dist) |
| + return; |
| + string16 description(WideToUTF16(dist->GetAppDescription())); |
|
gab
2012/08/24 19:28:16
dist->GetAppDescription() does return a string16,
Halli
2012/08/24 19:54:24
Done.
|
| + |
| + uint32 options = create ? ShellUtil::SHORTCUT_CREATE_ALWAYS : |
| + ShellUtil::SHORTCUT_NO_OPTIONS; |
|
gab
2012/08/24 19:28:16
optional nit: Align with ShellUtil::SHORTCUT_CREAT
Halli
2012/08/24 19:54:24
Done.
|
| + ShellUtil::CreateChromeDesktopShortcut( |
| + dist, |
| + chrome_exe.value(), |
| + description, |
| + profile_name, |
| + CreateProfileShortcutFlags(profile_path), |
| + shortcut_icon.empty() ? chrome_exe.value() : shortcut_icon.value(), |
| + shortcut_icon.empty() ? dist->GetIconIndex() : 0, |
| + ShellUtil::CURRENT_USER, |
| + options); |
| +} |
| + |
| } // namespace |
| -class ProfileShortcutManagerWin : public ProfileShortcutManager { |
| +class ProfileShortcutManagerWin : public ProfileShortcutManager, |
| + public ProfileInfoCacheObserver { |
| public: |
| - ProfileShortcutManagerWin(); |
| + explicit ProfileShortcutManagerWin(ProfileInfoCache& cache); |
| virtual ~ProfileShortcutManagerWin(); |
| - virtual void CreateChromeDesktopShortcut( |
| + virtual void StartProfileDesktopShortcutCreation( |
| const FilePath& profile_path, const string16& profile_name, |
| const gfx::Image& avatar_image) OVERRIDE; |
| - virtual void DeleteChromeDesktopShortcut(const FilePath& profile_path) |
| - OVERRIDE; |
| + virtual void DeleteProfileDesktopShortcut(const FilePath& profile_path, |
| + const string16& profile_name) OVERRIDE; |
| + virtual void OnProfileAdded(const FilePath& profile_path) OVERRIDE; |
| + virtual void OnProfileWillBeRemoved(const FilePath& profile_path) OVERRIDE; |
| + virtual void OnProfileWasRemoved(const FilePath& profile_path, |
| + const string16& profile_name) OVERRIDE; |
| + virtual void OnProfileNameChanged(const FilePath& profile_path, |
| + const string16& old_profile_name) OVERRIDE; |
| + virtual void OnProfileAvatarChanged(const FilePath& profile_path) OVERRIDE; |
| + |
| private: |
| - struct ProfileShortcutInfo { |
| - string16 flags; |
| - string16 profile_name; |
| - gfx::Image avatar_image; |
| - |
| - ProfileShortcutInfo() |
| - : flags(string16()), |
| - profile_name(string16()), |
| - avatar_image(gfx::Image()) { |
| - } |
| - |
| - ProfileShortcutInfo( |
| - string16 p_flags, |
| - string16 p_profile_name, |
| - gfx::Image p_avatar_image) |
| - : flags(p_flags), |
| - profile_name(p_profile_name), |
| - avatar_image(p_avatar_image) { |
| - } |
| - }; |
| - |
| - // TODO(hallielaine): Repopulate this map on chrome session startup |
| - typedef std::map<FilePath, ProfileShortcutInfo> ProfileShortcutsMap; |
| - ProfileShortcutsMap profile_shortcuts_; |
| + ProfileInfoCache& profile_info_cache_; |
| }; |
| // static |
| @@ -165,65 +199,129 @@ |
| } |
| // static |
| -ProfileShortcutManager* ProfileShortcutManager::Create() { |
| - return new ProfileShortcutManagerWin(); |
| +ProfileShortcutManager* ProfileShortcutManager::Create( |
| + ProfileInfoCache& cache) { |
| + return new ProfileShortcutManagerWin(cache); |
| } |
| -ProfileShortcutManagerWin::ProfileShortcutManagerWin() { |
| +ProfileShortcutManagerWin::ProfileShortcutManagerWin(ProfileInfoCache& cache) |
| + : profile_info_cache_(cache) { |
| + cache.AddObserver(this); |
| } |
| ProfileShortcutManagerWin::~ProfileShortcutManagerWin() { |
| + profile_info_cache_.RemoveObserver(this); |
| } |
| -void ProfileShortcutManagerWin::CreateChromeDesktopShortcut( |
| +void ProfileShortcutManagerWin::StartProfileDesktopShortcutCreation( |
| const FilePath& profile_path, const string16& profile_name, |
| const gfx::Image& avatar_image) { |
| - FilePath shortcut_icon = CreateChromeDesktopShortcutIconForProfile( |
| - profile_path, avatar_image); |
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| - FilePath chrome_exe; |
| - if (!PathService::Get(base::FILE_EXE, &chrome_exe)) |
| - return; |
| - BrowserDistribution* dist = BrowserDistribution::GetDistribution(); |
| - string16 description; |
| - if (!dist) |
| - return; |
| - description = WideToUTF16(dist->GetAppDescription()); |
| + DCHECK(!avatar_image.IsEmpty()); |
| + const SkBitmap* avatar_bitmap = avatar_image.ToSkBitmap(); |
| - // Add the profile to the map if it doesn't exist already |
| - if (!profile_shortcuts_.count(profile_path)) { |
| - string16 flags = CreateProfileShortcutFlags(profile_path); |
| - profile_shortcuts_.insert(std::make_pair(profile_path, |
| - ProfileShortcutInfo(flags, profile_name, |
| - avatar_image))); |
| - } |
| - |
| - ShellUtil::CreateChromeDesktopShortcut( |
| - dist, |
| - chrome_exe.value(), |
| - description, |
| - profile_shortcuts_[profile_path].profile_name, |
| - profile_shortcuts_[profile_path].flags, |
| - shortcut_icon.empty() ? chrome_exe.value() : shortcut_icon.value(), |
| - shortcut_icon.empty() ? dist->GetIconIndex() : 0, |
| - ShellUtil::CURRENT_USER, |
| - ShellUtil::SHORTCUT_CREATE_ALWAYS); |
| + // Make a copy of the SkBitmap to ensure that we can safely use the image |
| + // data on the FILE thread. |
| + SkBitmap avatar_bitmap_copy; |
| + DCHECK(avatar_bitmap->deepCopyTo(&avatar_bitmap_copy, |
| + avatar_bitmap->getConfig())); |
| + BrowserThread::PostTask( |
| + BrowserThread::FILE, FROM_HERE, |
| + base::Bind(&CreateOrUpdateProfileDesktopShortcut, |
| + profile_path, profile_name, avatar_bitmap_copy, true)); |
| } |
| -void ProfileShortcutManagerWin::DeleteChromeDesktopShortcut( |
| - const FilePath& profile_path) { |
| +void ProfileShortcutManagerWin::DeleteProfileDesktopShortcut( |
| + const FilePath& profile_path, const string16& profile_name) { |
| BrowserDistribution* dist = BrowserDistribution::GetDistribution(); |
| string16 shortcut; |
| // If we can find the shortcut, delete it |
| if (ShellUtil::GetChromeShortcutName(dist, false, |
| - profile_shortcuts_[profile_path].profile_name, &shortcut)) { |
| + profile_name, &shortcut)) { |
| std::vector<string16> appended_names(1, shortcut); |
| BrowserThread::PostTask( |
| BrowserThread::FILE, FROM_HERE, |
| - base::Bind(&CallShellUtilBoolFunction, base::Bind( |
| + base::Bind(&CallBoolFunction, base::Bind( |
| &ShellUtil::RemoveChromeDesktopShortcutsWithAppendedNames, |
|
gab
2012/08/24 19:17:33
Is RemoveChromeDesktopShortcutsWithAppendedNames()
Halli
2012/08/24 19:54:24
This will be used soon to remove all Profile short
|
| appended_names))); |
| - profile_shortcuts_.erase(profile_path); |
| } |
| + FilePath icon_path = profile_path.AppendASCII(kProfileIconFileName); |
| + BrowserThread::PostTask( |
| + BrowserThread::FILE, FROM_HERE, |
| + base::Bind(&CallBoolFunction, base::Bind( |
| + &file_util::Delete, icon_path, false))); |
| } |
| +void ProfileShortcutManagerWin::OnProfileAdded(const FilePath& profile_path) { |
| +} |
| + |
| +void ProfileShortcutManagerWin::OnProfileWillBeRemoved( |
| + const FilePath& profile_path) { |
| +} |
| + |
| +void ProfileShortcutManagerWin::OnProfileWasRemoved( |
| + const FilePath& profile_path, |
| + const string16& profile_name) { |
| +} |
| + |
| +void ProfileShortcutManagerWin::OnProfileNameChanged( |
| + const FilePath& profile_path, |
| + const string16& old_profile_name) { |
| + size_t profile_index = profile_info_cache_.GetIndexOfProfileWithPath( |
| + profile_path); |
| + if (profile_index == std::string::npos) |
| + return; |
| + |
| + string16 new_profile_name = |
| + profile_info_cache_.GetNameOfProfileAtIndex(profile_index); |
| + |
| + string16 old_shortcut_file; |
| + string16 new_shortcut_file; |
| + BrowserDistribution* dist = BrowserDistribution::GetDistribution(); |
| + if (ShellUtil::GetChromeShortcutName( |
| + dist, false, old_profile_name, &old_shortcut_file) && |
| + ShellUtil::GetChromeShortcutName( |
| + dist, false, new_profile_name, &new_shortcut_file)) { |
| + BrowserThread::PostTask( |
| + BrowserThread::FILE, FROM_HERE, |
| + base::Bind(&RenameChromeDesktopShortcutForProfile, |
| + old_shortcut_file, |
| + new_shortcut_file)); |
| + } |
| +} |
| + |
| +void ProfileShortcutManagerWin::OnProfileAvatarChanged( |
| + const FilePath& profile_path) { |
| + size_t profile_index = profile_info_cache_.GetIndexOfProfileWithPath( |
| + profile_path); |
| + if (profile_index == std::string::npos) |
| + return; |
| + |
| + string16 profile_name = |
| + profile_info_cache_.GetNameOfProfileAtIndex(profile_index); |
| + string16 shortcut; |
| + |
| + BrowserDistribution* dist = BrowserDistribution::GetDistribution(); |
| + if (ShellUtil::GetChromeShortcutName( |
| + dist, false, profile_name, &shortcut)) { |
| + size_t new_icon_index = profile_info_cache_. |
| + GetAvatarIconIndexOfProfileAtIndex(profile_index); |
| + gfx::Image avatar_image = |
| + ResourceBundle::GetSharedInstance().GetNativeImageNamed( |
| + profile_info_cache_.GetDefaultAvatarIconResourceIDAtIndex( |
| + new_icon_index)); |
| + |
| + DCHECK(!avatar_image.IsEmpty()); |
| + const SkBitmap* avatar_bitmap = avatar_image.ToSkBitmap(); |
| + |
| + // Make a copy of the SkBitmap to ensure that we can safely use the image |
| + // data on the FILE thread. |
| + SkBitmap avatar_bitmap_copy; |
| + DCHECK(avatar_bitmap->deepCopyTo(&avatar_bitmap_copy, |
| + avatar_bitmap->getConfig())); |
| + BrowserThread::PostTask( |
| + BrowserThread::FILE, FROM_HERE, |
| + base::Bind(&CreateOrUpdateProfileDesktopShortcut, |
| + profile_path, profile_name, avatar_bitmap_copy, false)); |
| + } |
| +} |
| + |