| 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,6 @@
|
| 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());
|
| -}
|
| -
|
| -// 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();
|
| -}
|
| -
|
| // 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 +58,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 +102,128 @@
|
| 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
|
|
|
| -ProfileShortcutManagerWin::ProfileShortcutManagerWin() {
|
| -}
|
| +class ProfileShortcutManagerWin : public ProfileShortcutManager {
|
| + public:
|
| + ProfileShortcutManagerWin();
|
| + virtual ~ProfileShortcutManagerWin();
|
|
|
| -ProfileShortcutManagerWin::~ProfileShortcutManagerWin() {
|
| -}
|
| + virtual void CreateChromeDesktopShortcut(
|
| + const FilePath& profile_path, const string16& profile_name,
|
| + const gfx::Image& avatar_image) OVERRIDE;
|
| + virtual void DeleteChromeDesktopShortcut(const FilePath& profile_path)
|
| + OVERRIDE;
|
|
|
| -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;
|
| + private:
|
| + struct ProfileShortcutInfo {
|
| + string16 flags;
|
| + string16 profile_name;
|
| + 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) {
|
| - {
|
| - // 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));
|
| + ProfileShortcutInfo()
|
| + : flags(string16()),
|
| + profile_name(string16()),
|
| + avatar_image(gfx::Image()) {
|
| }
|
|
|
| - // 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();
|
| + 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) {
|
| + }
|
| + };
|
|
|
| - 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));
|
| + // TODO(hallielaine): Repopulate this map on chrome session startup
|
| + typedef std::map<FilePath, ProfileShortcutInfo> ProfileShortcutsMap;
|
| + ProfileShortcutsMap profile_shortcuts_;
|
| +};
|
|
|
| - // 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
|
| +bool ProfileShortcutManager::IsFeatureEnabled() {
|
| + if (CommandLine::ForCurrentProcess()->HasSwitch(
|
| + switches::kProfileDesktopShortcuts)) {
|
| + return true;
|
| }
|
| + return false;
|
| }
|
|
|
| -void ProfileShortcutManagerWin::OnProfileAdded(
|
| - const FilePath& profile_path) {
|
| +// static
|
| +ProfileShortcutManager* ProfileShortcutManager::Create() {
|
| + return new ProfileShortcutManagerWin();
|
| }
|
|
|
| -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)));
|
| - }
|
| +ProfileShortcutManagerWin::ProfileShortcutManagerWin() {
|
| }
|
|
|
| -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)
|
| - 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)));
|
| - }
|
| +ProfileShortcutManagerWin::~ProfileShortcutManagerWin() {
|
| }
|
|
|
| -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)
|
| +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;
|
| - string16 new_profile_name = cache.GetNameOfProfileAtIndex(index);
|
| -
|
| - 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));
|
| - }
|
| -}
|
| -
|
| -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)
|
| + string16 description;
|
| + if (!dist)
|
| return;
|
| - string16 profile_name = cache.GetNameOfProfileAtIndex(index);
|
| - string16 profile_base_dir =
|
| - UTF8ToUTF16(profile_path.BaseName().MaybeAsASCII());
|
| - const gfx::Image& avatar_image = cache.GetAvatarIconOfProfileAtIndex(index);
|
| + description = WideToUTF16(dist->GetAppDescription());
|
|
|
| - // 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)));
|
| + // 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);
|
| }
|
|
|
| -// static
|
| -std::vector<string16> ProfileShortcutManagerWin::GenerateShortcutsFromProfiles(
|
| - const std::vector<string16>& profile_names) {
|
| +void ProfileShortcutManagerWin::DeleteChromeDesktopShortcut(
|
| + const FilePath& profile_path) {
|
| 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) {
|
| - string16 shortcut;
|
| - if (ShellUtil::GetChromeShortcutName(dist, false, *it, &shortcut))
|
| - shortcuts.push_back(shortcut);
|
| + string16 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;
|
| }
|
| +
|
|
|