summaryrefslogtreecommitdiffstats
path: root/chrome/browser
diff options
context:
space:
mode:
authormirandac@chromium.org <mirandac@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-11-22 14:58:23 +0000
committermirandac@chromium.org <mirandac@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-11-22 14:58:23 +0000
commitf8b2ca3555497caedc341ec16f110e310c15562d (patch)
treee9d22ccd68a40201dc1bb9834efb7ed26ab49561 /chrome/browser
parentd21a8a5fb4d3af19452149bdcf7f6855ba80a194 (diff)
downloadchromium_src-f8b2ca3555497caedc341ec16f110e310c15562d.zip
chromium_src-f8b2ca3555497caedc341ec16f110e310c15562d.tar.gz
chromium_src-f8b2ca3555497caedc341ec16f110e310c15562d.tar.bz2
Add Windows desktop shortcut for multiple profiles.
BUG=87770 TEST=new unit tests added with this CL. Review URL: http://codereview.chromium.org/8502033 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@111156 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
-rw-r--r--chrome/browser/chrome_browser_main_win.cc13
-rw-r--r--chrome/browser/first_run/first_run_win.cc2
-rw-r--r--chrome/browser/profiles/profile_info_cache.cc73
-rw-r--r--chrome/browser/profiles/profile_info_cache.h16
-rw-r--r--chrome/browser/profiles/profile_info_cache_observer.h30
-rw-r--r--chrome/browser/profiles/profile_manager.cc13
-rw-r--r--chrome/browser/profiles/profile_manager.h26
-rw-r--r--chrome/browser/profiles/profile_manager_unittest.cc6
-rw-r--r--chrome/browser/profiles/profile_shortcut_manager_win.cc216
-rw-r--r--chrome/browser/profiles/profile_shortcut_manager_win.h62
10 files changed, 436 insertions, 21 deletions
diff --git a/chrome/browser/chrome_browser_main_win.cc b/chrome/browser/chrome_browser_main_win.cc
index 928315b..3965c1d 100644
--- a/chrome/browser/chrome_browser_main_win.cc
+++ b/chrome/browser/chrome_browser_main_win.cc
@@ -22,6 +22,8 @@
#include "chrome/browser/browser_util_win.h"
#include "chrome/browser/first_run/first_run.h"
#include "chrome/browser/metrics/metrics_service.h"
+#include "chrome/browser/profiles/profile_info_cache.h"
+#include "chrome/browser/profiles/profile_shortcut_manager_win.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/views/uninstall_view.h"
#include "chrome/common/chrome_constants.h"
@@ -141,11 +143,18 @@ int DoUninstallTasks(bool chrome_still_running) {
// created by us and not by the installer so |alternate| is false.
BrowserDistribution* dist = BrowserDistribution::GetDistribution();
if (!ShellUtil::RemoveChromeDesktopShortcut(dist, ShellUtil::CURRENT_USER,
- false))
+ false)) {
VLOG(1) << "Failed to delete desktop shortcut.";
+ }
+ if (!ShellUtil::RemoveChromeDesktopShortcutsWithAppendedNames(
+ ProfileShortcutManagerWin::GenerateShortcutsFromProfiles(
+ ProfileInfoCache::GetProfileNames()))) {
+ VLOG(1) << "Failed to delete desktop profiles shortcuts.";
+ }
if (!ShellUtil::RemoveChromeQuickLaunchShortcut(dist,
- ShellUtil::CURRENT_USER))
+ ShellUtil::CURRENT_USER)) {
VLOG(1) << "Failed to delete quick launch shortcut.";
+ }
}
return ret;
}
diff --git a/chrome/browser/first_run/first_run_win.cc b/chrome/browser/first_run/first_run_win.cc
index 6d343c9..9a0c675 100644
--- a/chrome/browser/first_run/first_run_win.cc
+++ b/chrome/browser/first_run/first_run_win.cc
@@ -108,6 +108,8 @@ bool CreateChromeDesktopShortcut() {
dist,
chrome_exe.value(),
dist->GetAppDescription(),
+ L"",
+ L"",
ShellUtil::CURRENT_USER,
false,
true); // create if doesn't exist.
diff --git a/chrome/browser/profiles/profile_info_cache.cc b/chrome/browser/profiles/profile_info_cache.cc
index c0966da..c3b20e0 100644
--- a/chrome/browser/profiles/profile_info_cache.cc
+++ b/chrome/browser/profiles/profile_info_cache.cc
@@ -12,6 +12,7 @@
#include "base/stringprintf.h"
#include "base/utf_string_conversions.h"
#include "base/values.h"
+#include "chrome/browser/browser_process.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/prefs/scoped_user_pref_update.h"
#include "chrome/common/chrome_notification_types.h"
@@ -86,7 +87,7 @@ const int kDefaultNames[] = {
IDS_DEFAULT_AVATAR_NAME_25
};
-} // namespace
+} // namespace
ProfileInfoCache::ProfileInfoCache(PrefService* prefs,
const FilePath& user_data_dir)
@@ -127,10 +128,22 @@ void ProfileInfoCache::AddProfileToCache(const FilePath& profile_path,
sorted_keys_.insert(FindPositionForProfile(key, name), key);
+ FOR_EACH_OBSERVER(ProfileInfoCacheObserver,
+ observer_list_,
+ OnProfileAdded(name, UTF8ToUTF16(key)));
+
content::NotificationService::current()->Notify(
- chrome::NOTIFICATION_PROFILE_CACHED_INFO_CHANGED,
- content::NotificationService::AllSources(),
- content::NotificationService::NoDetails());
+ chrome::NOTIFICATION_PROFILE_CACHED_INFO_CHANGED,
+ content::NotificationService::AllSources(),
+ content::NotificationService::NoDetails());
+}
+
+void ProfileInfoCache::AddObserver(ProfileInfoCacheObserver* obs) {
+ observer_list_.AddObserver(obs);
+}
+
+void ProfileInfoCache::RemoveObserver(ProfileInfoCacheObserver* obs) {
+ observer_list_.RemoveObserver(obs);
}
void ProfileInfoCache::DeleteProfileFromCache(const FilePath& profile_path) {
@@ -138,13 +151,22 @@ void ProfileInfoCache::DeleteProfileFromCache(const FilePath& profile_path) {
DictionaryValue* cache = update.Get();
std::string key = CacheKeyFromProfilePath(profile_path);
+ DictionaryValue* info = NULL;
+ cache->GetDictionary(key, &info);
+ string16 name;
+ info->GetString(kNameKey, &name);
+
+ FOR_EACH_OBSERVER(ProfileInfoCacheObserver,
+ observer_list_,
+ OnProfileRemoved(name));
+
cache->Remove(key, NULL);
sorted_keys_.erase(std::find(sorted_keys_.begin(), sorted_keys_.end(), key));
content::NotificationService::current()->Notify(
- chrome::NOTIFICATION_PROFILE_CACHED_INFO_CHANGED,
- content::NotificationService::AllSources(),
- content::NotificationService::NoDetails());
+ chrome::NOTIFICATION_PROFILE_CACHED_INFO_CHANGED,
+ content::NotificationService::AllSources(),
+ content::NotificationService::NoDetails());
}
size_t ProfileInfoCache::GetNumberOfProfiles() const {
@@ -215,6 +237,8 @@ size_t ProfileInfoCache::GetAvatarIconIndexOfProfileAtIndex(size_t index)
void ProfileInfoCache::SetNameOfProfileAtIndex(size_t index,
const string16& name) {
scoped_ptr<DictionaryValue> info(GetInfoForProfileAtIndex(index)->DeepCopy());
+ string16 old_name;
+ info->GetString(kNameKey, &old_name);
info->SetString(kNameKey, name);
// This takes ownership of |info|.
SetInfoForProfileAtIndex(index, info.release());
@@ -227,10 +251,14 @@ void ProfileInfoCache::SetNameOfProfileAtIndex(size_t index,
sorted_keys_.erase(key_it);
sorted_keys_.insert(FindPositionForProfile(key, name), key);
+ FOR_EACH_OBSERVER(ProfileInfoCacheObserver,
+ observer_list_,
+ OnProfileNameChanged(old_name, name));
+
content::NotificationService::current()->Notify(
- chrome::NOTIFICATION_PROFILE_CACHED_INFO_CHANGED,
- content::NotificationService::AllSources(),
- content::NotificationService::NoDetails());
+ chrome::NOTIFICATION_PROFILE_CACHED_INFO_CHANGED,
+ content::NotificationService::AllSources(),
+ content::NotificationService::NoDetails());
}
void ProfileInfoCache::SetUserNameOfProfileAtIndex(size_t index,
@@ -395,9 +423,9 @@ void ProfileInfoCache::SetInfoForProfileAtIndex(size_t index,
cache->Set(sorted_keys_[index], info);
content::NotificationService::current()->Notify(
- chrome::NOTIFICATION_PROFILE_CACHED_INFO_CHANGED,
- content::NotificationService::AllSources(),
- content::NotificationService::NoDetails());
+ chrome::NOTIFICATION_PROFILE_CACHED_INFO_CHANGED,
+ content::NotificationService::AllSources(),
+ content::NotificationService::NoDetails());
}
std::string ProfileInfoCache::CacheKeyFromProfilePath(
@@ -423,6 +451,25 @@ std::vector<std::string>::iterator ProfileInfoCache::FindPositionForProfile(
return sorted_keys_.end();
}
+// static
+std::vector<string16> ProfileInfoCache::GetProfileNames() {
+ std::vector<string16> names;
+ PrefService* local_state = g_browser_process->local_state();
+ const DictionaryValue* cache = local_state->GetDictionary(
+ prefs::kProfileInfoCache);
+ string16 name;
+ for (base::DictionaryValue::key_iterator it = cache->begin_keys();
+ it != cache->end_keys();
+ ++it) {
+ base::DictionaryValue* info = NULL;
+ cache->GetDictionary(*it, &info);
+ info->GetString(kNameKey, &name);
+ names.push_back(name);
+ }
+ return names;
+}
+
+// static
void ProfileInfoCache::RegisterPrefs(PrefService* prefs) {
prefs->RegisterDictionaryPref(prefs::kProfileInfoCache);
}
diff --git a/chrome/browser/profiles/profile_info_cache.h b/chrome/browser/profiles/profile_info_cache.h
index 345503c..63e08ff 100644
--- a/chrome/browser/profiles/profile_info_cache.h
+++ b/chrome/browser/profiles/profile_info_cache.h
@@ -12,7 +12,9 @@
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/file_path.h"
+#include "base/observer_list.h"
#include "base/string16.h"
+#include "chrome/browser/profiles/profile_info_cache_observer.h"
#include "chrome/browser/profiles/profile_info_interface.h"
namespace gfx {
@@ -25,7 +27,6 @@ class DictionaryValue;
class PrefService;
-
// This class saves various information about profiles to local preferences.
// This cache can be used to display a list of profiles without having to
// actually load the profiles from disk.
@@ -83,13 +84,22 @@ class ProfileInfoCache : public ProfileInfoInterface {
static bool IsDefaultAvatarIconUrl(const std::string& icon_url,
size_t *icon_index);
+ // Gets all names of profiles associated with this instance of Chrome.
+ // Because this method will be called during uninstall, before the creation
+ // of the ProfileManager, it reads directly from the local state preferences,
+ // rather than going through the ProfileInfoCache object.
+ static std::vector<string16> GetProfileNames();
+
// Register cache related preferences in Local State.
static void RegisterPrefs(PrefService* prefs);
+ void AddObserver(ProfileInfoCacheObserver* obs);
+ void RemoveObserver(ProfileInfoCacheObserver* obs);
+
private:
const base::DictionaryValue* GetInfoForProfileAtIndex(size_t index) const;
// Saves the profile info to a cache and takes ownership of |info|.
- // Currently the only information that is cached is the profiles name,
+ // Currently the only information that is cached is the profile's name,
// user name, and avatar icon.
void SetInfoForProfileAtIndex(size_t index, base::DictionaryValue* info);
std::string CacheKeyFromProfilePath(const FilePath& profile_path) const;
@@ -110,6 +120,8 @@ class ProfileInfoCache : public ProfileInfoInterface {
std::vector<std::string> sorted_keys_;
FilePath user_data_dir_;
+ ObserverList<ProfileInfoCacheObserver> observer_list_;
+
DISALLOW_COPY_AND_ASSIGN(ProfileInfoCache);
};
diff --git a/chrome/browser/profiles/profile_info_cache_observer.h b/chrome/browser/profiles/profile_info_cache_observer.h
new file mode 100644
index 0000000..43beaef7
--- /dev/null
+++ b/chrome/browser/profiles/profile_info_cache_observer.h
@@ -0,0 +1,30 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_PROFILES_PROFILE_INFO_CACHE_OBSERVER_H_
+#define CHROME_BROWSER_PROFILES_PROFILE_INFO_CACHE_OBSERVER_H_
+#pragma once
+
+// This class provides an Observer interface to watch for changes to the
+// ProfileInfoCache.
+class ProfileInfoCacheObserver {
+ public:
+ virtual ~ProfileInfoCacheObserver() {}
+
+ virtual void OnProfileAdded(
+ const string16& profile_name,
+ const string16& profile_base_dir) = 0;
+ virtual void OnProfileRemoved(
+ const string16& profile_name) = 0;
+ virtual void OnProfileNameChanged(
+ const string16& old_profile_name,
+ const string16& new_profile_name) = 0;
+
+ protected:
+ ProfileInfoCacheObserver() {}
+
+ DISALLOW_COPY_AND_ASSIGN(ProfileInfoCacheObserver);
+};
+
+#endif // CHROME_BROWSER_PROFILES_PROFILE_INFO_CACHE_OBSERVER_H_
diff --git a/chrome/browser/profiles/profile_manager.cc b/chrome/browser/profiles/profile_manager.cc
index 26d38b6..6836041 100644
--- a/chrome/browser/profiles/profile_manager.cc
+++ b/chrome/browser/profiles/profile_manager.cc
@@ -213,6 +213,9 @@ ProfileManager::ProfileManager(const FilePath& user_data_dir)
ProfileManager::~ProfileManager() {
BrowserList::RemoveObserver(this);
+#if defined(OS_WIN)
+ profile_info_cache_->RemoveObserver(profile_shortcut_manager_.get());
+#endif
}
FilePath ProfileManager::GetDefaultProfileDir(
@@ -589,6 +592,10 @@ ProfileInfoCache& ProfileManager::GetProfileInfoCache() {
if (!profile_info_cache_.get()) {
profile_info_cache_.reset(new ProfileInfoCache(
g_browser_process->local_state(), user_data_dir_));
+#if defined(OS_WIN)
+ profile_shortcut_manager_.reset(new ProfileShortcutManagerWin());
+ profile_info_cache_->AddObserver(profile_shortcut_manager_.get());
+#endif
}
return *profile_info_cache_.get();
}
@@ -699,3 +706,9 @@ void ProfileManager::RegisterTestingProfile(Profile* profile,
if (add_to_cache)
AddProfileToCache(profile);
}
+
+#if defined(OS_WIN)
+void ProfileManager::RemoveProfileShortcutManagerForTesting() {
+ profile_info_cache_->RemoveObserver(profile_shortcut_manager_.get());
+}
+#endif
diff --git a/chrome/browser/profiles/profile_manager.h b/chrome/browser/profiles/profile_manager.h
index 12c5d99..b353b0a 100644
--- a/chrome/browser/profiles/profile_manager.h
+++ b/chrome/browser/profiles/profile_manager.h
@@ -24,13 +24,17 @@
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
+#if defined(OS_WIN)
+#include "chrome/browser/profiles/profile_shortcut_manager_win.h"
+#endif
+
class NewProfileLauncher;
class ProfileInfoCache;
class ProfileManagerObserver {
public:
enum Status {
- // So epic.
+ // Asynchronous Profile services were not created.
STATUS_FAIL,
// Profile created but before initializing extensions and promo resources.
STATUS_CREATED,
@@ -190,6 +194,11 @@ class ProfileManager : public base::NonThreadSafe,
// for testing. If |addToCache|, add to ProfileInfoCache as well.
void RegisterTestingProfile(Profile* profile, bool addToCache);
+#if defined(OS_WIN)
+ // Remove the shortcut manager for testing.
+ void RemoveProfileShortcutManagerForTesting();
+#endif
+
const FilePath& user_data_dir() const { return user_data_dir_; }
protected:
@@ -243,7 +252,7 @@ class ProfileManager : public base::NonThreadSafe,
const ProfileManager::ProfilePathAndName& pair1,
const ProfileManager::ProfilePathAndName& pair2);
- // Adds |profile| to the profile info cache if it's not already there.
+ // Adds |profile| to the profile info cache if it hasn't been added yet.
void AddProfileToCache(Profile* profile);
// For ChromeOS, determines if profile should be otr.
@@ -270,13 +279,22 @@ class ProfileManager : public base::NonThreadSafe,
bool will_import_;
// Maps profile path to ProfileInfo (if profile has been created). Use
- // RegisterProfile() to add into this map.
+ // RegisterProfile() to add into this map. This map owns all loaded profile
+ // objects in a running instance of Chrome.
typedef std::map<FilePath, linked_ptr<ProfileInfo> > ProfilesInfoMap;
ProfilesInfoMap profiles_info_;
- // Object to cache various information about profiles.
+ // Object to cache various information about profiles. Contains information
+ // about every profile which has been created for this instance of Chrome,
+ // if it has not been explicitly deleted.
scoped_ptr<ProfileInfoCache> profile_info_cache_;
+#if defined(OS_WIN)
+ // Manages the creation, deletion, and renaming of Windows shortcuts by
+ // observing the ProfileInfoCache.
+ scoped_ptr<ProfileShortcutManagerWin> profile_shortcut_manager_;
+#endif
+
DISALLOW_COPY_AND_ASSIGN(ProfileManager);
};
diff --git a/chrome/browser/profiles/profile_manager_unittest.cc b/chrome/browser/profiles/profile_manager_unittest.cc
index 0392b4d..4f91e70 100644
--- a/chrome/browser/profiles/profile_manager_unittest.cc
+++ b/chrome/browser/profiles/profile_manager_unittest.cc
@@ -66,6 +66,12 @@ class ProfileManagerTest : public testing::Test {
// Create a new temporary directory, and store the path
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
profile_manager_.reset(new ProfileManagerWithoutInit(temp_dir_.path()));
+#if defined(OS_WIN)
+ // Force the ProfileInfoCache to be created immediately, so we can
+ // remove the shortcut manager for testing.
+ profile_manager_->GetProfileInfoCache();
+ profile_manager_->RemoveProfileShortcutManagerForTesting();
+#endif
}
virtual void TearDown() {
diff --git a/chrome/browser/profiles/profile_shortcut_manager_win.cc b/chrome/browser/profiles/profile_shortcut_manager_win.cc
new file mode 100644
index 0000000..8258ef5
--- /dev/null
+++ b/chrome/browser/profiles/profile_shortcut_manager_win.cc
@@ -0,0 +1,216 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// 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 "base/bind.h"
+#include "base/file_path.h"
+#include "base/file_util.h"
+#include "base/path_service.h"
+#include "base/stringprintf.h"
+#include "base/utf_string_conversions.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_manager.h"
+#include "chrome/common/chrome_constants.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/installer/util/browser_distribution.h"
+#include "chrome/installer/util/shell_util.h"
+#include "content/public/browser/browser_thread.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+
+using content::BrowserThread;
+
+namespace {
+
+// 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(string16 profile_base_dir) {
+ string16 profile_directory = base::StringPrintf(L"--%ls=\"%ls\"",
+ ASCIIToUTF16(switches::kProfileDirectory).c_str(),
+ profile_base_dir.c_str());
+ return profile_directory;
+}
+
+// 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();
+}
+
+} // namespace
+
+ProfileShortcutManagerWin::ProfileShortcutManagerWin() {
+}
+
+ProfileShortcutManagerWin::~ProfileShortcutManagerWin() {
+}
+
+void ProfileShortcutManagerWin::OnProfileAdded(
+ const string16& profile_name,
+ const string16& profile_base_dir) {
+ // 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));
+
+ // If this is the very first multi-user account created, change the
+ // original shortcut to launch with the First User profile.
+ PrefService* local_state = g_browser_process->local_state();
+ 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;
+ string16 new_shortcut;
+ if (ShellUtil::GetChromeShortcutName(dist, false, L"", &old_shortcut) &&
+ ShellUtil::GetChromeShortcutName(dist, false, default_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));
+ BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
+ base::Bind(&UpdateChromeDesktopShortcutForProfile,
+ new_shortcut, default_directory));
+ }
+ }
+ } else { // Only one profile, so create original shortcut.
+ BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
+ base::Bind(&CreateChromeDesktopShortcutForProfile,
+ L"", L"", true));
+ }
+}
+
+void ProfileShortcutManagerWin::OnProfileRemoved(
+ const string16& profile_name) {
+ 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)));
+ }
+}
+
+void ProfileShortcutManagerWin::OnProfileNameChanged(
+ const string16& old_profile_name,
+ const string16& new_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)
+ 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));
+ }
+}
+
+// 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) {
+ string16 shortcut;
+ if (ShellUtil::GetChromeShortcutName(dist, false, *it, &shortcut))
+ shortcuts.push_back(shortcut);
+ }
+ 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);
+}
diff --git a/chrome/browser/profiles/profile_shortcut_manager_win.h b/chrome/browser/profiles/profile_shortcut_manager_win.h
new file mode 100644
index 0000000..938bcbe
--- /dev/null
+++ b/chrome/browser/profiles/profile_shortcut_manager_win.h
@@ -0,0 +1,62 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_PROFILES_PROFILE_SHORTCUT_MANAGER_WIN_H_
+#define CHROME_BROWSER_PROFILES_PROFILE_SHORTCUT_MANAGER_WIN_H_
+#pragma once
+
+#include <vector>
+
+#include "base/callback.h"
+#include "base/compiler_specific.h"
+#include "base/string16.h"
+#include "chrome/browser/profiles/profile_info_cache_observer.h"
+
+// This class observes the ProfileInfoCache, and makes corresponding changes
+// to shortcuts on the user's desktop in Windows systems.
+class ProfileShortcutManagerWin : public ProfileInfoCacheObserver {
+ public:
+ ProfileShortcutManagerWin();
+ virtual ~ProfileShortcutManagerWin();
+
+ // ProfileInfoCacheObserver:
+ virtual void OnProfileAdded(
+ const string16& profile_name,
+ const string16& profile_base_dir) OVERRIDE;
+ virtual void OnProfileRemoved(
+ const string16& profile_name) OVERRIDE;
+ virtual void OnProfileNameChanged(
+ const string16& old_profile_name,
+ const string16& new_profile_name) OVERRIDE;
+
+ // Takes a vector of profile names (for example: "Sparky") and generates a
+ // vector of shortcut link names (for example: "Chromium (Sparky).lnk").
+ static std::vector<string16> GenerateShortcutsFromProfiles(
+ const std::vector<string16>& profile_names);
+
+ private:
+ // Creates a desktop shortcut to open Chrome with the given profile name and
+ // directory. Iff |create|, create shortcut if it doesn't already exist. Must
+ // be called on the FILE thread.
+ static void CreateChromeDesktopShortcutForProfile(
+ const string16& profile_name,
+ const string16& directory,
+ bool create);
+
+ // Renames an existing Chrome desktop profile shortcut. Must be called on the
+ // FILE thread.
+ static void RenameChromeDesktopShortcutForProfile(
+ const string16& old_profile_name,
+ const string16& new_profile_name);
+
+ // Updates the arguments to a Chrome desktop shortcut for a profile. Must be
+ // called on the FILE thread.
+ static void UpdateChromeDesktopShortcutForProfile(
+ const string16& shortcut,
+ const string16& arguments);
+
+ DISALLOW_COPY_AND_ASSIGN(ProfileShortcutManagerWin);
+};
+
+#endif // CHROME_BROWSER_PROFILES_PROFILE_SHORTCUT_MANAGER_WIN_H_