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

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

Issue 8785006: Badge Windows profile shortcuts with multi-user avatar. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Applied some grt memory suggestions. Created 9 years 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
===================================================================
--- chrome/browser/profiles/profile_shortcut_manager_win.cc (revision 112717)
+++ chrome/browser/profiles/profile_shortcut_manager_win.cc (working copy)
@@ -10,9 +10,11 @@
#include "base/path_service.h"
#include "base/stringprintf.h"
#include "base/utf_string_conversions.h"
+#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_util.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_switches.h"
@@ -21,12 +23,21 @@
#include "chrome/installer/util/shell_util.h"
#include "content/public/browser/browser_thread.h"
#include "grit/generated_resources.h"
+#include "skia/ext/image_operations.h"
+#include "skia/ext/platform_canvas.h"
#include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/icon_util.h"
+#include "ui/gfx/image/image.h"
using content::BrowserThread;
namespace {
+const char kProfileIconFileName[] = "Google Profile.ico";
+const int kProfileAvatarShortcutBadgeWidth = 28;
+const int kProfileAvatarShortcutBadgeHeight = 28;
+const int kShortcutIconSize = 48;
+
// Creates the argument to pass to the Windows executable that launches Chrome
// with the profile in |profile_base_dir|.
// For example: --profile-directory="Profile 2"
@@ -44,6 +55,157 @@
bool_function.Run();
}
+// Creates a desktop shortcut icon file (.ico) on the disk for a given profile,
+// badging the browser distribution icon with the profile avatar.
+// |profile_base_dir| is the base directory (and key) of the profile. 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.
+FilePath CreateChromeDesktopShortcutIconForProfile(
+ const FilePath& profile_path,
+ const gfx::Image* avatar_image) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+ if (!avatar_image)
+ return FilePath();
+ const SkBitmap* avatar_bitmap = avatar_image->ToSkBitmap();
+ DCHECK(avatar_bitmap);
Robert Sesek 2011/12/05 18:03:28 This DCHECK is unnecessary.
SteveT 2011/12/05 20:33:17 Removed.
+ HICON app_icon_handle = GetAppIconForSize(kShortcutIconSize);
+ scoped_ptr<SkBitmap> app_icon_bitmap(
+ IconUtil::CreateSkBitmapFromHICON(app_icon_handle));
+ DestroyIcon(app_icon_handle);
+ if (!app_icon_bitmap.get())
+ return FilePath();
+
+ // TODO(stevet): Share this chunk of code with
+ // avatar_menu_button::DrawTaskBarDecoration.
+ const SkBitmap* source_bitmap = NULL;
+ SkBitmap squarer_bitmap;
+ 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,
+ profiles::kAvatarIconWidth - x * 2, profiles::kAvatarIconHeight));
+ source_bitmap = &squarer_bitmap;
+ } else {
+ source_bitmap = avatar_bitmap;
+ }
+ SkBitmap sk_icon = skia::ImageOperations::Resize(
+ *source_bitmap,
+ skia::ImageOperations::RESIZE_LANCZOS3,
+ kProfileAvatarShortcutBadgeWidth,
+ kProfileAvatarShortcutBadgeHeight);
+
+ // Overlay the avatar on the icon, anchoring it to the bottom-right of the
+ // icon.
+ scoped_ptr<SkCanvas> offscreen_canvas(
+ skia::CreateBitmapCanvas(app_icon_bitmap->width(),
+ app_icon_bitmap->height(),
+ false));
+ DCHECK(offscreen_canvas.get());
+ offscreen_canvas->drawBitmap(*app_icon_bitmap, 0, 0);
+ offscreen_canvas->drawBitmap(
+ sk_icon,
+ app_icon_bitmap->width() - kProfileAvatarShortcutBadgeWidth,
+ app_icon_bitmap->height() - kProfileAvatarShortcutBadgeHeight);
+ const SkBitmap& final_bitmap =
+ offscreen_canvas->getDevice()->accessBitmap(false);
+
+ // Finally, write the .ico file containing this new bitmap.
+ FilePath icon_path = profile_path.AppendASCII(kProfileIconFileName);
+ if (!IconUtil::CreateIconFileFromSkBitmap(final_bitmap, icon_path))
+ return FilePath();
+
+ return icon_path;
+}
+
+// Creates a desktop shortcut to open Chrome with the given profile name and
+// base directory. Iff |create|, create shortcut if it doesn't already exist.
+// Must be called on the FILE thread.
+void CreateChromeDesktopShortcutForProfile(
+ const string16& profile_name,
+ const string16& profile_base_dir,
+ const FilePath& profile_path,
+ const gfx::Image* avatar_image,
+ bool create) {
+ 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;
+ else
+ description = WideToUTF16(dist->GetAppDescription());
+ const string16& directory = CreateProfileShortcutSwitch(profile_base_dir);
+ FilePath icon_path =
+ CreateChromeDesktopShortcutIconForProfile(profile_path, avatar_image);
+
+ ShellUtil::CreateChromeDesktopShortcut(
+ dist,
+ chrome_exe.value(),
+ description,
+ profile_name,
+ directory,
+ icon_path.empty() ? chrome_exe.value() : icon_path.value(),
+ icon_path.empty() ? dist->GetIconIndex() : 0,
+ ShellUtil::CURRENT_USER,
+ false, // Use alternate text.
+ create); // Create if it doesn't already exist.
+}
+
+// Renames an existing Chrome desktop profile shortcut. Must be called on the
+// FILE thread.
+void RenameChromeDesktopShortcutForProfile(
+ const string16& old_shortcut,
+ const string16& new_shortcut) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+ FilePath shortcut_path;
+ if (ShellUtil::GetDesktopPath(false, // User's directory instead of system.
+ &shortcut_path)) {
+ FilePath old_profile = shortcut_path.Append(old_shortcut);
+ FilePath new_profile = shortcut_path.Append(new_shortcut);
+ file_util::Move(old_profile, new_profile);
+ }
+}
+
+// Updates the arguments to a Chrome desktop shortcut for a profile. Must be
+// called on the FILE thread.
+void UpdateChromeDesktopShortcutForProfile(
+ const string16& shortcut,
+ const string16& arguments,
+ const FilePath& profile_path,
+ const gfx::Image* avatar_image) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+ FilePath shortcut_path;
+ if (!ShellUtil::GetDesktopPath(false, &shortcut_path))
+ return;
+
+ shortcut_path = shortcut_path.Append(shortcut);
+ FilePath chrome_exe;
+ if (!PathService::Get(base::FILE_EXE, &chrome_exe))
+ return;
+ BrowserDistribution* dist = BrowserDistribution::GetDistribution();
+ string16 description;
+ if (!dist)
+ return;
+ else
+ description = WideToUTF16(dist->GetAppDescription());
+ FilePath icon_path =
+ CreateChromeDesktopShortcutIconForProfile(profile_path, avatar_image);
+
+ ShellUtil::UpdateChromeShortcut(
+ dist,
+ chrome_exe.value(),
+ shortcut_path.value(),
+ arguments,
+ description,
+ icon_path.empty() ? chrome_exe.value() : icon_path.value(),
+ icon_path.empty() ? dist->GetIconIndex() : 0,
+ false);
+}
+
} // namespace
ProfileShortcutManagerWin::ProfileShortcutManagerWin() {
@@ -54,17 +216,24 @@
void ProfileShortcutManagerWin::OnProfileAdded(
const string16& profile_name,
- const string16& profile_base_dir) {
+ const string16& profile_base_dir,
+ const FilePath& profile_path,
+ const gfx::Image* avatar_image) {
// Launch task to add shortcut to desktop on Windows. If this is the very
// first profile created, don't add the user name to the shortcut.
// TODO(mirandac): respect master_preferences choice to create no shortcuts
// (see http://crbug.com/104463)
if (g_browser_process->profile_manager()->GetNumberOfProfiles() > 1) {
- string16 profile_directory =
- CreateProfileShortcutSwitch(profile_base_dir);
- BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
- base::Bind(&CreateChromeDesktopShortcutForProfile,
- profile_name, profile_directory, true));
+ // There is no guarantee that avatar_image won't be deleted before it's
+ // used, so we'll make a deep copy of it and pass ownership to the user.
+ {
+ gfx::Image* avatar_copy = avatar_image ?
Robert Sesek 2011/12/05 18:03:28 You don't need to make a deep copy like this. gfx:
SteveT 2011/12/05 20:33:17 Cool. Thanks for the tip. Done.
+ new gfx::Image(avatar_image->CopySkBitmap()) : NULL;
+ BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
+ base::Bind(&CreateChromeDesktopShortcutForProfile,
+ profile_name, profile_base_dir, profile_path,
+ base::Owned(avatar_copy), true));
+ }
// If this is the very first multi-user account created, change the
// original shortcut to launch with the First User profile.
@@ -72,8 +241,6 @@
if (local_state->GetInteger(prefs::kProfilesNumCreated) == 2) {
string16 default_name = l10n_util::GetStringUTF16(
IDS_DEFAULT_PROFILE_NAME);
- string16 default_directory =
- CreateProfileShortcutSwitch(UTF8ToUTF16(chrome::kInitialProfile));
BrowserDistribution* dist = BrowserDistribution::GetDistribution();
string16 old_shortcut;
@@ -85,15 +252,18 @@
BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
base::Bind(&RenameChromeDesktopShortcutForProfile,
old_shortcut, new_shortcut));
+ // TODO(stevet): We actually need to retrieve the newly assigned avatar
+ // icon for the original profile here and update it with that.
BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
base::Bind(&UpdateChromeDesktopShortcutForProfile,
- new_shortcut, default_directory));
+ new_shortcut, UTF8ToUTF16(chrome::kInitialProfile),
+ profile_path, static_cast<gfx::Image*>(NULL)));
}
}
- } else { // Only one profile, so create original shortcut.
+ } else { // Only one profile, so create original shortcut, with no avatar.
BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
base::Bind(&CreateChromeDesktopShortcutForProfile,
- L"", L"", true));
+ L"", L"", FilePath(), static_cast<gfx::Image*>(NULL), true));
}
}
@@ -131,6 +301,29 @@
}
}
+void ProfileShortcutManagerWin::OnProfileAvatarChanged(
+ const string16& profile_name,
+ const string16& profile_base_dir,
+ const FilePath& profile_path,
+ const gfx::Image* avatar_image) {
+ // Launch task to change the icon of the desktop shortcut on windows.
+ string16 new_shortcut;
+ BrowserDistribution* dist = BrowserDistribution::GetDistribution();
+ if (ShellUtil::GetChromeShortcutName(dist, false, profile_name,
+ &new_shortcut)) {
+ // There is no guarantee that avatar_image won't be deleted before it's
+ // used, so we'll make a deep copy of it and pass ownership to the user.
+ gfx::Image* avatar_copy = avatar_image ?
Robert Sesek 2011/12/05 18:03:28 Here too.
SteveT 2011/12/05 20:33:17 Done.
+ new gfx::Image(avatar_image->CopySkBitmap()) : NULL;
+ BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
+ base::Bind(&UpdateChromeDesktopShortcutForProfile,
+ new_shortcut,
+ CreateProfileShortcutSwitch(profile_base_dir),
+ profile_path,
+ base::Owned(avatar_copy)));
+ }
+}
+
// static
std::vector<string16> ProfileShortcutManagerWin::GenerateShortcutsFromProfiles(
const std::vector<string16>& profile_names) {
@@ -146,71 +339,3 @@
}
return shortcuts;
}
-
-// static
-void ProfileShortcutManagerWin::CreateChromeDesktopShortcutForProfile(
- const string16& profile_name,
- const string16& directory,
- bool create) {
- 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;
- else
- description = WideToUTF16(dist->GetAppDescription());
- ShellUtil::CreateChromeDesktopShortcut(
- dist,
- chrome_exe.value(),
- description,
- profile_name,
- directory,
- ShellUtil::CURRENT_USER,
- false, // Use alternate text.
- create); // Create if it doesn't already exist.
-}
-
-// static
-void ProfileShortcutManagerWin::RenameChromeDesktopShortcutForProfile(
- const string16& old_shortcut,
- const string16& new_shortcut) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
- FilePath shortcut_path;
- if (ShellUtil::GetDesktopPath(false, // User's directory instead of system.
- &shortcut_path)) {
- FilePath old_profile = shortcut_path.Append(old_shortcut);
- FilePath new_profile = shortcut_path.Append(new_shortcut);
- file_util::Move(old_profile, new_profile);
- }
-}
-
-// static
-void ProfileShortcutManagerWin::UpdateChromeDesktopShortcutForProfile(
- const string16& shortcut,
- const string16& arguments) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
- FilePath shortcut_path;
- if (!ShellUtil::GetDesktopPath(false, &shortcut_path))
- return;
-
- shortcut_path = shortcut_path.Append(shortcut);
- FilePath chrome_exe;
- if (!PathService::Get(base::FILE_EXE, &chrome_exe))
- return;
- BrowserDistribution* dist = BrowserDistribution::GetDistribution();
- string16 description;
- if (!dist)
- return;
- else
- description = WideToUTF16(dist->GetAppDescription());
- ShellUtil::UpdateChromeShortcut(
- dist,
- chrome_exe.value(),
- shortcut_path.value(),
- arguments,
- description,
- false);
-}

Powered by Google App Engine
This is Rietveld 408576698