Index: chrome/browser/profiles/profile_shortcut_manager_win.cc |
=================================================================== |
--- chrome/browser/profiles/profile_shortcut_manager_win.cc (revision 150342) |
+++ chrome/browser/profiles/profile_shortcut_manager_win.cc (working copy) |
@@ -2,10 +2,12 @@ |
// Use of this source code is governed by a BSD-style license that can be |
// found in the LICENSE file. |
-#include "chrome/browser/profiles/profile_shortcut_manager_win.h" |
+#include "chrome/browser/profiles/profile_shortcut_manager.h" |
+#include <map> |
+ |
#include "base/bind.h" |
-#include "base/file_path.h" |
+#include "base/command_line.h" |
#include "base/file_util.h" |
#include "base/path_service.h" |
#include "base/stringprintf.h" |
@@ -29,7 +31,6 @@ |
#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" |
using content::BrowserThread; |
@@ -40,22 +41,24 @@ |
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" |
-string16 CreateProfileShortcutSwitch(const string16& profile_base_dir) { |
- return base::StringPrintf(L"--%ls=\"%ls\"", |
- ASCIIToUTF16(switches::kProfileDirectory).c_str(), |
- profile_base_dir.c_str()); |
-} |
+struct ProfileShortcutInfo { |
+ string16 flags; |
+ string16 profile_name; |
+ gfx::Image avatar_image; |
-// Wrap a ShellUtil function that returns a bool so it can be posted in a |
-// task to the FILE thread. |
-void CallShellUtilBoolFunction( |
- const base::Callback<bool(void)>& bool_function) { |
- bool_function.Run(); |
-} |
+ 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) { |
+ } |
+}; |
+ |
+typedef std::map<FilePath, ProfileShortcutInfo> ProfileShortcutsMap; |
+ProfileShortcutsMap profile_shortcuts_; |
+ |
// 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 |
@@ -73,7 +76,7 @@ |
if (!app_icon_bitmap.get()) |
return FilePath(); |
- // TODO(stevet): Share this chunk of code with |
+ // TODO(hallielaine): Share this chunk of code with |
// avatar_menu_button::DrawTaskBarDecoration. |
const SkBitmap* source_bitmap = NULL; |
SkBitmap squarer_bitmap; |
@@ -117,315 +120,104 @@ |
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 = avatar_image ? |
- CreateChromeDesktopShortcutIconForProfile(profile_path, *avatar_image) : |
- FilePath(); |
- |
- 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, |
- create ? ShellUtil::SHORTCUT_CREATE_ALWAYS : |
- ShellUtil::SHORTCUT_NO_OPTIONS); |
+string16 CreateProfileShortcutFlags(const FilePath& profile_path) { |
+ return base::StringPrintf(L"--%ls=\"%ls\"", |
+ ASCIIToUTF16(switches::kProfileDirectory).c_str(), |
+ profile_path.BaseName().value().c_str()); |
} |
-// 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); |
- } |
+// Wrap a ShellUtil function that returns a bool so it can be posted in a |
+// task to the FILE thread. |
+void CallShellUtilBoolFunction( |
+ const base::Callback<bool(void)>& bool_function) { |
+ bool_function.Run(); |
} |
-// 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 = avatar_image ? |
- CreateChromeDesktopShortcutIconForProfile(profile_path, *avatar_image) : |
- FilePath(); |
- |
- 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, |
- ShellUtil::SHORTCUT_NO_OPTIONS); |
-} |
- |
-void DeleteAutoLaunchValueForProfile( |
- const FilePath& profile_path) { |
- if (auto_launch_util::AutoStartRequested(profile_path.BaseName().value(), |
- true, // Window requested. |
- FilePath())) { |
- auto_launch_util::DisableForegroundStartAtLogin( |
- profile_path.BaseName().value()); |
- } |
-} |
- |
} // namespace |
+class ProfileShortcutManagerWin : public ProfileShortcutManager { |
+ public: |
+ ProfileShortcutManagerWin(); |
+ virtual void CreateChromeDesktopShortcut( |
+ const FilePath& profile_path, const string16& profile_name, |
+ const gfx::Image& avatar_image); |
+ virtual void DeleteChromeDesktopShortcut(const FilePath& profile_path); |
+ ~ProfileShortcutManagerWin(); |
+}; |
+ |
ProfileShortcutManagerWin::ProfileShortcutManagerWin() { |
} |
ProfileShortcutManagerWin::~ProfileShortcutManagerWin() { |
} |
-void ProfileShortcutManagerWin::AddProfileShortcut( |
- const FilePath& profile_path) { |
- ProfileInfoCache& cache = |
- g_browser_process->profile_manager()->GetProfileInfoCache(); |
- size_t index = cache.GetIndexOfProfileWithPath(profile_path); |
- if (index == std::string::npos) |
- return; |
- |
- // 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) { |
- { |
- // We make a copy of the Image to ensure that the underlying image data is |
- // AddRef'd, in case the original copy gets deleted. |
- gfx::Image* avatar_copy = |
- new gfx::Image(cache.GetAvatarIconOfProfileAtIndex(index)); |
- string16 profile_name = cache.GetNameOfProfileAtIndex(index); |
- string16 profile_base_dir = profile_path.BaseName().value(); |
- 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 second existing multi-user account created, change the |
- // original shortcut use the first profile's details (name, badge, |
- // argument). |
- if (cache.GetNumberOfProfiles() == 2) { |
- // Get the index of the first profile, based on the index of the second |
- // profile. It's either 0 or 1, whichever the second profile isn't. |
- size_t first_index = 0; |
- if (cache.GetIndexOfProfileWithPath(profile_path) == 0) |
- first_index = 1; |
- string16 first_name = cache.GetNameOfProfileAtIndex(first_index); |
- BrowserDistribution* dist = BrowserDistribution::GetDistribution(); |
- |
- string16 old_shortcut; |
- string16 new_shortcut; |
- if (ShellUtil::GetChromeShortcutName(dist, false, L"", &old_shortcut) && |
- ShellUtil::GetChromeShortcutName(dist, false, first_name, |
- &new_shortcut)) { |
- // Update doesn't allow changing the target, so rename first. |
- BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, |
- base::Bind(&RenameChromeDesktopShortcutForProfile, |
- old_shortcut, new_shortcut)); |
- |
- // Fetch the avatar for the first profile and make a copy of the Image |
- // to ensure that the underlying image data is AddRef'd, in case the |
- // original copy is deleted. |
- gfx::Image& first_avatar = |
- ResourceBundle::GetSharedInstance().GetNativeImageNamed( |
- ProfileInfoCache::GetDefaultAvatarIconResourceIDAtIndex( |
- cache.GetAvatarIconIndexOfProfileAtIndex(first_index))); |
- gfx::Image* first_avatar_copy = new gfx::Image(first_avatar); |
- FilePath first_path = cache.GetPathOfProfileAtIndex(first_index); |
- |
- BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, |
- base::Bind(&UpdateChromeDesktopShortcutForProfile, |
- new_shortcut, |
- CreateProfileShortcutSwitch(UTF8ToUTF16( |
- first_path.BaseName().MaybeAsASCII())), |
- first_path, |
- base::Owned(first_avatar_copy))); |
- } |
- } |
- } else { // Only one profile, so create original shortcut, with no avatar. |
- BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, |
- base::Bind(&CreateChromeDesktopShortcutForProfile, |
- string16(), string16(), FilePath(), |
- static_cast<gfx::Image*>(NULL), true)); |
- } |
+// static |
+ProfileShortcutManager* ProfileShortcutManager::Create() { |
+ return new ProfileShortcutManagerWin(); |
} |
-void ProfileShortcutManagerWin::OnProfileAdded( |
- const FilePath& profile_path) { |
-} |
- |
-void ProfileShortcutManagerWin::OnProfileWillBeRemoved( |
- const FilePath& profile_path) { |
- ProfileInfoCache& cache = |
- g_browser_process->profile_manager()->GetProfileInfoCache(); |
- size_t index = cache.GetIndexOfProfileWithPath(profile_path); |
- if (index == std::string::npos) |
- return; |
- string16 profile_name = cache.GetNameOfProfileAtIndex(index); |
- BrowserDistribution* dist = BrowserDistribution::GetDistribution(); |
- string16 shortcut; |
- if (ShellUtil::GetChromeShortcutName(dist, false, profile_name, &shortcut)) { |
- std::vector<string16> shortcuts(1, shortcut); |
- BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, |
- base::Bind(&CallShellUtilBoolFunction, |
- base::Bind( |
- &ShellUtil::RemoveChromeDesktopShortcutsWithAppendedNames, |
- shortcuts))); |
+// static |
+bool ProfileShortcutManager::IsFeatureEnabled() { |
+ if (CommandLine::ForCurrentProcess()->HasSwitch( |
+ switches::kProfileDesktopShortcuts)) { |
+ return true; |
} |
+ return false; |
} |
-void ProfileShortcutManagerWin::OnProfileWasRemoved( |
- const FilePath& profile_path, |
- const string16& profile_name) { |
- BrowserThread::PostTask( |
- BrowserThread::FILE, FROM_HERE, |
- base::Bind(&DeleteAutoLaunchValueForProfile, profile_path)); |
- |
- // If there is one profile left, we want to remove the badge and name from it. |
- ProfileInfoCache& cache = |
- g_browser_process->profile_manager()->GetProfileInfoCache(); |
- if (cache.GetNumberOfProfiles() != 1) |
+void ProfileShortcutManagerWin::CreateChromeDesktopShortcut( |
+ 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; |
- |
- FilePath last_profile_path = cache.GetPathOfProfileAtIndex(0); |
- string16 old_shortcut; |
- string16 new_shortcut; |
BrowserDistribution* dist = BrowserDistribution::GetDistribution(); |
- if (ShellUtil::GetChromeShortcutName( |
- dist, false, cache.GetNameOfProfileAtIndex(0), &old_shortcut) && |
- ShellUtil::GetChromeShortcutName( |
- dist, false, L"", &new_shortcut)) { |
- BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, |
- base::Bind(&RenameChromeDesktopShortcutForProfile, |
- old_shortcut, |
- new_shortcut)); |
- BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, |
- base::Bind(&UpdateChromeDesktopShortcutForProfile, |
- new_shortcut, |
- CreateProfileShortcutSwitch(UTF8ToUTF16( |
- last_profile_path.BaseName().MaybeAsASCII())), |
- last_profile_path, |
- static_cast<gfx::Image*>(NULL))); |
- } |
-} |
- |
-void ProfileShortcutManagerWin::OnProfileNameChanged( |
- const FilePath& profile_path, |
- const string16& old_profile_name) { |
- // Launch task to change name of desktop shortcut on Windows. |
- // TODO(mirandac): respect master_preferences choice to create no shortcuts |
- // (see http://crbug.com/104463) |
- ProfileInfoCache& cache = |
- g_browser_process->profile_manager()->GetProfileInfoCache(); |
- size_t index = cache.GetIndexOfProfileWithPath(profile_path); |
- if (index == std::string::npos) |
+ string16 description; |
+ if (!dist) |
return; |
- string16 new_profile_name = cache.GetNameOfProfileAtIndex(index); |
+ else |
+ description = WideToUTF16(dist->GetAppDescription()); |
- string16 old_shortcut; |
- string16 new_shortcut; |
- BrowserDistribution* dist = BrowserDistribution::GetDistribution(); |
- if (ShellUtil::GetChromeShortcutName( |
- dist, false, old_profile_name, &old_shortcut) && |
- ShellUtil::GetChromeShortcutName( |
- dist, false, new_profile_name, &new_shortcut)) { |
- BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, |
- base::Bind(&RenameChromeDesktopShortcutForProfile, |
- old_shortcut, |
- new_shortcut)); |
+ // 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))); |
} |
-} |
-void ProfileShortcutManagerWin::OnProfileAvatarChanged( |
- const FilePath& profile_path) { |
- ProfileInfoCache& cache = |
- g_browser_process->profile_manager()->GetProfileInfoCache(); |
- size_t index = cache.GetIndexOfProfileWithPath(profile_path); |
- if (index == std::string::npos) |
- return; |
- string16 profile_name = cache.GetNameOfProfileAtIndex(index); |
- string16 profile_base_dir = |
- UTF8ToUTF16(profile_path.BaseName().MaybeAsASCII()); |
- const gfx::Image& avatar_image = cache.GetAvatarIconOfProfileAtIndex(index); |
- |
- // 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)) { |
- // We make a copy of the Image to ensure that the underlying image data is |
- // AddRef'd, in case the original copy gets deleted. |
- gfx::Image* avatar_copy = new gfx::Image(avatar_image); |
- BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, |
- base::Bind(&UpdateChromeDesktopShortcutForProfile, |
- new_shortcut, |
- CreateProfileShortcutSwitch(profile_base_dir), |
- profile_path, |
- base::Owned(avatar_copy))); |
- } |
+ 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); |
} |
-// static |
-std::vector<string16> ProfileShortcutManagerWin::GenerateShortcutsFromProfiles( |
- const std::vector<string16>& profile_names) { |
- BrowserDistribution* dist = BrowserDistribution::GetDistribution(); |
- std::vector<string16> shortcuts; |
- shortcuts.reserve(profile_names.size()); |
- for (std::vector<string16>::const_iterator it = profile_names.begin(); |
- it != profile_names.end(); |
- ++it) { |
+void ProfileShortcutManagerWin::DeleteChromeDesktopShortcut( |
+ const FilePath& profile_path) { |
+ // If the profile to be deleted has a shortcut |
+ if (profile_shortcuts_.count(profile_path)) { |
+ BrowserDistribution* dist = BrowserDistribution::GetDistribution(); |
string16 shortcut; |
- if (ShellUtil::GetChromeShortcutName(dist, false, *it, &shortcut)) |
- shortcuts.push_back(shortcut); |
+ // If we can find the shortcut, delete it |
+ if (ShellUtil::GetChromeShortcutName(dist, false, |
+ profile_shortcuts_[profile_path].profile_name, &shortcut)) { |
+ std::vector<string16> appended_names(1, shortcut); |
+ BrowserThread::PostTask( |
+ BrowserThread::FILE, FROM_HERE, |
+ base::Bind(&CallShellUtilBoolFunction, base::Bind( |
+ &ShellUtil::RemoveChromeDesktopShortcutsWithAppendedNames, |
+ appended_names))); |
+ profile_shortcuts_.erase(profile_path); |
+ } |
} |
- return shortcuts; |
} |
+ |