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

Unified Diff: chrome/browser/profiles/profile_shortcut_manager_win.cc

Issue 14137032: Create profile .ico file on profile creation (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rework Created 7 years, 7 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 side-by-side diff with in-line comments
Download patch
Index: chrome/browser/profiles/profile_shortcut_manager_win.cc
diff --git a/chrome/browser/profiles/profile_shortcut_manager_win.cc b/chrome/browser/profiles/profile_shortcut_manager_win.cc
index 92ac0ea7f0a856cdcc3e8a32d79f5415766cec2a..0cc4fa56774de5c5fadfdcc35a9fc1526781cf86 100644
--- a/chrome/browser/profiles/profile_shortcut_manager_win.cc
+++ b/chrome/browser/profiles/profile_shortcut_manager_win.cc
@@ -44,6 +44,9 @@ using content::BrowserThread;
namespace {
+// Name of the badged icon file generated for a given profile.
+const char kProfileIconFileName[] = "Google Profile.ico";
+
// Characters that are not allowed in Windows filenames. Taken from
// http://msdn.microsoft.com/en-us/library/aa365247.aspx
const char16 kReservedCharacters[] = L"<>:\"/\\|?*\x01\x02\x03\x04\x05\x06\x07"
@@ -139,32 +142,61 @@ SkBitmap BadgeIcon(const SkBitmap& app_icon_bitmap,
// Creates a desktop shortcut icon file (.ico) on the disk for a given profile,
// badging the browser distribution icon with the profile avatar.
// Returns a path to the shortcut icon file on disk, which is empty if this
-// fails. Use index 0 when assigning the resulting file as the icon.
-base::FilePath CreateChromeDesktopShortcutIconForProfile(
+// fails. Use index 0 when assigning the resulting file as the icon. If both
+// given bitmaps are empty, an unbadged icon is created.
+// |is_create| should be true if we are creating the icon at a time when it
+// is not possibly already in use. If it is false, we will refresh the Windows
+// icon cache.
+// TODO(calamity): Ideally we'd just copy the app icon verbatim from the exe's
+// resources in the case of an unbadged icon.
+base::FilePath CreateOrUpdateShortcutIconForProfile(
const base::FilePath& profile_path,
const SkBitmap& avatar_bitmap_1x,
- const SkBitmap& avatar_bitmap_2x) {
+ const SkBitmap& avatar_bitmap_2x,
+ bool is_icon_create) {
Alexei Svitkine (slow) 2013/05/24 14:43:51 Instead of passing this parameter, can this just c
calamity 2013/05/31 04:07:27 Done.
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
scoped_ptr<SkBitmap> app_icon_bitmap(GetAppIconForSize(kShortcutIconSize));
if (!app_icon_bitmap)
return base::FilePath();
gfx::ImageFamily badged_bitmaps;
- badged_bitmaps.Add(gfx::Image::CreateFrom1xBitmap(
- BadgeIcon(*app_icon_bitmap, avatar_bitmap_1x, 1)));
+ if (!avatar_bitmap_1x.empty()) {
+ badged_bitmaps.Add(gfx::Image::CreateFrom1xBitmap(
+ BadgeIcon(*app_icon_bitmap, avatar_bitmap_1x, 1)));
+ }
- app_icon_bitmap = GetAppIconForSize(IconUtil::kLargeIconSize);
- if (app_icon_bitmap) {
+ scoped_ptr<SkBitmap> large_app_icon_bitmap(
+ GetAppIconForSize(IconUtil::kLargeIconSize));
+ if (large_app_icon_bitmap && !avatar_bitmap_2x.empty()) {
badged_bitmaps.Add(gfx::Image::CreateFrom1xBitmap(
- BadgeIcon(*app_icon_bitmap, avatar_bitmap_2x, 2)));
+ BadgeIcon(*large_app_icon_bitmap, avatar_bitmap_2x, 2)));
}
+ // If we have no badged bitmaps, we should just use the default chrome icon.
+ if (badged_bitmaps.empty()) {
+ badged_bitmaps.Add(gfx::Image::CreateFrom1xBitmap(*app_icon_bitmap));
+ if (large_app_icon_bitmap) {
+ badged_bitmaps.Add(
+ gfx::Image::CreateFrom1xBitmap(*large_app_icon_bitmap));
+ }
+ }
// Finally, write the .ico file containing this new bitmap.
const base::FilePath icon_path =
- profile_path.AppendASCII(profiles::internal::kProfileIconFileName);
- if (!IconUtil::CreateIconFileFromImageFamily(badged_bitmaps, icon_path))
+ profiles::internal::GetProfileIconPath(profile_path);
+
+ if (!IconUtil::CreateIconFileFromImageFamily(badged_bitmaps, icon_path)) {
+ NOTREACHED();
return base::FilePath();
+ }
+ if (is_icon_create) {
+ SHChangeNotify(SHCNE_CREATE, SHCNF_PATH, icon_path.value().c_str(), NULL);
+ } else {
+ // This invalidates the Windows icon cache and causes the icon changes to
+ // register with the taskbar and desktop.
+ SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST | SHCNF_FLUSHNOWAIT,
+ NULL, NULL);
+ }
return icon_path;
}
@@ -299,7 +331,8 @@ void RenameChromeDesktopShortcutForProfile(
// It's also possible that a system-level shortcut exists instead - this
// should only be the case for the original Chrome shortcut from an
// installation. If that's the case, copy that one over - it will get its
- // properties updated by |CreateOrUpdateDesktopShortcutsForProfile()|.
+ // properties updated by
+ // |CreateOrUpdateDesktopShortcutsAndIconForProfile()|.
const base::FilePath possible_old_system_shortcut =
system_shortcuts_directory.Append(old_shortcut_filename);
if (file_util::PathExists(possible_old_system_shortcut))
@@ -307,20 +340,40 @@ void RenameChromeDesktopShortcutForProfile(
}
}
+struct CreateOrUpdateShortcutsParams {
+ CreateOrUpdateShortcutsParams() {}
+ ~CreateOrUpdateShortcutsParams() {}
+
+ base::FilePath profile_path;
+ string16 old_profile_name;
+ string16 profile_name;
+ SkBitmap avatar_image_1x;
+ SkBitmap avatar_image_2x;
+ ProfileShortcutManagerWin::CreateOrUpdateMode create_mode;
+ ProfileShortcutManagerWin::NonProfileShortcutAction action;
+ bool is_icon_create;
+};
+
// Updates all desktop shortcuts for the given profile to have the specified
// parameters. If |create_mode| is CREATE_WHEN_NONE_FOUND, a new shortcut is
// created if no existing ones were found. Whether non-profile shortcuts should
// be updated is specified by |action|. Must be called on the FILE thread.
-void CreateOrUpdateDesktopShortcutsForProfile(
- const base::FilePath& profile_path,
- const string16& old_profile_name,
- const string16& profile_name,
- const SkBitmap& avatar_image_1x,
- const SkBitmap& avatar_image_2x,
- ProfileShortcutManagerWin::CreateOrUpdateMode create_mode,
- ProfileShortcutManagerWin::NonProfileShortcutAction action) {
+void CreateOrUpdateDesktopShortcutsAndIconForProfile(
+ const CreateOrUpdateShortcutsParams& params) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+ base::FilePath shortcut_icon =
+ CreateOrUpdateShortcutIconForProfile(params.profile_path,
+ params.avatar_image_1x,
+ params.avatar_image_2x,
+ params.is_icon_create);
+ if (shortcut_icon.empty()) {
+ NOTREACHED();
+ return;
+ }
+ if (params.create_mode == ProfileShortcutManagerWin::CREATE_ICON_ONLY)
+ return;
+
base::FilePath chrome_exe;
if (!PathService::Get(base::FILE_EXE, &chrome_exe)) {
NOTREACHED();
@@ -332,12 +385,13 @@ void CreateOrUpdateDesktopShortcutsForProfile(
// the following code may result in NOTREACHED() being hit.
DCHECK(distribution->CanCreateDesktopShortcuts());
- if (old_profile_name != profile_name) {
+ if (params.old_profile_name != params.profile_name) {
const string16 old_shortcut_filename =
- profiles::internal::GetShortcutFilenameForProfile(old_profile_name,
- distribution);
+ profiles::internal::GetShortcutFilenameForProfile(
+ params.old_profile_name,
+ distribution);
const string16 new_shortcut_filename =
- profiles::internal::GetShortcutFilenameForProfile(profile_name,
+ profiles::internal::GetShortcutFilenameForProfile(params.profile_name,
distribution);
RenameChromeDesktopShortcutForProfile(old_shortcut_filename,
new_shortcut_filename);
@@ -348,16 +402,12 @@ void CreateOrUpdateDesktopShortcutsForProfile(
product.AddDefaultShortcutProperties(chrome_exe, &properties);
const string16 command_line =
- profiles::internal::CreateProfileShortcutFlags(profile_path);
+ profiles::internal::CreateProfileShortcutFlags(params.profile_path);
// Only set the profile-specific properties when |profile_name| is non empty.
// If it is empty, it means the shortcut being created should be a regular,
// non-profile Chrome shortcut.
- if (!profile_name.empty()) {
- const base::FilePath shortcut_icon =
- CreateChromeDesktopShortcutIconForProfile(profile_path,
- avatar_image_1x,
- avatar_image_2x);
+ if (!params.profile_name.empty()) {
if (!shortcut_icon.empty())
properties.set_icon(shortcut_icon, 0);
properties.set_arguments(command_line);
@@ -372,12 +422,12 @@ void CreateOrUpdateDesktopShortcutsForProfile(
std::vector<base::FilePath> shortcuts;
ListDesktopShortcutsWithCommandLine(chrome_exe, command_line,
- action == ProfileShortcutManagerWin::UPDATE_NON_PROFILE_SHORTCUTS,
+ params.action == ProfileShortcutManagerWin::UPDATE_NON_PROFILE_SHORTCUTS,
&shortcuts);
- if (create_mode == ProfileShortcutManagerWin::CREATE_WHEN_NONE_FOUND &&
+ if (params.create_mode == ProfileShortcutManagerWin::CREATE_WHEN_NONE_FOUND &&
shortcuts.empty()) {
const string16 shortcut_name =
- profiles::internal::GetShortcutFilenameForProfile(profile_name,
+ profiles::internal::GetShortcutFilenameForProfile(params.profile_name,
distribution);
shortcuts.push_back(base::FilePath(shortcut_name));
operation = ShellUtil::SHELL_SHORTCUT_CREATE_IF_NO_SYSTEM_LEVEL;
@@ -410,12 +460,12 @@ bool ChromeDesktopShortcutsExist(const base::FilePath& chrome_exe) {
return false;
}
-// Deletes all desktop shortcuts for the specified profile and also removes the
-// corresponding icon file. If |ensure_shortcuts_remain| is true, then a regular
-// non-profile shortcut will be created if this function would otherwise delete
-// the last Chrome desktop shortcut(s). Must be called on the FILE thread.
-void DeleteDesktopShortcutsAndIconFile(const base::FilePath& profile_path,
- bool ensure_shortcuts_remain) {
+// Deletes all desktop shortcuts for the specified profile. If
+// |ensure_shortcuts_remain| is true, then a regular non-profile shortcut will
+// be created if this function would otherwise delete the last Chrome desktop
+// shortcut(s). Must be called on the FILE thread.
+void DeleteDesktopShortcuts(const base::FilePath& profile_path,
+ bool ensure_shortcuts_remain) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
base::FilePath chrome_exe;
@@ -440,10 +490,6 @@ void DeleteDesktopShortcutsAndIconFile(const base::FilePath& profile_path,
NULL);
}
- const base::FilePath icon_path =
- profile_path.AppendASCII(profiles::internal::kProfileIconFileName);
- file_util::Delete(icon_path, false);
-
// If |ensure_shortcuts_remain| is true and deleting this profile caused the
// last shortcuts to be removed, re-create a regular non-profile shortcut.
const bool had_shortcuts = !shortcuts.empty();
@@ -525,7 +571,9 @@ SkBitmap GetImageResourceSkBitmapCopy(int resource_id) {
namespace profiles {
namespace internal {
-const char kProfileIconFileName[] = "Google Profile.ico";
+base::FilePath GetProfileIconPath(const base::FilePath& profile_path) {
+ return profile_path.AppendASCII(kProfileIconFileName);
+}
string16 GetShortcutFilenameForProfile(const string16& profile_name,
BrowserDistribution* distribution) {
@@ -552,8 +600,7 @@ string16 CreateProfileShortcutFlags(const base::FilePath& profile_path) {
// static
bool ProfileShortcutManager::IsFeatureEnabled() {
return BrowserDistribution::GetDistribution()->CanCreateDesktopShortcuts() &&
- !CommandLine::ForCurrentProcess()->HasSwitch(switches::kUserDataDir) &&
- !CommandLine::ForCurrentProcess()->HasSwitch(switches::kShowAppList);
+ !CommandLine::ForCurrentProcess()->HasSwitch(switches::kUserDataDir);
}
// static
@@ -575,17 +622,29 @@ ProfileShortcutManagerWin::~ProfileShortcutManagerWin() {
profile_manager_->GetProfileInfoCache().RemoveObserver(this);
}
+void ProfileShortcutManagerWin::CreateProfileIcon(
+ const base::FilePath& profile_path) {
+ CreateOrUpdateShortcutsForProfileAtPath(profile_path, CREATE_ICON_ONLY,
+ IGNORE_NON_PROFILE_SHORTCUTS, true);
+}
+
+void ProfileShortcutManagerWin::UpdateProfileIcon(
+ const base::FilePath& profile_path) {
+ CreateOrUpdateShortcutsForProfileAtPath(profile_path, CREATE_ICON_ONLY,
+ IGNORE_NON_PROFILE_SHORTCUTS, false);
+}
+
void ProfileShortcutManagerWin::CreateProfileShortcut(
const base::FilePath& profile_path) {
CreateOrUpdateShortcutsForProfileAtPath(profile_path, CREATE_WHEN_NONE_FOUND,
- IGNORE_NON_PROFILE_SHORTCUTS);
+ IGNORE_NON_PROFILE_SHORTCUTS, true);
}
void ProfileShortcutManagerWin::RemoveProfileShortcuts(
const base::FilePath& profile_path) {
BrowserThread::PostTask(
BrowserThread::FILE, FROM_HERE,
- base::Bind(&DeleteDesktopShortcutsAndIconFile, profile_path, false));
+ base::Bind(&DeleteDesktopShortcuts, profile_path, false));
}
void ProfileShortcutManagerWin::HasProfileShortcuts(
@@ -603,11 +662,16 @@ void ProfileShortcutManagerWin::OnProfileAdded(
if (profile_count == 1) {
CreateOrUpdateShortcutsForProfileAtPath(profile_path,
CREATE_WHEN_NONE_FOUND,
- UPDATE_NON_PROFILE_SHORTCUTS);
- } else if (profile_count == 2) {
- CreateOrUpdateShortcutsForProfileAtPath(GetOtherProfilePath(profile_path),
- UPDATE_EXISTING_ONLY,
- UPDATE_NON_PROFILE_SHORTCUTS);
+ UPDATE_NON_PROFILE_SHORTCUTS,
+ false);
+ } else {
+ CreateProfileIcon(profile_path);
+ if (profile_count == 2) {
+ CreateOrUpdateShortcutsForProfileAtPath(GetOtherProfilePath(profile_path),
+ UPDATE_EXISTING_ONLY,
+ UPDATE_NON_PROFILE_SHORTCUTS,
+ true);
+ }
}
}
@@ -623,13 +687,15 @@ void ProfileShortcutManagerWin::OnProfileWasRemoved(
// from an existing shortcut.
const bool deleting_down_to_last_profile = (cache.GetNumberOfProfiles() == 1);
if (deleting_down_to_last_profile) {
+ // This is needed to unbadge the icon.
CreateOrUpdateShortcutsForProfileAtPath(cache.GetPathOfProfileAtIndex(0),
UPDATE_EXISTING_ONLY,
- IGNORE_NON_PROFILE_SHORTCUTS);
+ IGNORE_NON_PROFILE_SHORTCUTS,
+ false);
}
BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
- base::Bind(&DeleteDesktopShortcutsAndIconFile,
+ base::Bind(&DeleteDesktopShortcuts,
profile_path,
deleting_down_to_last_profile));
}
@@ -638,13 +704,12 @@ void ProfileShortcutManagerWin::OnProfileNameChanged(
const base::FilePath& profile_path,
const string16& old_profile_name) {
CreateOrUpdateShortcutsForProfileAtPath(profile_path, UPDATE_EXISTING_ONLY,
- IGNORE_NON_PROFILE_SHORTCUTS);
+ IGNORE_NON_PROFILE_SHORTCUTS, false);
}
void ProfileShortcutManagerWin::OnProfileAvatarChanged(
const base::FilePath& profile_path) {
- CreateOrUpdateShortcutsForProfileAtPath(profile_path, UPDATE_EXISTING_ONLY,
- IGNORE_NON_PROFILE_SHORTCUTS);
+ UpdateProfileIcon(profile_path);
}
base::FilePath ProfileShortcutManagerWin::GetOtherProfilePath(
@@ -661,31 +726,35 @@ base::FilePath ProfileShortcutManagerWin::GetOtherProfilePath(
void ProfileShortcutManagerWin::CreateOrUpdateShortcutsForProfileAtPath(
const base::FilePath& profile_path,
CreateOrUpdateMode create_mode,
- NonProfileShortcutAction action) {
+ NonProfileShortcutAction action,
+ bool is_icon_create) {
+ CreateOrUpdateShortcutsParams params;
+ params.profile_path = profile_path;
+ params.create_mode = create_mode;
+ params.action = action;
+ params.is_icon_create = is_icon_create;
+
ProfileInfoCache* cache = &profile_manager_->GetProfileInfoCache();
size_t profile_index = cache->GetIndexOfProfileWithPath(profile_path);
if (profile_index == std::string::npos)
return;
bool remove_badging = cache->GetNumberOfProfiles() == 1;
- string16 old_shortcut_appended_name =
+ params.old_profile_name =
cache->GetShortcutNameOfProfileAtIndex(profile_index);
// Exit early if the mode is to update existing profile shortcuts only and
// none were ever created for this profile, per the shortcut name not being
// set in the profile info cache.
- if (old_shortcut_appended_name.empty() &&
+ if (params.old_profile_name.empty() &&
create_mode == UPDATE_EXISTING_ONLY &&
action == IGNORE_NON_PROFILE_SHORTCUTS) {
return;
}
- string16 new_shortcut_appended_name;
if (!remove_badging)
- new_shortcut_appended_name = cache->GetNameOfProfileAtIndex(profile_index);
+ params.profile_name = cache->GetNameOfProfileAtIndex(profile_index);
- SkBitmap avatar_bitmap_copy_1x;
- SkBitmap avatar_bitmap_copy_2x;
if (!remove_badging) {
const size_t icon_index =
cache->GetAvatarIconIndexOfProfileAtIndex(profile_index);
@@ -694,16 +763,13 @@ void ProfileShortcutManagerWin::CreateOrUpdateShortcutsForProfileAtPath(
const int resource_id_2x = kProfileAvatarIconResources2x[icon_index];
// Make a copy of the SkBitmaps to ensure that we can safely use the image
// data on the FILE thread.
- avatar_bitmap_copy_1x = GetImageResourceSkBitmapCopy(resource_id_1x);
- avatar_bitmap_copy_2x = GetImageResourceSkBitmapCopy(resource_id_2x);
+ params.avatar_image_1x = GetImageResourceSkBitmapCopy(resource_id_1x);
+ params.avatar_image_2x = GetImageResourceSkBitmapCopy(resource_id_2x);
}
BrowserThread::PostTask(
BrowserThread::FILE, FROM_HERE,
- base::Bind(&CreateOrUpdateDesktopShortcutsForProfile, profile_path,
- old_shortcut_appended_name, new_shortcut_appended_name,
- avatar_bitmap_copy_1x, avatar_bitmap_copy_2x, create_mode,
- action));
+ base::Bind(&CreateOrUpdateDesktopShortcutsAndIconForProfile, params));
cache->SetShortcutNameOfProfileAtIndex(profile_index,
- new_shortcut_appended_name);
+ params.profile_name);
}

Powered by Google App Engine
This is Rietveld 408576698