Create and delete desktop shortcuts in general.

Currently planning 6 steps for this feature:
1. (this step) Create/delete shortcuts in general (few edge cases)
2. Add functionality for the checkbox- allow the user to select whether they want a shortcut or not from the create/manage profile dialogs
3. Find shortcuts on the desktop by their arguments instead of the path.
4. Handle edge case of 1 to 2 and 2 to 1 profiles (adding/removing icon and name from the shortcut)
5. Update shortcuts when the user changes their name/icon
6. Repopulate shortcuts map when browser starts up (to allow delete/update on new browser instances) 

This CL depends on: Issue 10826188

BUG=133585
TEST=manual testing

Review URL: https://chromiumcodereview.appspot.com/10823217

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@151974 0039d316-1c4b-4281-b951-d872f2087c98
parent 77363287
......@@ -25,7 +25,7 @@
#include "chrome/browser/media_gallery/media_device_notifications_window_win.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/profiles/profile_shortcut_manager.h"
#include "chrome/browser/ui/simple_message_box.h"
#include "chrome/browser/ui/uninstall_browser_prompt.h"
#include "chrome/common/chrome_constants.h"
......@@ -132,11 +132,7 @@ int DoUninstallTasks(bool chrome_still_running) {
dist, ShellUtil::CURRENT_USER, ShellUtil::SHORTCUT_NO_OPTIONS)) {
VLOG(1) << "Failed to delete desktop shortcut.";
}
if (!ShellUtil::RemoveChromeDesktopShortcutsWithAppendedNames(
ProfileShortcutManagerWin::GenerateShortcutsFromProfiles(
ProfileInfoCache::GetProfileNames()))) {
VLOG(1) << "Failed to delete desktop profiles shortcuts.";
}
// TODO(hallielaine): Cleanup profiles shortcuts.
if (!ShellUtil::RemoveChromeQuickLaunchShortcut(dist,
ShellUtil::CURRENT_USER)) {
VLOG(1) << "Failed to delete quick launch shortcut.";
......
......@@ -7,6 +7,7 @@
#include "base/bind.h"
#include "base/stl_util.h"
#include "base/string_number_conversions.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/profiles/avatar_menu_model_observer.h"
#include "chrome/browser/profiles/profile.h"
......@@ -102,7 +103,21 @@ void AvatarMenuModel::EditProfile(size_t index) {
}
void AvatarMenuModel::AddNewProfile() {
ProfileManager::CreateMultiProfileAsync(string16(), string16());
// Temporarily generate a random icon/name pair to create the profile with
// instead of opening a dialog for creating a profile.
// Remove on completion of BUG 134904.
if (ProfileShortcutManager::IsFeatureEnabled()) {
ProfileManager* profile_manager = g_browser_process->profile_manager();
ProfileInfoCache& cache = profile_manager->GetProfileInfoCache();
size_t icon_index = cache.ChooseAvatarIconIndexForNewProfile();
g_browser_process->profile_manager()->CreateMultiProfileAsync(
cache.ChooseNameForNewProfile(icon_index),
ASCIIToUTF16(cache.GetDefaultAvatarIconUrl(icon_index)));
} else {
ProfileManager::CreateMultiProfileAsync(string16(), string16());
}
ProfileMetrics::LogProfileAddNewUser(ProfileMetrics::ADD_NEW_USER_ICON);
}
......
......@@ -239,6 +239,7 @@ ProfileManager::ProfileManager(const FilePath& user_data_dir)
: user_data_dir_(user_data_dir),
logged_in_(false),
will_import_(false),
profile_shortcut_manager_(NULL),
#if !defined(OS_ANDROID)
ALLOW_THIS_IN_INITIALIZER_LIST(
browser_list_observer_(this)),
......@@ -266,13 +267,12 @@ ProfileManager::ProfileManager(const FilePath& user_data_dir)
this,
chrome::NOTIFICATION_BROWSER_CLOSE_CANCELLED,
content::NotificationService::AllSources());
if (ProfileShortcutManager::IsFeatureEnabled())
profile_shortcut_manager_.reset(ProfileShortcutManager::Create());
}
ProfileManager::~ProfileManager() {
#if defined(OS_WIN)
if (profile_shortcut_manager_.get())
profile_info_cache_->RemoveObserver(profile_shortcut_manager_.get());
#endif
}
FilePath ProfileManager::GetDefaultProfileDir(
......@@ -454,6 +454,15 @@ void ProfileManager::CreateProfileAsync(const FilePath& profile_path,
cache.AddProfileToCache(profile_path, name, string16(), icon_index);
}
info->callbacks.push_back(callback);
if (profile_shortcut_manager_.get() && !name.empty() &&
!icon_url.empty()) {
BrowserThread::PostTask(
BrowserThread::FILE, FROM_HERE,
base::Bind(&ProfileShortcutManager::CreateChromeDesktopShortcut,
base::Unretained(profile_shortcut_manager_.get()), profile_path, name,
ResourceBundle::GetSharedInstance().GetNativeImageNamed(
cache.GetDefaultAvatarIconResourceIDAtIndex(icon_index))));
}
}
}
......@@ -680,9 +689,6 @@ void ProfileManager::DoFinalInit(Profile* profile, bool go_off_the_record) {
InitProfileUserPrefs(profile);
AddProfileToCache(profile);
DoFinalInitLogging(profile);
#if defined(OS_WIN)
CreateDesktopShortcut(profile);
#endif
ProfileMetrics::LogNumberOfProfiles(this, ProfileMetrics::ADD_PROFILE_EVENT);
content::NotificationService::current()->Notify(
......@@ -732,12 +738,6 @@ Profile* ProfileManager::CreateProfileAsyncHelper(const FilePath& path,
Profile::CREATE_MODE_ASYNCHRONOUS);
}
#if defined(OS_WIN)
ProfileShortcutManagerWin* ProfileManager::CreateShortcutManager() {
return new ProfileShortcutManagerWin();
}
#endif
void ProfileManager::OnProfileCreated(Profile* profile,
bool success,
bool is_new_profile) {
......@@ -838,16 +838,6 @@ 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)
BrowserDistribution* dist = BrowserDistribution::GetDistribution();
ProfileShortcutManagerWin* shortcut_manager = CreateShortcutManager();
const CommandLine& command_line = *CommandLine::ForCurrentProcess();
if (dist && dist->CanCreateDesktopShortcuts() && shortcut_manager &&
!command_line.HasSwitch(switches::kDisableDesktopShortcuts)) {
profile_shortcut_manager_.reset(shortcut_manager);
profile_info_cache_->AddObserver(profile_shortcut_manager_.get());
}
#endif
}
return *profile_info_cache_.get();
}
......@@ -877,28 +867,6 @@ void ProfileManager::AddProfileToCache(Profile* profile) {
icon_index);
}
#if defined(OS_WIN)
void ProfileManager::CreateDesktopShortcut(Profile* profile) {
// TODO(sail): Disable creating new shortcuts for now.
return;
// Some distributions and tests cannot create desktop shortcuts, in which case
// profile_shortcut_manager_ will not be set.
if (!profile_shortcut_manager_.get())
return;
bool shortcut_created =
profile->GetPrefs()->GetBoolean(prefs::kProfileShortcutCreated);
if (!shortcut_created && GetNumberOfProfiles() > 1) {
profile_shortcut_manager_->AddProfileShortcut(profile->GetPath());
// We only ever create the shortcut for a profile once, so set a pref
// reminding us to skip this in the future.
profile->GetPrefs()->SetBoolean(prefs::kProfileShortcutCreated, true);
}
}
#endif
void ProfileManager::InitProfileUserPrefs(Profile* profile) {
ProfileInfoCache& cache = GetProfileInfoCache();
......@@ -989,6 +957,10 @@ void ProfileManager::ScheduleProfileForDeletion(const FilePath& profile_dir) {
QueueProfileDirectoryForDeletion(profile_dir);
cache.DeleteProfileFromCache(profile_dir);
// Delete possible shortcuts for this profile
if (profile_shortcut_manager_.get())
profile_shortcut_manager_->DeleteChromeDesktopShortcut(profile_dir);
ProfileMetrics::LogNumberOfProfiles(this,
ProfileMetrics::DELETE_PROFILE_EVENT);
}
......
......@@ -19,15 +19,12 @@
#include "base/message_loop.h"
#include "base/threading/non_thread_safe.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_shortcut_manager.h"
#include "chrome/browser/ui/browser_list_observer.h"
#include "chrome/browser/ui/startup/startup_types.h"
#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;
......@@ -209,12 +206,6 @@ class ProfileManager : public base::NonThreadSafe,
virtual Profile* CreateProfileAsyncHelper(const FilePath& path,
Delegate* delegate);
#if defined(OS_WIN)
// Creates a shortcut manager. Override this to return a different shortcut
// manager or NULL to avoid creating shortcuts.
virtual ProfileShortcutManagerWin* CreateShortcutManager();
#endif
private:
friend class TestingProfileManager;
FRIEND_TEST_ALL_PREFIXES(ProfileManagerBrowserTest, DeleteAllProfiles);
......@@ -258,12 +249,6 @@ class ProfileManager : public base::NonThreadSafe,
// Adds |profile| to the profile info cache if it hasn't been added yet.
void AddProfileToCache(Profile* profile);
#if defined(OS_WIN)
// Creates a profile desktop shortcut for |profile| if we are in multi
// profile mode and the shortcut has not been created before.
void CreateDesktopShortcut(Profile* profile);
#endif
// Initializes user prefs of |profile|. This includes profile name and
// avatar values
void InitProfileUserPrefs(Profile* profile);
......@@ -306,11 +291,8 @@ class ProfileManager : public base::NonThreadSafe,
// 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
// Manages the process of creating, deleteing and updating Desktop shortcuts.
scoped_ptr<ProfileShortcutManager> profile_shortcut_manager_;
#if !defined(OS_ANDROID)
class BrowserListObserver : public chrome::BrowserListObserver {
......
......@@ -77,13 +77,6 @@ class ProfileManager : public ::ProfileManagerWithoutInit {
return new TestingProfile(path, this);
}
#if defined(OS_WIN)
virtual ProfileShortcutManagerWin* CreateShortcutManager() OVERRIDE {
// We should avoid creating shortcuts in these tests.
return NULL;
}
#endif
};
} // namespace testing
......@@ -117,8 +110,9 @@ class ProfileManagerTest : public testing::Test {
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
static_cast<TestingBrowserProcess*>(g_browser_process)->SetProfileManager(
new testing::ProfileManager(temp_dir_.path()));
#if defined(OS_CHROMEOS)
CommandLine *cl = CommandLine::ForCurrentProcess();
CommandLine* cl = CommandLine::ForCurrentProcess();
cl->AppendSwitch(switches::kTestType);
#endif
}
......@@ -287,13 +281,16 @@ TEST_F(ProfileManagerTest, CreateProfileAsyncMultipleRequests) {
profile_manager->CreateProfileAsync(dest_path,
base::Bind(&MockObserver::OnProfileCreated,
base::Unretained(&mock_observer1)), string16(), string16());
base::Unretained(&mock_observer1)),
string16(), string16());
profile_manager->CreateProfileAsync(dest_path,
base::Bind(&MockObserver::OnProfileCreated,
base::Unretained(&mock_observer2)), string16(), string16());
base::Unretained(&mock_observer2)),
string16(), string16());
profile_manager->CreateProfileAsync(dest_path,
base::Bind(&MockObserver::OnProfileCreated,
base::Unretained(&mock_observer3)), string16(), string16());
base::Unretained(&mock_observer3)),
string16(), string16());
message_loop_.RunAllPending();
}
......
// Copyright (c) 2012 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.h"
ProfileShortcutManager::~ProfileShortcutManager() {
}
ProfileShortcutManager::ProfileShortcutManager() {
}
// Copyright (c) 2012 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_H_
#define CHROME_BROWSER_PROFILES_PROFILE_SHORTCUT_MANAGER_H_
#include "base/file_path.h"
#include "ui/gfx/image/image.h"
class ProfileShortcutManager {
public:
virtual ~ProfileShortcutManager();
static bool IsFeatureEnabled();
static ProfileShortcutManager* Create();
virtual void CreateChromeDesktopShortcut(
const FilePath& profile_path, const string16& profile_name,
const gfx::Image& avatar_image) = 0;
virtual void DeleteChromeDesktopShortcut(const FilePath& profile_path) = 0;
protected:
ProfileShortcutManager();
private:
DISALLOW_COPY_AND_ASSIGN(ProfileShortcutManager);
};
#endif // CHROME_BROWSER_PROFILES_PROFILE_SHORTCUT_MANAGER_H_
// Copyright (c) 2012 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.h"
// static
bool ProfileShortcutManager::IsFeatureEnabled() {
return false;
}
// static
ProfileShortcutManager* ProfileShortcutManager::Create() {
return NULL;
}
// Copyright (c) 2012 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 "base/file_util.h"
#include "base/message_loop.h"
#include "base/path_service.h"
#include "base/scoped_temp_dir.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_shortcut_manager.h"
#include "chrome/installer/util/browser_distribution.h"
#include "chrome/installer/util/shell_util.h"
#include "chrome/test/base/testing_pref_service.h"
#include "content/public/test/test_browser_thread.h"
#include "grit/theme_resources.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/resource/resource_bundle.h"
using content::BrowserThread;
class ProfileShortcutManagerTest : public testing::Test {
protected:
ProfileShortcutManagerTest()
: file_thread_(BrowserThread::FILE, &message_loop_) {
}
virtual void SetUp() {
// Create a new temporary directory, and store the path
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
}
virtual void TearDown() {
message_loop_.RunAllPending();
}
// The path to temporary directory used to contain the test operations.
ScopedTempDir temp_dir_;
MessageLoopForUI message_loop_;
content::TestBrowserThread file_thread_;
};
TEST_F(ProfileShortcutManagerTest, DesktopShortcutsIconExists) {
// Profile shortcut manager will be NULL for non-windows platforms
ProfileShortcutManager* profile_shortcut_manager =
ProfileShortcutManager::Create();
if (!profile_shortcut_manager)
return;
FilePath dest_path = temp_dir_.path();
string16 profile_name = ASCIIToUTF16("My Profile");
gfx::Image& avatar = ResourceBundle::GetSharedInstance().
GetNativeImageNamed(IDR_PROFILE_AVATAR_0);
profile_shortcut_manager->CreateChromeDesktopShortcut(dest_path,
profile_name, avatar);
ASSERT_TRUE(file_util::PathExists(dest_path.Append(
(FILE_PATH_LITERAL("Google Profile.ico")))));
profile_shortcut_manager->DeleteChromeDesktopShortcut(dest_path);
// TODO(hallielaine): Verify shortcut deletion
}
TEST_F(ProfileShortcutManagerTest, DesktopShortcutsLnk) {
// Profile shortcut manager will be NULL for non-windows platforms
ProfileShortcutManager* profile_shortcut_manager =
ProfileShortcutManager::Create();
if (!profile_shortcut_manager)
return;
FilePath dest_path = temp_dir_.path();
dest_path = dest_path.Append(FILE_PATH_LITERAL("New Profile 1"));
gfx::Image& avatar = ResourceBundle::GetSharedInstance().
GetNativeImageNamed(IDR_PROFILE_AVATAR_0);
profile_shortcut_manager->CreateChromeDesktopShortcut(dest_path,
ASCIIToUTF16("My Profile"), avatar);
FilePath exe_path;
ASSERT_TRUE(PathService::Get(base::FILE_EXE, &exe_path));
FilePath shortcut;
string16 shortcut_name;
BrowserDistribution* dist = BrowserDistribution::GetDistribution();
// Get the desktop path of the current user
ShellUtil::GetDesktopPath(false, &shortcut);
// Get the name of the shortcut with profile attached
ShellUtil::GetChromeShortcutName(dist, false, ASCIIToUTF16("My Profile"),
&shortcut_name);
shortcut = shortcut.Append(shortcut_name);
EXPECT_EQ(ShellUtil::VERIFY_SHORTCUT_SUCCESS,
ShellUtil::VerifyChromeShortcut(exe_path.value(),
shortcut.value(), dist->GetAppDescription(), 0));
profile_shortcut_manager->DeleteChromeDesktopShortcut(dest_path);
}
......@@ -1989,8 +1989,10 @@
'browser/profiles/profile_manager.h',
'browser/profiles/profile_metrics.cc',
'browser/profiles/profile_metrics.h',
'browser/profiles/profile_shortcut_manager.h',
'browser/profiles/profile_shortcut_manager.cc',
'browser/profiles/profile_shortcut_manager_stub.cc',
'browser/profiles/profile_shortcut_manager_win.cc',
'browser/profiles/profile_shortcut_manager_win.h',
'browser/profiles/refcounted_profile_keyed_service.h',
'browser/profiles/refcounted_profile_keyed_service.cc',
'browser/profiles/refcounted_profile_keyed_service_factory.h',
......@@ -5259,6 +5261,7 @@
'browser/importer/nss_decryptor_system_nss.cc',
'browser/importer/nss_decryptor_system_nss.h',
'browser/lifetime/application_lifetime_stub.cc',
'browser/profiles/profile_shortcut_manager_stub.cc',
'browser/ui/certificate_dialogs.cc',
'browser/ui/certificate_dialogs.h',
'browser/ui/crypto_module_password_dialog.cc',
......
......@@ -1505,6 +1505,7 @@
'browser/profiles/profile_info_cache_unittest.h',
'browser/profiles/profile_info_util_unittest.cc',
'browser/profiles/profile_manager_unittest.cc',
'browser/profiles/profile_shortcut_manager_unittest_win.cc',
'browser/protector/composite_settings_change_unittest.cc',
'browser/protector/homepage_change_unittest.cc',
'browser/protector/prefs_backup_invalid_change_unittest.cc',
......
......@@ -1074,6 +1074,9 @@ const char kProductVersion[] = "product-version";
// Selects directory of profile to associate with the first browser launched.
const char kProfileDirectory[] = "profile-directory";
// Enables the Windows profile desktop shortcuts feature.
const char kProfileDesktopShortcuts[] = "enable-profile-desktop-shortcuts";
// Starts the sampling based profiler for the browser process at startup. This
// will only work if chrome has been built with the gyp variable profiling=1.
// The output will go to the value of kProfilingFile.
......
......@@ -288,6 +288,7 @@ extern const char kPrerenderModeSwitchValueEnabled[];
extern const char kPrerenderModeSwitchValuePrefetchOnly[];
extern const char kPrintSettingsReset[];
extern const char kProductVersion[];
extern const char kProfileDesktopShortcuts[];
extern const char kProfileDirectory[];
extern const char kProfilingAtStart[];
extern const char kProfilingFile[];
......
......@@ -24,13 +24,6 @@ class ProfileManager : public ::ProfileManager {
virtual Profile* CreateProfileHelper(const FilePath& file_path) OVERRIDE {
return new TestingProfile(file_path);
}
#if defined(OS_WIN)
virtual ProfileShortcutManagerWin* CreateShortcutManager() OVERRIDE {
// We should avoid creating shortcuts in these tests.
return NULL;
}
#endif
};
} // namespace testing
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment