This source file includes following definitions.
- BadgeIcon
- OnProfileIconCreateSuccess
- CreateOrUpdateShortcutIconForProfile
- GetDesktopShortcutsDirectories
- ConvertToLongPath
- IsChromeShortcut
- ListDesktopShortcutsWithCommandLine
- RenameDesktopShortcut
- RenameChromeDesktopShortcutForProfile
- CreateOrUpdateDesktopShortcutsAndIconForProfile
- ChromeDesktopShortcutsExist
- DeleteDesktopShortcuts
- HasAnyProfileShortcuts
- SanitizeShortcutProfileNameString
- GetImageResourceSkBitmapCopy
- GetProfileIconPath
- GetShortcutFilenameForProfile
- CreateProfileShortcutFlags
- IsFeatureEnabled
- Create
- CreateOrUpdateProfileIcon
- CreateProfileShortcut
- RemoveProfileShortcuts
- HasProfileShortcuts
- GetShortcutProperties
- OnProfileAdded
- OnProfileWasRemoved
- OnProfileNameChanged
- OnProfileAvatarChanged
- GetOtherProfilePath
- CreateOrUpdateShortcutsForProfileAtPath
- Observe
#include "chrome/browser/profiles/profile_shortcut_manager_win.h"
#include <shlobj.h>
#include <string>
#include <vector>
#include "base/bind.h"
#include "base/command_line.h"
#include "base/file_util.h"
#include "base/files/file_enumerator.h"
#include "base/path_service.h"
#include "base/prefs/pref_service.h"
#include "base/strings/string16.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/win/shortcut.h"
#include "chrome/browser/app_icon_win.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_notification_types.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/browser/shell_integration.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
#include "chrome/installer/util/browser_distribution.h"
#include "chrome/installer/util/product.h"
#include "chrome/installer/util/shell_util.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/notification_service.h"
#include "grit/chrome_unscaled_resources.h"
#include "grit/chromium_strings.h"
#include "skia/ext/image_operations.h"
#include "skia/ext/platform_canvas.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/icon_util.h"
#include "ui/gfx/image/image.h"
#include "ui/gfx/image/image_family.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/skia_util.h"
using content::BrowserThread;
namespace {
const char kProfileIconFileName[] = "Google Profile.ico";
const base::char16 kReservedCharacters[] = L"<>:\"/\\|?*\x01\x02\x03\x04\x05"
L"\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17"
L"\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F";
const int kMaxProfileShortcutFileNameLength = 64;
const int kShortcutIconSize = 48;
const int kProfileAvatarBadgeSize = kShortcutIconSize / 2;
const int kCurrentProfileIconVersion = 2;
const int kProfileAvatarIconResources2x[] = {
IDR_PROFILE_AVATAR_2X_0,
IDR_PROFILE_AVATAR_2X_1,
IDR_PROFILE_AVATAR_2X_2,
IDR_PROFILE_AVATAR_2X_3,
IDR_PROFILE_AVATAR_2X_4,
IDR_PROFILE_AVATAR_2X_5,
IDR_PROFILE_AVATAR_2X_6,
IDR_PROFILE_AVATAR_2X_7,
IDR_PROFILE_AVATAR_2X_8,
IDR_PROFILE_AVATAR_2X_9,
IDR_PROFILE_AVATAR_2X_10,
IDR_PROFILE_AVATAR_2X_11,
IDR_PROFILE_AVATAR_2X_12,
IDR_PROFILE_AVATAR_2X_13,
IDR_PROFILE_AVATAR_2X_14,
IDR_PROFILE_AVATAR_2X_15,
IDR_PROFILE_AVATAR_2X_16,
IDR_PROFILE_AVATAR_2X_17,
IDR_PROFILE_AVATAR_2X_18,
IDR_PROFILE_AVATAR_2X_19,
IDR_PROFILE_AVATAR_2X_20,
IDR_PROFILE_AVATAR_2X_21,
IDR_PROFILE_AVATAR_2X_22,
IDR_PROFILE_AVATAR_2X_23,
IDR_PROFILE_AVATAR_2X_24,
IDR_PROFILE_AVATAR_2X_25,
};
SkBitmap BadgeIcon(const SkBitmap& app_icon_bitmap,
const SkBitmap& avatar_bitmap,
int scale_factor) {
SkBitmap source_bitmap = avatar_bitmap;
if ((avatar_bitmap.width() == scale_factor * profiles::kAvatarIconWidth) &&
(avatar_bitmap.height() == scale_factor * profiles::kAvatarIconHeight)) {
gfx::Rect frame(scale_factor * profiles::kAvatarIconWidth,
scale_factor * profiles::kAvatarIconHeight);
frame.Inset(scale_factor * 2, 0, scale_factor * 2, 0);
avatar_bitmap.extractSubset(&source_bitmap, gfx::RectToSkIRect(frame));
} else {
NOTREACHED();
}
int avatar_badge_size = kProfileAvatarBadgeSize;
if (app_icon_bitmap.width() != kShortcutIconSize) {
avatar_badge_size =
app_icon_bitmap.width() * kProfileAvatarBadgeSize / kShortcutIconSize;
}
SkBitmap sk_icon = skia::ImageOperations::Resize(
source_bitmap, skia::ImageOperations::RESIZE_LANCZOS3, avatar_badge_size,
source_bitmap.height() * avatar_badge_size / source_bitmap.width());
SkBitmap badged_bitmap;
badged_bitmap.allocN32Pixels(app_icon_bitmap.width(),
app_icon_bitmap.height());
SkCanvas offscreen_canvas(badged_bitmap);
offscreen_canvas.clear(SK_ColorTRANSPARENT);
offscreen_canvas.drawBitmap(app_icon_bitmap, 0, 0);
offscreen_canvas.drawBitmap(sk_icon,
app_icon_bitmap.width() - sk_icon.width(),
app_icon_bitmap.height() - sk_icon.height());
return badged_bitmap;
}
void OnProfileIconCreateSuccess(base::FilePath profile_path) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (!g_browser_process->profile_manager())
return;
Profile* profile =
g_browser_process->profile_manager()->GetProfileByPath(profile_path);
if (profile) {
profile->GetPrefs()->SetInteger(prefs::kProfileIconVersion,
kCurrentProfileIconVersion);
}
}
base::FilePath CreateOrUpdateShortcutIconForProfile(
const base::FilePath& profile_path,
const SkBitmap& avatar_bitmap_1x,
const SkBitmap& avatar_bitmap_2x) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
if (!base::PathExists(profile_path)) {
LOG(ERROR) << "Profile directory " << profile_path.value()
<< " did not exist when trying to create profile icon";
return base::FilePath();
}
scoped_ptr<SkBitmap> app_icon_bitmap(GetAppIconForSize(kShortcutIconSize));
if (!app_icon_bitmap)
return base::FilePath();
gfx::ImageFamily badged_bitmaps;
if (!avatar_bitmap_1x.empty()) {
badged_bitmaps.Add(gfx::Image::CreateFrom1xBitmap(
BadgeIcon(*app_icon_bitmap, avatar_bitmap_1x, 1)));
}
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(*large_app_icon_bitmap, avatar_bitmap_2x, 2)));
}
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));
}
}
const base::FilePath icon_path =
profiles::internal::GetProfileIconPath(profile_path);
const bool had_icon = base::PathExists(icon_path);
if (!IconUtil::CreateIconFileFromImageFamily(badged_bitmaps, icon_path)) {
NOTREACHED();
return base::FilePath();
}
if (had_icon) {
SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL);
} else {
SHChangeNotify(SHCNE_CREATE, SHCNF_PATH, icon_path.value().c_str(), NULL);
}
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::Bind(&OnProfileIconCreateSuccess, profile_path));
return icon_path;
}
bool GetDesktopShortcutsDirectories(
base::FilePath* user_shortcuts_directory,
base::FilePath* system_shortcuts_directory) {
BrowserDistribution* distribution = BrowserDistribution::GetDistribution();
if (user_shortcuts_directory &&
!ShellUtil::GetShortcutPath(ShellUtil::SHORTCUT_LOCATION_DESKTOP,
distribution, ShellUtil::CURRENT_USER,
user_shortcuts_directory)) {
NOTREACHED();
return false;
}
if (system_shortcuts_directory &&
!ShellUtil::GetShortcutPath(ShellUtil::SHORTCUT_LOCATION_DESKTOP,
distribution, ShellUtil::SYSTEM_LEVEL,
system_shortcuts_directory)) {
NOTREACHED();
return false;
}
return true;
}
base::FilePath ConvertToLongPath(const base::FilePath& path) {
const size_t length = GetLongPathName(path.value().c_str(), NULL, 0);
if (length != 0 && length != path.value().length()) {
std::vector<wchar_t> long_path(length);
if (GetLongPathName(path.value().c_str(), &long_path[0], length) != 0)
return base::FilePath(&long_path[0]);
}
return path;
}
bool IsChromeShortcut(const base::FilePath& path,
const base::FilePath& chrome_exe,
base::string16* command_line) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
if (path.Extension() != installer::kLnkExt)
return false;
base::FilePath target_path;
if (!base::win::ResolveShortcut(path, &target_path, command_line))
return false;
return ConvertToLongPath(target_path) == ConvertToLongPath(chrome_exe);
}
void ListDesktopShortcutsWithCommandLine(const base::FilePath& chrome_exe,
const base::string16& command_line,
bool include_empty_command_lines,
std::vector<base::FilePath>* paths) {
base::FilePath user_shortcuts_directory;
if (!GetDesktopShortcutsDirectories(&user_shortcuts_directory, NULL))
return;
base::FileEnumerator enumerator(user_shortcuts_directory, false,
base::FileEnumerator::FILES);
for (base::FilePath path = enumerator.Next(); !path.empty();
path = enumerator.Next()) {
base::string16 shortcut_command_line;
if (!IsChromeShortcut(path, chrome_exe, &shortcut_command_line))
continue;
if ((shortcut_command_line.empty() && include_empty_command_lines) ||
(shortcut_command_line.find(command_line) != base::string16::npos)) {
paths->push_back(path);
}
}
}
bool RenameDesktopShortcut(const base::FilePath& old_shortcut_path,
const base::FilePath& new_shortcut_path) {
if (!base::Move(old_shortcut_path, new_shortcut_path))
return false;
SHChangeNotify(SHCNE_RENAMEITEM, SHCNF_PATH | SHCNF_FLUSHNOWAIT,
old_shortcut_path.value().c_str(),
new_shortcut_path.value().c_str());
return true;
}
void RenameChromeDesktopShortcutForProfile(
const base::string16& old_shortcut_filename,
const base::string16& new_shortcut_filename) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
base::FilePath user_shortcuts_directory;
base::FilePath system_shortcuts_directory;
if (!GetDesktopShortcutsDirectories(&user_shortcuts_directory,
&system_shortcuts_directory)) {
return;
}
const base::FilePath old_shortcut_path =
user_shortcuts_directory.Append(old_shortcut_filename);
const base::FilePath new_shortcut_path =
user_shortcuts_directory.Append(new_shortcut_filename);
if (base::PathExists(old_shortcut_path)) {
const base::FilePath possible_new_system_shortcut =
system_shortcuts_directory.Append(new_shortcut_filename);
if (base::PathExists(possible_new_system_shortcut))
base::DeleteFile(old_shortcut_path, false);
else if (!RenameDesktopShortcut(old_shortcut_path, new_shortcut_path))
DLOG(ERROR) << "Could not rename Windows profile desktop shortcut.";
} else {
const base::FilePath possible_old_system_shortcut =
system_shortcuts_directory.Append(old_shortcut_filename);
if (base::PathExists(possible_old_system_shortcut))
base::CopyFile(possible_old_system_shortcut, new_shortcut_path);
}
}
struct CreateOrUpdateShortcutsParams {
CreateOrUpdateShortcutsParams(
base::FilePath profile_path,
ProfileShortcutManagerWin::CreateOrUpdateMode create_mode,
ProfileShortcutManagerWin::NonProfileShortcutAction action)
: profile_path(profile_path), create_mode(create_mode), action(action) {}
~CreateOrUpdateShortcutsParams() {}
ProfileShortcutManagerWin::CreateOrUpdateMode create_mode;
ProfileShortcutManagerWin::NonProfileShortcutAction action;
base::FilePath profile_path;
base::string16 old_profile_name;
base::string16 profile_name;
SkBitmap avatar_image_1x;
SkBitmap avatar_image_2x;
};
void CreateOrUpdateDesktopShortcutsAndIconForProfile(
const CreateOrUpdateShortcutsParams& params) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
const base::FilePath shortcut_icon =
CreateOrUpdateShortcutIconForProfile(params.profile_path,
params.avatar_image_1x,
params.avatar_image_2x);
if (shortcut_icon.empty() ||
params.create_mode ==
ProfileShortcutManagerWin::CREATE_OR_UPDATE_ICON_ONLY) {
return;
}
base::FilePath chrome_exe;
if (!PathService::Get(base::FILE_EXE, &chrome_exe)) {
NOTREACHED();
return;
}
BrowserDistribution* distribution = BrowserDistribution::GetDistribution();
DCHECK(distribution->CanCreateDesktopShortcuts());
if (params.old_profile_name != params.profile_name) {
const base::string16 old_shortcut_filename =
profiles::internal::GetShortcutFilenameForProfile(
params.old_profile_name,
distribution);
const base::string16 new_shortcut_filename =
profiles::internal::GetShortcutFilenameForProfile(params.profile_name,
distribution);
RenameChromeDesktopShortcutForProfile(old_shortcut_filename,
new_shortcut_filename);
}
ShellUtil::ShortcutProperties properties(ShellUtil::CURRENT_USER);
installer::Product product(distribution);
product.AddDefaultShortcutProperties(chrome_exe, &properties);
const base::string16 command_line =
profiles::internal::CreateProfileShortcutFlags(params.profile_path);
if (!params.profile_name.empty()) {
properties.set_arguments(command_line);
properties.set_icon(shortcut_icon, 0);
} else {
properties.set_arguments(base::string16());
}
properties.set_app_id(
ShellIntegration::GetChromiumModelIdForProfile(params.profile_path));
ShellUtil::ShortcutOperation operation =
ShellUtil::SHELL_SHORTCUT_REPLACE_EXISTING;
std::vector<base::FilePath> shortcuts;
ListDesktopShortcutsWithCommandLine(chrome_exe, command_line,
params.action == ProfileShortcutManagerWin::UPDATE_NON_PROFILE_SHORTCUTS,
&shortcuts);
if (params.create_mode == ProfileShortcutManagerWin::CREATE_WHEN_NONE_FOUND &&
shortcuts.empty()) {
const base::string16 shortcut_name =
profiles::internal::GetShortcutFilenameForProfile(params.profile_name,
distribution);
shortcuts.push_back(base::FilePath(shortcut_name));
operation = ShellUtil::SHELL_SHORTCUT_CREATE_IF_NO_SYSTEM_LEVEL;
}
for (size_t i = 0; i < shortcuts.size(); ++i) {
const base::FilePath shortcut_name =
shortcuts[i].BaseName().RemoveExtension();
properties.set_shortcut_name(shortcut_name.value());
ShellUtil::CreateOrUpdateShortcut(ShellUtil::SHORTCUT_LOCATION_DESKTOP,
distribution, properties, operation);
}
}
bool ChromeDesktopShortcutsExist(const base::FilePath& chrome_exe) {
base::FilePath user_shortcuts_directory;
if (!GetDesktopShortcutsDirectories(&user_shortcuts_directory, NULL))
return false;
base::FileEnumerator enumerator(user_shortcuts_directory, false,
base::FileEnumerator::FILES);
for (base::FilePath path = enumerator.Next(); !path.empty();
path = enumerator.Next()) {
if (IsChromeShortcut(path, chrome_exe, NULL))
return true;
}
return false;
}
void DeleteDesktopShortcuts(const base::FilePath& profile_path,
bool ensure_shortcuts_remain) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
base::FilePath chrome_exe;
if (!PathService::Get(base::FILE_EXE, &chrome_exe)) {
NOTREACHED();
return;
}
const base::string16 command_line =
profiles::internal::CreateProfileShortcutFlags(profile_path);
std::vector<base::FilePath> shortcuts;
ListDesktopShortcutsWithCommandLine(chrome_exe, command_line, false,
&shortcuts);
for (size_t i = 0; i < shortcuts.size(); ++i) {
base::win::TaskbarUnpinShortcutLink(shortcuts[i].value().c_str());
base::DeleteFile(shortcuts[i], false);
SHChangeNotify(SHCNE_DELETE, SHCNF_PATH, shortcuts[i].value().c_str(),
NULL);
}
const bool had_shortcuts = !shortcuts.empty();
if (ensure_shortcuts_remain && had_shortcuts &&
!ChromeDesktopShortcutsExist(chrome_exe)) {
BrowserDistribution* distribution = BrowserDistribution::GetDistribution();
DCHECK(distribution->CanCreateDesktopShortcuts());
installer::Product product(distribution);
ShellUtil::ShortcutProperties properties(ShellUtil::CURRENT_USER);
product.AddDefaultShortcutProperties(chrome_exe, &properties);
properties.set_shortcut_name(
profiles::internal::GetShortcutFilenameForProfile(base::string16(),
distribution));
ShellUtil::CreateOrUpdateShortcut(
ShellUtil::SHORTCUT_LOCATION_DESKTOP, distribution, properties,
ShellUtil::SHELL_SHORTCUT_CREATE_IF_NO_SYSTEM_LEVEL);
}
}
bool HasAnyProfileShortcuts(const base::FilePath& profile_path) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
base::FilePath chrome_exe;
if (!PathService::Get(base::FILE_EXE, &chrome_exe)) {
NOTREACHED();
return false;
}
const base::string16 command_line =
profiles::internal::CreateProfileShortcutFlags(profile_path);
std::vector<base::FilePath> shortcuts;
ListDesktopShortcutsWithCommandLine(chrome_exe, command_line, false,
&shortcuts);
return !shortcuts.empty();
}
base::string16 SanitizeShortcutProfileNameString(
const base::string16& profile_name) {
base::string16 sanitized = profile_name;
size_t pos = sanitized.find_first_of(kReservedCharacters);
while (pos != base::string16::npos) {
sanitized[pos] = L' ';
pos = sanitized.find_first_of(kReservedCharacters, pos + 1);
}
base::TrimWhitespace(sanitized, base::TRIM_LEADING, &sanitized);
if (sanitized.size() > kMaxProfileShortcutFileNameLength)
sanitized.erase(kMaxProfileShortcutFileNameLength);
base::TrimWhitespace(sanitized, base::TRIM_TRAILING, &sanitized);
return sanitized;
}
SkBitmap GetImageResourceSkBitmapCopy(int resource_id) {
const gfx::Image image =
ResourceBundle::GetSharedInstance().GetNativeImageNamed(resource_id);
DCHECK(!image.IsEmpty());
const SkBitmap* image_bitmap = image.ToSkBitmap();
SkBitmap bitmap_copy;
image_bitmap->deepCopyTo(&bitmap_copy);
return bitmap_copy;
}
}
namespace profiles {
namespace internal {
base::FilePath GetProfileIconPath(const base::FilePath& profile_path) {
return profile_path.AppendASCII(kProfileIconFileName);
}
base::string16 GetShortcutFilenameForProfile(
const base::string16& profile_name,
BrowserDistribution* distribution) {
base::string16 shortcut_name;
if (!profile_name.empty()) {
shortcut_name.append(SanitizeShortcutProfileNameString(profile_name));
shortcut_name.append(L" - ");
shortcut_name.append(l10n_util::GetStringUTF16(IDS_SHORT_PRODUCT_NAME));
} else {
shortcut_name.append(
distribution->GetShortcutName(BrowserDistribution::SHORTCUT_CHROME));
}
return shortcut_name + installer::kLnkExt;
}
base::string16 CreateProfileShortcutFlags(const base::FilePath& profile_path) {
return base::StringPrintf(L"--%ls=\"%ls\"",
base::ASCIIToUTF16(
switches::kProfileDirectory).c_str(),
profile_path.BaseName().value().c_str());
}
}
}
bool ProfileShortcutManager::IsFeatureEnabled() {
CommandLine* command_line = CommandLine::ForCurrentProcess();
return command_line->HasSwitch(switches::kEnableProfileShortcutManager) ||
(BrowserDistribution::GetDistribution()->CanCreateDesktopShortcuts() &&
!command_line->HasSwitch(switches::kUserDataDir));
}
ProfileShortcutManager* ProfileShortcutManager::Create(
ProfileManager* manager) {
return new ProfileShortcutManagerWin(manager);
}
ProfileShortcutManagerWin::ProfileShortcutManagerWin(ProfileManager* manager)
: profile_manager_(manager) {
DCHECK_EQ(
arraysize(kProfileAvatarIconResources2x),
profile_manager_->GetProfileInfoCache().GetDefaultAvatarIconCount());
registrar_.Add(this, chrome::NOTIFICATION_PROFILE_CREATED,
content::NotificationService::AllSources());
profile_manager_->GetProfileInfoCache().AddObserver(this);
}
ProfileShortcutManagerWin::~ProfileShortcutManagerWin() {
profile_manager_->GetProfileInfoCache().RemoveObserver(this);
}
void ProfileShortcutManagerWin::CreateOrUpdateProfileIcon(
const base::FilePath& profile_path) {
CreateOrUpdateShortcutsForProfileAtPath(profile_path,
CREATE_OR_UPDATE_ICON_ONLY,
IGNORE_NON_PROFILE_SHORTCUTS);
}
void ProfileShortcutManagerWin::CreateProfileShortcut(
const base::FilePath& profile_path) {
CreateOrUpdateShortcutsForProfileAtPath(profile_path, CREATE_WHEN_NONE_FOUND,
IGNORE_NON_PROFILE_SHORTCUTS);
}
void ProfileShortcutManagerWin::RemoveProfileShortcuts(
const base::FilePath& profile_path) {
BrowserThread::PostTask(
BrowserThread::FILE, FROM_HERE,
base::Bind(&DeleteDesktopShortcuts, profile_path, false));
}
void ProfileShortcutManagerWin::HasProfileShortcuts(
const base::FilePath& profile_path,
const base::Callback<void(bool)>& callback) {
BrowserThread::PostTaskAndReplyWithResult(
BrowserThread::FILE, FROM_HERE,
base::Bind(&HasAnyProfileShortcuts, profile_path), callback);
}
void ProfileShortcutManagerWin::GetShortcutProperties(
const base::FilePath& profile_path,
CommandLine* command_line,
base::string16* name,
base::FilePath* icon_path) {
base::FilePath chrome_exe;
if (!PathService::Get(base::FILE_EXE, &chrome_exe)) {
NOTREACHED();
return;
}
const ProfileInfoCache& cache = profile_manager_->GetProfileInfoCache();
size_t profile_index = cache.GetIndexOfProfileWithPath(profile_path);
DCHECK_LT(profile_index, cache.GetNumberOfProfiles());
base::string16 shortcut_profile_name;
if (cache.GetNumberOfProfiles() > 1)
shortcut_profile_name = cache.GetNameOfProfileAtIndex(profile_index);
*name = base::FilePath(profiles::internal::GetShortcutFilenameForProfile(
shortcut_profile_name,
BrowserDistribution::GetDistribution())).RemoveExtension().value();
command_line->ParseFromString(L"\"" + chrome_exe.value() + L"\" " +
profiles::internal::CreateProfileShortcutFlags(profile_path));
*icon_path = profiles::internal::GetProfileIconPath(profile_path);
}
void ProfileShortcutManagerWin::OnProfileAdded(
const base::FilePath& profile_path) {
CreateOrUpdateProfileIcon(profile_path);
if (profile_manager_->GetProfileInfoCache().GetNumberOfProfiles() == 2) {
CreateOrUpdateShortcutsForProfileAtPath(GetOtherProfilePath(profile_path),
UPDATE_EXISTING_ONLY,
UPDATE_NON_PROFILE_SHORTCUTS);
}
}
void ProfileShortcutManagerWin::OnProfileWasRemoved(
const base::FilePath& profile_path,
const base::string16& profile_name) {
const ProfileInfoCache& cache = profile_manager_->GetProfileInfoCache();
const bool deleting_down_to_last_profile = (cache.GetNumberOfProfiles() == 1);
if (deleting_down_to_last_profile) {
CreateOrUpdateShortcutsForProfileAtPath(cache.GetPathOfProfileAtIndex(0),
UPDATE_EXISTING_ONLY,
IGNORE_NON_PROFILE_SHORTCUTS);
}
BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
base::Bind(&DeleteDesktopShortcuts,
profile_path,
deleting_down_to_last_profile));
}
void ProfileShortcutManagerWin::OnProfileNameChanged(
const base::FilePath& profile_path,
const base::string16& old_profile_name) {
CreateOrUpdateShortcutsForProfileAtPath(profile_path, UPDATE_EXISTING_ONLY,
IGNORE_NON_PROFILE_SHORTCUTS);
}
void ProfileShortcutManagerWin::OnProfileAvatarChanged(
const base::FilePath& profile_path) {
CreateOrUpdateProfileIcon(profile_path);
}
base::FilePath ProfileShortcutManagerWin::GetOtherProfilePath(
const base::FilePath& profile_path) {
const ProfileInfoCache& cache = profile_manager_->GetProfileInfoCache();
DCHECK_EQ(2U, cache.GetNumberOfProfiles());
size_t current_profile_index = cache.GetIndexOfProfileWithPath(profile_path);
size_t other_profile_index = (current_profile_index == 0) ? 1 : 0;
return cache.GetPathOfProfileAtIndex(other_profile_index);
}
void ProfileShortcutManagerWin::CreateOrUpdateShortcutsForProfileAtPath(
const base::FilePath& profile_path,
CreateOrUpdateMode create_mode,
NonProfileShortcutAction action) {
DCHECK(!BrowserThread::IsThreadInitialized(BrowserThread::UI) ||
BrowserThread::CurrentlyOn(BrowserThread::UI));
CreateOrUpdateShortcutsParams params(profile_path, create_mode, action);
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;
params.old_profile_name =
cache->GetShortcutNameOfProfileAtIndex(profile_index);
if (params.old_profile_name.empty() &&
create_mode == UPDATE_EXISTING_ONLY &&
action == IGNORE_NON_PROFILE_SHORTCUTS) {
return;
}
if (!remove_badging) {
params.profile_name = cache->GetNameOfProfileAtIndex(profile_index);
const size_t icon_index =
cache->GetAvatarIconIndexOfProfileAtIndex(profile_index);
const int resource_id_1x =
cache->GetDefaultAvatarIconResourceIDAtIndex(icon_index);
const int resource_id_2x = kProfileAvatarIconResources2x[icon_index];
params.avatar_image_1x = GetImageResourceSkBitmapCopy(resource_id_1x);
params.avatar_image_2x = GetImageResourceSkBitmapCopy(resource_id_2x);
}
BrowserThread::PostTask(
BrowserThread::FILE, FROM_HERE,
base::Bind(&CreateOrUpdateDesktopShortcutsAndIconForProfile, params));
cache->SetShortcutNameOfProfileAtIndex(profile_index,
params.profile_name);
}
void ProfileShortcutManagerWin::Observe(
int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) {
switch (type) {
case chrome::NOTIFICATION_PROFILE_CREATED: {
Profile* profile =
content::Source<Profile>(source).ptr()->GetOriginalProfile();
if (profile->GetPrefs()->GetInteger(prefs::kProfileIconVersion) <
kCurrentProfileIconVersion) {
CreateOrUpdateProfileIcon(profile->GetPath());
}
break;
}
default:
NOTREACHED();
break;
}
}