Chromium Code Reviews| Index: chrome/installer/util/shell_util.cc |
| diff --git a/chrome/installer/util/shell_util.cc b/chrome/installer/util/shell_util.cc |
| index 37ed8c214ea4ccb25235cdf4606505f92aea8a4e..9407d4638f7a6685f0a4f847e8428530a888cf27 100644 |
| --- a/chrome/installer/util/shell_util.cc |
| +++ b/chrome/installer/util/shell_util.cc |
| @@ -971,103 +971,153 @@ bool ShellUtil::QuickIsChromeRegisteredInHKLM(BrowserDistribution* dist, |
| CONFIRM_SHELL_REGISTRATION_IN_HKLM); |
| } |
| -bool ShellUtil::CreateChromeDesktopShortcut(BrowserDistribution* dist, |
| - const string16& chrome_exe, |
| - const string16& description, |
| - const string16& appended_name, |
| - const string16& arguments, |
| - const string16& icon_path, |
| - int icon_index, |
| - ShellChange shell_change, |
| - uint32 options) { |
| - string16 shortcut_name; |
| - bool alternate = (options & ShellUtil::SHORTCUT_ALTERNATE) != 0; |
| - if (!ShellUtil::GetChromeShortcutName(dist, alternate, appended_name, |
| - &shortcut_name)) |
| - return false; |
| - |
| - bool ret = false; |
| - if (shell_change == ShellUtil::CURRENT_USER) { |
| - FilePath shortcut_path; |
| - // We do not want to create a desktop shortcut to Chrome in the current |
| - // user's desktop folder if there is already one in the "All Users" |
| - // desktop folder. |
| - bool got_system_desktop = ShellUtil::GetDesktopPath(true, &shortcut_path); |
| - FilePath shortcut = shortcut_path.Append(shortcut_name); |
| - if (!got_system_desktop || !file_util::PathExists(shortcut)) { |
| - // Either we couldn't query the "All Users" Desktop folder or there's |
| - // nothing in it, so let's continue. |
| - if (ShellUtil::GetDesktopPath(false, &shortcut_path)) { |
| - shortcut = shortcut_path.Append(shortcut_name); |
| - ret = ShellUtil::UpdateChromeShortcut(dist, |
| - chrome_exe, |
| - shortcut.value(), |
| - arguments, |
| - description, |
| - icon_path, |
| - icon_index, |
| - options); |
| +bool ShellUtil::GetShortcutPath(ShellUtil::ShortcutLocation location, |
| + bool system_level, |
| + FilePath* path) { |
| + switch (location) { |
| + case ShellUtil::SHORTCUT_DESKTOP: { |
| + wchar_t desktop[MAX_PATH]; |
| + int dir = system_level ? CSIDL_COMMON_DESKTOPDIRECTORY : |
| + CSIDL_DESKTOPDIRECTORY; |
| + if (FAILED(SHGetFolderPath(NULL, dir, NULL, SHGFP_TYPE_CURRENT, desktop))) |
| + return false; |
| + *path = FilePath(desktop); |
| + break; |
| + } |
| + case ShellUtil::SHORTCUT_QUICK_LAUNCH: { |
| + if (system_level) { |
| + wchar_t qlaunch[MAX_PATH]; |
| + // We are accessing GetDefaultUserProfileDirectory this way so that we |
| + // do not have to declare dependency to Userenv.lib for chrome.exe |
| + typedef BOOL (WINAPI *PROFILE_FUNC)(LPWSTR, LPDWORD); |
| + HMODULE module = LoadLibrary(L"Userenv.dll"); |
| + PROFILE_FUNC p = reinterpret_cast<PROFILE_FUNC>(GetProcAddress(module, |
| + "GetDefaultUserProfileDirectoryW")); |
| + DWORD size = _countof(qlaunch); |
| + if ((p == NULL) || ((p)(qlaunch, &size) != TRUE)) |
| + return false; |
| + *path = FilePath(qlaunch); |
| + if (base::win::GetVersion() >= base::win::VERSION_VISTA) { |
| + *path = path->AppendASCII("AppData"); |
| + *path = path->AppendASCII("Roaming"); |
| + } else { |
| + *path = path->AppendASCII("Application Data"); |
|
robertshield
2012/08/22 21:39:07
This doesn't look like the right way of getting th
|
| + } |
| + } else { |
| + if (!PathService::Get(base::DIR_APP_DATA, path)) { |
| + return false; |
| + } |
| } |
| + *path = path->AppendASCII("Microsoft"); |
| + *path = path->AppendASCII("Internet Explorer"); |
| + *path = path->AppendASCII("Quick Launch"); |
|
robertshield
2012/08/22 21:39:07
Same comment about not hard-coding paths. Doing th
|
| + break; |
| } |
| - } else if (shell_change == ShellUtil::SYSTEM_LEVEL) { |
| - FilePath shortcut_path; |
| - if (ShellUtil::GetDesktopPath(true, &shortcut_path)) { |
| - FilePath shortcut = shortcut_path.Append(shortcut_name); |
| - ret = ShellUtil::UpdateChromeShortcut(dist, |
| - chrome_exe, |
| - shortcut.value(), |
| - arguments, |
| - description, |
| - icon_path, |
| - icon_index, |
| - options); |
| + case ShellUtil::SHORTCUT_START_MENU: |
| + case ShellUtil::SHORTCUT_START_MENU_UNINSTALL: { |
| + int dir = system_level ? base::DIR_COMMON_START_MENU : |
| + base::DIR_START_MENU; |
| + if (!PathService::Get(dir, path)) |
| + return false; |
| + BrowserDistribution* dist = BrowserDistribution::GetDistribution(); |
| + *path = path->Append(dist->GetAppShortCutName()); |
| + break; |
| + } |
| + default: { |
| + NOTREACHED(); |
| + return false; |
| } |
| + } |
| + return true; |
| +} |
| + |
| +FilePath ShellUtil::DetermineShortcutPathToCreateFromOptions( |
| + const FilePath& user_level_shortcut, |
| + const FilePath& system_level_shortcut, |
| + uint32 options) { |
| + if (options & ShellUtil::SHORTCUT_SYSTEM_LEVEL) { |
| + // Install the system-level shortcut if requested. |
| + DCHECK(!system_level_shortcut.empty()); |
| + return system_level_shortcut; |
| + } else if (system_level_shortcut.empty() || |
| + !file_util::PathExists(system_level_shortcut)){ |
| + // Otherwise install the user-level shortcut, but do so iff no system-level |
| + // shortcut is present. |
| + DCHECK(!user_level_shortcut.empty()); |
| + return user_level_shortcut; |
| } else { |
| - NOTREACHED(); |
| + // Do not install anything if the system-level shortcut is present, but we |
| + // are told to install the user-level shortcut. |
| + return FilePath(); |
| } |
| - return ret; |
| } |
| -bool ShellUtil::CreateChromeQuickLaunchShortcut(BrowserDistribution* dist, |
| - const string16& chrome_exe, |
| - int shell_change, |
| - uint32 options) { |
| +bool ShellUtil::CreateOrUpdateChromeShortcut( |
| + ShellUtil::ShortcutLocation location, |
| + BrowserDistribution* dist, |
| + const string16& exe_path, |
| + const string16& description, |
| + const string16& appended_name, |
| + const string16& arguments, |
| + const string16& icon_path, |
| + int icon_index, |
| + uint32 options) { |
| string16 shortcut_name; |
| - if (!ShellUtil::GetChromeShortcutName(dist, false, L"", &shortcut_name)) |
| + const bool alternate = ((options & ShellUtil::SHORTCUT_ALTERNATE) != 0 && |
| + location == SHORTCUT_DESKTOP); |
| + if (!ShellUtil::GetChromeShortcutName(location, dist, alternate, |
| + appended_name, &shortcut_name)) { |
| return false; |
| + } |
| - bool ret = true; |
| - // First create shortcut for the current user. |
| - if (shell_change & ShellUtil::CURRENT_USER) { |
| - FilePath user_ql_path; |
| - if (ShellUtil::GetQuickLaunchPath(false, &user_ql_path)) { |
| - user_ql_path = user_ql_path.Append(shortcut_name); |
| - ret = ShellUtil::UpdateChromeShortcut(dist, chrome_exe, |
| - user_ql_path.value(), |
| - L"", L"", chrome_exe, |
| - dist->GetIconIndex(), |
| - options); |
| - } else { |
| - ret = false; |
| - } |
| + FilePath user_shortcut_path; |
| + FilePath system_shortcut_path; |
| + if (!GetShortcutPath(location, false, &user_shortcut_path)) |
| + user_shortcut_path.clear(); |
| + if (!GetShortcutPath(location, true, &system_shortcut_path)) |
| + system_shortcut_path.clear(); |
| + |
| + FilePath path_to_create(DetermineShortcutPathToCreateFromOptions( |
| + user_shortcut_path, system_shortcut_path, options)); |
| + |
| + // No shortcut needs to be created/updated. |
| + if (path_to_create.empty()) |
| + return true; |
| + |
| + // Make sure the parent directories exist. |
| + if ((options & SHORTCUT_CREATE_ALWAYS) && |
| + !file_util::CreateDirectory(path_to_create.DirName())) { |
| + NOTREACHED(); |
| + return false; |
| } |
| - // Add a shortcut to Default User's profile so that all new user profiles |
| - // get it. |
| - if (shell_change & ShellUtil::SYSTEM_LEVEL) { |
| - FilePath default_ql_path; |
| - if (ShellUtil::GetQuickLaunchPath(true, &default_ql_path)) { |
| - default_ql_path = default_ql_path.Append(shortcut_name); |
| - ret = ShellUtil::UpdateChromeShortcut(dist, chrome_exe, |
| - default_ql_path.value(), |
| - L"", L"", chrome_exe, |
| - dist->GetIconIndex(), |
| - options) && ret; |
| - } else { |
| - ret = false; |
| + string16 app_id; |
| + FilePath exe_dir(FilePath(exe_path).DirName()); |
| + // Set the |app_id| and |icon_index| correctly if this is a shortcut to |
| + // chrome.exe. |
| + if (exe_path.find(installer::kChromeExe) != string16::npos) { |
| + app_id.assign(GetBrowserModelId(dist, exe_path)); |
| + |
| + installer::MasterPreferences prefs( |
| + exe_dir.AppendASCII(installer::kDefaultMasterPrefs)); |
| + if (InstallUtil::ProgramCompare(FilePath(exe_path)).Evaluate(icon_path)) { |
| + prefs.GetInt(installer::master_preferences::kChromeShortcutIconIndex, |
| + &icon_index); |
| } |
| } |
| + bool ret = file_util::CreateOrUpdateShortcutLink( |
| + exe_path.c_str(), path_to_create.value().c_str(), |
| + exe_dir.value().c_str(), arguments.c_str(), description.c_str(), |
| + icon_path.c_str(), icon_index, app_id.c_str(), |
| + ConvertShellUtilShortcutOptionsToFileUtil(options)); |
| + |
| + if (ret && (options & SHORTCUT_PIN_TO_TASKBAR) && |
| + (options & SHORTCUT_CREATE_ALWAYS) && |
| + base::win::GetVersion() >= base::win::VERSION_WIN7) { |
| + ret = file_util::TaskbarPinShortcutLink(path_to_create.value().c_str()); |
| + } |
| + |
| return ret; |
| } |
| @@ -1087,12 +1137,32 @@ string16 ShellUtil::GetChromeDelegateCommand(const string16& chrome_exe) { |
| return L"\"" + chrome_exe + L"\" -- %*"; |
| } |
| -bool ShellUtil::GetChromeShortcutName(BrowserDistribution* dist, |
| +bool ShellUtil::GetChromeShortcutName(ShellUtil::ShortcutLocation location, |
| + BrowserDistribution* dist, |
| bool alternate, |
| const string16& appended_name, |
| string16* shortcut) { |
| - shortcut->assign(alternate ? dist->GetAlternateApplicationName() : |
| - dist->GetAppShortCutName()); |
| + // Only the Desktop shortcut can use the alternate name. |
| + DCHECK(!alternate || location == SHORTCUT_DESKTOP); |
| + |
| + switch (location) { |
| + case SHORTCUT_DESKTOP: |
| + shortcut->assign(alternate ? dist->GetAlternateApplicationName() : |
| + dist->GetAppShortCutName()); |
| + break; |
| + case SHORTCUT_QUICK_LAUNCH: |
| + case SHORTCUT_START_MENU: |
| + shortcut->assign(dist->GetAppShortCutName()); |
| + break; |
| + case SHORTCUT_START_MENU_UNINSTALL: |
| + shortcut->assign(dist->GetUninstallLinkName()); |
| + break; |
| + default: |
| + NOTREACHED(); |
| + shortcut->clear(); |
| + return false; |
| + } |
| + |
| if (!appended_name.empty()) { |
| shortcut->append(L" ("); |
| shortcut->append(appended_name); |
| @@ -1102,46 +1172,6 @@ bool ShellUtil::GetChromeShortcutName(BrowserDistribution* dist, |
| return true; |
| } |
| -bool ShellUtil::GetDesktopPath(bool system_level, FilePath* path) { |
| - wchar_t desktop[MAX_PATH]; |
| - int dir = system_level ? CSIDL_COMMON_DESKTOPDIRECTORY : |
| - CSIDL_DESKTOPDIRECTORY; |
| - if (FAILED(SHGetFolderPath(NULL, dir, NULL, SHGFP_TYPE_CURRENT, desktop))) |
| - return false; |
| - *path = FilePath(desktop); |
| - return true; |
| -} |
| - |
| -bool ShellUtil::GetQuickLaunchPath(bool system_level, FilePath* path) { |
| - if (system_level) { |
| - wchar_t qlaunch[MAX_PATH]; |
| - // We are accessing GetDefaultUserProfileDirectory this way so that we do |
| - // not have to declare dependency to Userenv.lib for chrome.exe |
| - typedef BOOL (WINAPI *PROFILE_FUNC)(LPWSTR, LPDWORD); |
| - HMODULE module = LoadLibrary(L"Userenv.dll"); |
| - PROFILE_FUNC p = reinterpret_cast<PROFILE_FUNC>(GetProcAddress(module, |
| - "GetDefaultUserProfileDirectoryW")); |
| - DWORD size = _countof(qlaunch); |
| - if ((p == NULL) || ((p)(qlaunch, &size) != TRUE)) |
| - return false; |
| - *path = FilePath(qlaunch); |
| - if (base::win::GetVersion() >= base::win::VERSION_VISTA) { |
| - *path = path->AppendASCII("AppData"); |
| - *path = path->AppendASCII("Roaming"); |
| - } else { |
| - *path = path->AppendASCII("Application Data"); |
| - } |
| - } else { |
| - if (!PathService::Get(base::DIR_APP_DATA, path)) { |
| - return false; |
| - } |
| - } |
| - *path = path->AppendASCII("Microsoft"); |
| - *path = path->AppendASCII("Internet Explorer"); |
| - *path = path->AppendASCII("Quick Launch"); |
| - return true; |
| -} |
| - |
| void ShellUtil::GetRegisteredBrowsers( |
| BrowserDistribution* dist, |
| std::map<string16, string16>* browsers) { |
| @@ -1542,33 +1572,33 @@ bool ShellUtil::RegisterChromeForProtocol(BrowserDistribution* dist, |
| } |
| } |
| -bool ShellUtil::RemoveChromeDesktopShortcut(BrowserDistribution* dist, |
| - int shell_change, uint32 options) { |
| - // Only SHORTCUT_ALTERNATE is a valid option for this function. |
| - DCHECK(!options || options == ShellUtil::SHORTCUT_ALTERNATE); |
| - |
| +bool ShellUtil::RemoveChromeShortcut(ShellUtil::ShortcutLocation location, |
| + BrowserDistribution* dist, |
| + uint32 options) { |
| string16 shortcut_name; |
| - bool alternate = (options & ShellUtil::SHORTCUT_ALTERNATE) != 0; |
| - if (!ShellUtil::GetChromeShortcutName(dist, alternate, L"", |
| + bool alternate = (options & ShellUtil::SHORTCUT_ALTERNATE) != 0 && |
| + location == SHORTCUT_DESKTOP; |
| + if (!ShellUtil::GetChromeShortcutName(location, dist, alternate, string16(), |
| &shortcut_name)) |
| return false; |
| bool ret = true; |
| - if (shell_change & ShellUtil::CURRENT_USER) { |
| - FilePath shortcut_path; |
| - if (ShellUtil::GetDesktopPath(false, &shortcut_path)) { |
| - FilePath shortcut = shortcut_path.Append(shortcut_name); |
| - ret = file_util::Delete(shortcut, false); |
| - } else { |
| - ret = false; |
| - } |
| + |
| + // Always delete the user-level shortcut. |
| + FilePath user_shortcut_path; |
| + if (GetShortcutPath(location, false, &user_shortcut_path)) { |
| + user_shortcut_path = user_shortcut_path.Append(shortcut_name); |
| + ret = file_util::Delete(user_shortcut_path, false); |
| + } else { |
| + ret = false; |
| } |
| - if (shell_change & ShellUtil::SYSTEM_LEVEL) { |
| - FilePath shortcut_path; |
| - if (ShellUtil::GetDesktopPath(true, &shortcut_path)) { |
| - FilePath shortcut = shortcut_path.Append(shortcut_name); |
| - ret = file_util::Delete(shortcut, false) && ret; |
| + // Delete the system-level shortcut if requested. |
| + if (options & ShellUtil::SHORTCUT_SYSTEM_LEVEL) { |
| + FilePath system_shortcut_path; |
| + if (GetShortcutPath(location, true, &system_shortcut_path)) { |
| + system_shortcut_path = system_shortcut_path.Append(shortcut_name); |
| + ret = ret && file_util::Delete(system_shortcut_path, false); |
|
robertshield
2012/08/22 21:39:07
if ret is already false, the Delete operation is n
|
| } else { |
| ret = false; |
| } |
| @@ -1580,11 +1610,9 @@ bool ShellUtil::RemoveChromeDesktopShortcutsWithAppendedNames( |
| const std::vector<string16>& appended_names) { |
| FilePath shortcut_path; |
| bool ret = true; |
| - if (ShellUtil::GetDesktopPath(false, &shortcut_path)) { |
| - for (std::vector<string16>::const_iterator it = |
| - appended_names.begin(); |
| - it != appended_names.end(); |
| - ++it) { |
| + if (GetShortcutPath(ShellUtil::SHORTCUT_DESKTOP, false, &shortcut_path)) { |
| + for (std::vector<string16>::const_iterator it = appended_names.begin(); |
| + it != appended_names.end(); ++it) { |
| FilePath delete_shortcut = shortcut_path.Append(*it); |
| ret = ret && file_util::Delete(delete_shortcut, false); |
| } |
| @@ -1594,69 +1622,6 @@ bool ShellUtil::RemoveChromeDesktopShortcutsWithAppendedNames( |
| return ret; |
| } |
| -bool ShellUtil::RemoveChromeQuickLaunchShortcut(BrowserDistribution* dist, |
| - int shell_change) { |
| - string16 shortcut_name; |
| - if (!ShellUtil::GetChromeShortcutName(dist, false, L"", &shortcut_name)) |
| - return false; |
| - |
| - bool ret = true; |
| - // First remove shortcut for the current user. |
| - if (shell_change & ShellUtil::CURRENT_USER) { |
| - FilePath user_ql_path; |
| - if (ShellUtil::GetQuickLaunchPath(false, &user_ql_path)) { |
| - user_ql_path = user_ql_path.Append(shortcut_name); |
| - ret = file_util::Delete(user_ql_path, false); |
| - } else { |
| - ret = false; |
| - } |
| - } |
| - |
| - // Delete shortcut in Default User's profile |
| - if (shell_change & ShellUtil::SYSTEM_LEVEL) { |
| - FilePath default_ql_path; |
| - if (ShellUtil::GetQuickLaunchPath(true, &default_ql_path)) { |
| - default_ql_path = default_ql_path.Append(shortcut_name); |
| - ret = file_util::Delete(default_ql_path, false) && ret; |
| - } else { |
| - ret = false; |
| - } |
| - } |
| - |
| - return ret; |
| -} |
| - |
| -bool ShellUtil::UpdateChromeShortcut(BrowserDistribution* dist, |
| - const string16& chrome_exe, |
| - const string16& shortcut, |
| - const string16& arguments, |
| - const string16& description, |
| - const string16& icon_path, |
| - int icon_index, |
| - uint32 options) { |
| - const FilePath chrome_path(FilePath(chrome_exe).DirName()); |
| - |
| - installer::MasterPreferences prefs( |
| - chrome_path.AppendASCII(installer::kDefaultMasterPrefs)); |
| - if (FilePath::CompareEqualIgnoreCase(icon_path, chrome_exe)) { |
| - prefs.GetInt(installer::master_preferences::kChromeShortcutIconIndex, |
| - &icon_index); |
| - } |
| - |
| - const string16 app_id(GetBrowserModelId(dist, chrome_exe)); |
| - |
| - return file_util::CreateOrUpdateShortcutLink( |
| - chrome_exe.c_str(), |
| - shortcut.c_str(), |
| - chrome_path.value().c_str(), |
| - arguments.c_str(), |
| - description.c_str(), |
| - icon_path.c_str(), |
| - icon_index, |
| - app_id.c_str(), |
| - ConvertShellUtilShortcutOptionsToFileUtil(options)); |
| -} |
| - |
| ShellUtil::VerifyShortcutStatus ShellUtil::VerifyChromeShortcut( |
| const string16& exe_path, const string16& shortcut, |
| const string16& description, int icon_index) { |