Index: chrome/browser/shell_integration_win.cc |
diff --git a/chrome/browser/shell_integration_win.cc b/chrome/browser/shell_integration_win.cc |
index 5dd80834c0ab7b81ce673f99f255d24c920ac2c2..d3876c2ee8da4eccabb1b54072e13dead915d5a0 100644 |
--- a/chrome/browser/shell_integration_win.cc |
+++ b/chrome/browser/shell_integration_win.cc |
@@ -26,6 +26,7 @@ |
#include "chrome/common/chrome_constants.h" |
#include "chrome/common/chrome_paths_internal.h" |
#include "chrome/common/chrome_switches.h" |
+#include "chrome/installer/launcher_support/chrome_launcher_support.h" |
#include "chrome/installer/setup/setup_util.h" |
#include "chrome/installer/util/browser_distribution.h" |
#include "chrome/installer/util/create_reg_key_work_item.h" |
@@ -43,6 +44,9 @@ namespace { |
const wchar_t kAppListAppNameSuffix[] = L"AppList"; |
+// How many seconds to delay migrating app host shortcuts. |
+const int64 kMigrateAppHostShortcutsDelaySeconds = 15; |
huangs
2013/04/19 15:21:28
This appears unused.
|
+ |
// Helper function for ShellIntegration::GetAppId to generates profile id |
// from profile path. "profile_id" is composed of sanitized basenames of |
// user data dir and profile dir joined by a ".". |
@@ -90,12 +94,18 @@ string16 GetAppListAppName() { |
// |is_per_user_install|). |
string16 GetExpectedAppId(const CommandLine& command_line, |
bool is_per_user_install) { |
- base::FilePath profile_path; |
- if (command_line.HasSwitch(switches::kUserDataDir)) { |
- profile_path = |
- command_line.GetSwitchValuePath(switches::kUserDataDir).AppendASCII( |
- chrome::kInitialProfile); |
- } |
+ base::FilePath user_data_dir; |
+ chrome::GetDefaultUserDataDirectory(&user_data_dir); |
+ if (command_line.HasSwitch(switches::kUserDataDir)) |
+ user_data_dir = command_line.GetSwitchValuePath(switches::kUserDataDir); |
+ |
+ base::FilePath profile_subdir; |
+ profile_subdir.AppendASCII(chrome::kInitialProfile); |
+ if (command_line.HasSwitch(switches::kProfileDirectory)) |
+ profile_subdir = |
+ command_line.GetSwitchValuePath(switches::kProfileDirectory); |
+ |
+ base::FilePath profile_path = user_data_dir.Append(profile_subdir); |
string16 app_name; |
if (command_line.HasSwitch(switches::kApp)) { |
@@ -114,7 +124,35 @@ string16 GetExpectedAppId(const CommandLine& command_line, |
return ShellIntegration::GetAppModelIdForProfile(app_name, profile_path); |
} |
-void MigrateChromiumShortcutsCallback() { |
+// Locations to check for shortcuts migration. |
+static const struct { |
+ int location_id; |
+ const wchar_t* sub_dir; |
+} kLocations[] = { |
+ { |
+ base::DIR_IMPLICIT_APP_SHORTCUTS, |
+ NULL |
+ }, { |
+ base::DIR_TASKBAR_PINS, |
+ NULL |
+ }, { |
+ base::DIR_USER_DESKTOP, |
+ NULL |
+ }, { |
+ base::DIR_START_MENU, |
+ NULL |
+ }, { |
+ base::DIR_APP_DATA, |
+ L"Microsoft\\Internet Explorer\\Quick Launch\\User Pinned\\StartMenu" |
+ } |
+}; |
+ |
+void MigrateShortcutsCallback() { |
+ ShellIntegration::MigrateAppHostShortcuts(); |
+ ShellIntegration::MigrateChromiumShortcuts(); |
+} |
+ |
+void MigrateAppHostShortcutsCallback() { |
// This should run on the file thread. |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
@@ -123,25 +161,40 @@ void MigrateChromiumShortcutsCallback() { |
if (!PathService::Get(base::FILE_EXE, &chrome_exe)) |
return; |
- // Locations to check for shortcuts migration. |
- static const struct { |
- int location_id; |
- const wchar_t* sub_dir; |
- } kLocations[] = { |
- { |
- base::DIR_TASKBAR_PINS, |
- NULL |
- }, { |
- base::DIR_USER_DESKTOP, |
- NULL |
- }, { |
- base::DIR_START_MENU, |
- NULL |
- }, { |
- base::DIR_APP_DATA, |
- L"Microsoft\\Internet Explorer\\Quick Launch\\User Pinned\\StartMenu" |
+ // Get the app_host.exe path. |
+ bool is_per_user_install = |
+ InstallUtil::IsPerUserInstall(chrome_exe.value().c_str()); |
+ base::FilePath app_host_exe = GetAppHostPathForInstallationLevel( |
huangs
2013/04/19 15:21:28
Does this code account for the case:
1. Chrome is
|
+ is_per_user_install ? chrome_launcher_support::USER_LEVEL_INSTALLATION |
+ : chrome_launcher_support::SYSTEM_LEVEL_INSTALLATION); |
+ |
+ for (int i = 0; i < arraysize(kLocations); ++i) { |
+ base::FilePath path; |
+ if (!PathService::Get(kLocations[i].location_id, &path)) { |
+ NOTREACHED(); |
+ continue; |
} |
- }; |
+ |
+ if (kLocations[i].sub_dir) |
+ path = path.Append(kLocations[i].sub_dir); |
+ |
+ // Recurse when looking for user-pinned shortcuts as they exist in |
+ // subdirectories. |
+ bool recursive = |
+ (kLocations[i].location_id == base::DIR_IMPLICIT_APP_SHORTCUTS); |
+ ShellIntegration::MigrateAppHostShortcutsInPathInternal( |
+ chrome_exe, app_host_exe, path, recursive); |
+ } |
+} |
+ |
+void MigrateChromiumShortcutsCallback() { |
+ // This should run on the file thread. |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
+ |
+ // Get full path of chrome. |
+ base::FilePath chrome_exe; |
+ if (!PathService::Get(base::FILE_EXE, &chrome_exe)) |
+ return; |
for (int i = 0; i < arraysize(kLocations); ++i) { |
base::FilePath path; |
@@ -364,14 +417,9 @@ void ShellIntegration::MigrateChromiumShortcuts() { |
if (base::win::GetVersion() < base::win::VERSION_WIN7) |
return; |
- // This needs to happen eventually (e.g. so that the appid is fixed and the |
- // run-time Chrome icon is merged with the taskbar shortcut), but this is not |
- // urgent and shouldn't delay Chrome startup. |
- static const int64 kMigrateChromiumShortcutsDelaySeconds = 15; |
- BrowserThread::PostDelayedTask( |
+ BrowserThread::PostTask( |
gab
2013/04/19 18:34:50
No need for a second task here given this is alrea
|
BrowserThread::FILE, FROM_HERE, |
- base::Bind(&MigrateChromiumShortcutsCallback), |
- base::TimeDelta::FromSeconds(kMigrateChromiumShortcutsDelaySeconds)); |
+ base::Bind(&MigrateChromiumShortcutsCallback)); |
} |
int ShellIntegration::MigrateShortcutsInPathInternal( |
@@ -489,6 +537,58 @@ int ShellIntegration::MigrateShortcutsInPathInternal( |
return shortcuts_migrated; |
} |
+void ShellIntegration::MigrateShortcuts() { |
+ // These migrations need to happen eventually (e.g. so that the appid is fixed |
+ // and the run-time Chrome icon is merged with the taskbar shortcut), but this |
+ // is not urgent and shouldn't delay Chrome startup. |
+ const int64 kMigrateShortcutsDelaySeconds = 15; |
+ |
+ BrowserThread::PostDelayedTask( |
+ BrowserThread::FILE, FROM_HERE, |
+ base::Bind(&MigrateShortcutsCallback), |
+ base::TimeDelta::FromSeconds(kMigrateShortcutsDelaySeconds)); |
+} |
+ |
+void ShellIntegration::MigrateAppHostShortcuts() { |
+ BrowserThread::PostTask( |
+ BrowserThread::FILE, FROM_HERE, |
+ base::Bind(&MigrateAppHostShortcutsCallback)); |
+} |
+ |
+int ShellIntegration::MigrateAppHostShortcutsInPathInternal( |
+ const base::FilePath& chrome_exe, |
+ const base::FilePath& app_host_exe, |
+ const base::FilePath& path, |
+ bool recursive) { |
+ int shortcuts_migrated = 0; |
+ base::FilePath target_path; |
+ string16 arguments; |
+ file_util::FileEnumerator shortcuts_enum( |
+ path, recursive, file_util::FileEnumerator::FILES); |
+ for (base::FilePath shortcut = shortcuts_enum.Next(); !shortcut.empty(); |
+ shortcut = shortcuts_enum.Next()) { |
+ // TODO(gab): Use ProgramCompare instead of comparing FilePaths below once |
+ // it is fixed to work with FilePaths with spaces. |
gab
2013/04/19 18:34:50
PS: This has been fixed, you can now use InstallUt
|
+ if (shortcut.Extension() != installer::kLnkExt || |
+ !base::win::ResolveShortcut(shortcut, &target_path, &arguments) || |
+ app_host_exe != target_path) { |
+ continue; |
+ } |
+ |
+ // Any properties that need to be updated on the shortcut will be stored in |
+ // |updated_properties|. |
+ base::win::ShortcutProperties updated_properties; |
+ updated_properties.set_target(chrome_exe); |
+ |
+ if (base::win::CreateOrUpdateShortcutLink( |
+ shortcut, updated_properties, |
+ base::win::SHORTCUT_UPDATE_EXISTING)) { |
+ ++shortcuts_migrated; |
+ } |
+ } |
+ return shortcuts_migrated; |
+} |
+ |
base::FilePath ShellIntegration::GetStartMenuShortcut( |
const base::FilePath& chrome_exe) { |
static const int kFolderIds[] = { |