| Index: chrome/installer/util/shell_util.cc
|
| diff --git a/chrome/installer/util/shell_util.cc b/chrome/installer/util/shell_util.cc
|
| index 113b4793ce0c1a6d38d992d3041d805df6c93dba..0974a674282b7337f58c59dbe3aae33a5d5cbedf 100644
|
| --- a/chrome/installer/util/shell_util.cc
|
| +++ b/chrome/installer/util/shell_util.cc
|
| @@ -46,6 +46,8 @@ using base::win::RegKey;
|
|
|
| namespace {
|
|
|
| +typedef ShellUtil::ChromeShortcutProperties ChromeShortcutProperties;
|
| +
|
| // An enum used to tell QuickIsChromeRegistered() which level of registration
|
| // the caller wants to confirm.
|
| enum RegistrationConfirmationLevel {
|
| @@ -937,6 +939,84 @@ bool RegisterChromeAsDefaultProtocolClientForXP(BrowserDistribution* dist,
|
| return true;
|
| }
|
|
|
| +// Returns |properties.shortcut_name| if the property is set, otherwise it
|
| +// returns dist->GetAppShortcutName(). In any case, it makes sure the
|
| +// return value is suffixed with ".lnk".
|
| +string16 ExtractShortcutNameFromProperties(
|
| + BrowserDistribution* dist,
|
| + const ChromeShortcutProperties& properties) {
|
| + DCHECK(dist);
|
| + string16 shortcut_name;
|
| + if (properties.options & ChromeShortcutProperties::PROPERTIES_SHORTCUT_NAME)
|
| + shortcut_name = properties.shortcut_name;
|
| + else
|
| + shortcut_name = dist->GetAppShortCutName();
|
| +
|
| + if (!EndsWith(shortcut_name, installer::kLnkExt, false))
|
| + shortcut_name.append(installer::kLnkExt);
|
| +
|
| + return shortcut_name;
|
| +}
|
| +
|
| +// Returns a ShortcutProperties struct containing the properties to set on the
|
| +// shortcut based on the provided ChromeShortcutProperties. If |operation| is
|
| +// to create, some properties might be given a default if not set in
|
| +// |properties| (see individual setters in ChromeShortcutProperties for
|
| +// details).
|
| +base::win::ShortcutProperties GetShortcutPropertiesFromChromeShortcutProperties(
|
| + BrowserDistribution* dist,
|
| + const ChromeShortcutProperties& properties,
|
| + base::win::ShortcutOperation operation) {
|
| + bool create = (operation == base::win::SHORTCUT_CREATE_ALWAYS ||
|
| + operation == base::win::SHORTCUT_REPLACE_EXISTING);
|
| + // |chrome_exe| is mandatory when creating the shortcut.
|
| + DCHECK(!create ||
|
| + (properties.options &
|
| + ChromeShortcutProperties::PROPERTIES_CHROME_EXE));
|
| +
|
| + base::win::ShortcutProperties shortcut_properties;
|
| +
|
| + if (properties.options & ChromeShortcutProperties::PROPERTIES_CHROME_EXE) {
|
| + shortcut_properties.set_target(properties.chrome_exe);
|
| + DCHECK(!properties.chrome_exe.DirName().empty());
|
| + shortcut_properties.set_working_dir(properties.chrome_exe.DirName());
|
| + }
|
| +
|
| + if (properties.options & ChromeShortcutProperties::PROPERTIES_ARGUMENTS)
|
| + shortcut_properties.set_arguments(properties.arguments);
|
| +
|
| + if (properties.options & ChromeShortcutProperties::PROPERTIES_DESCRIPTION)
|
| + shortcut_properties.set_description(properties.description);
|
| + else if (create)
|
| + shortcut_properties.set_description(dist->GetAppDescription());
|
| +
|
| + if (properties.options & ChromeShortcutProperties::PROPERTIES_ICON) {
|
| + shortcut_properties.set_icon(properties.icon, 0);
|
| + } else if (create) {
|
| + int icon_index = dist->GetIconIndex();
|
| + installer::MasterPreferences prefs(
|
| + properties.chrome_exe.DirName().AppendASCII(
|
| + installer::kDefaultMasterPrefs));
|
| + prefs.GetInt(installer::master_preferences::kChromeShortcutIconIndex,
|
| + &icon_index);
|
| + shortcut_properties.set_icon(properties.chrome_exe, icon_index);
|
| + }
|
| +
|
| + if (properties.options & ChromeShortcutProperties::PROPERTIES_APP_ID) {
|
| + shortcut_properties.set_app_id(properties.app_id);
|
| + } else if (create) {
|
| + bool is_per_user_install =
|
| + InstallUtil::IsPerUserInstall(properties.chrome_exe.value().c_str());
|
| + shortcut_properties.set_app_id(
|
| + ShellUtil::GetBrowserModelId(dist, is_per_user_install));
|
| + }
|
| +
|
| + if (properties.options & ChromeShortcutProperties::PROPERTIES_DUAL_MODE)
|
| + shortcut_properties.set_dual_mode(properties.dual_mode);
|
| +
|
| + return shortcut_properties;
|
| +}
|
| +
|
| } // namespace
|
|
|
| const wchar_t* ShellUtil::kRegDefaultIcon = L"\\DefaultIcon";
|
| @@ -992,100 +1072,111 @@ 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 ShellUtil::GetShortcutPath(ChromeShortcutLocation location,
|
| + BrowserDistribution* dist,
|
| + ShellChange level,
|
| + FilePath* path) {
|
| + int dir_key = -1;
|
| + bool add_folder_for_dist = false;
|
| + switch (location) {
|
| + case SHORTCUT_DESKTOP:
|
| + dir_key = (level == CURRENT_USER) ? base::DIR_USER_DESKTOP :
|
| + base::DIR_COMMON_DESKTOP;
|
| + break;
|
| + case SHORTCUT_QUICK_LAUNCH:
|
| + dir_key = (level == CURRENT_USER) ? base::DIR_USER_QUICK_LAUNCH :
|
| + base::DIR_DEFAULT_USER_QUICK_LAUNCH;
|
| + break;
|
| + case SHORTCUT_START_MENU:
|
| + dir_key = (level == CURRENT_USER) ? base::DIR_START_MENU :
|
| + base::DIR_COMMON_START_MENU;
|
| + add_folder_for_dist = true;
|
| + break;
|
| + default:
|
| + NOTREACHED();
|
| + 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);
|
| - }
|
| - }
|
| - } 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);
|
| - }
|
| - } else {
|
| - NOTREACHED();
|
| + if (dir_key == -1 || !PathService::Get(dir_key, path) || path->empty()) {
|
| + NOTREACHED() << dir_key;
|
| + return false;
|
| }
|
| - return ret;
|
| +
|
| + if (add_folder_for_dist)
|
| + *path = path->Append(dist->GetAppShortCutName());
|
| +
|
| + return true;
|
| }
|
|
|
| -bool ShellUtil::CreateChromeQuickLaunchShortcut(BrowserDistribution* dist,
|
| - const string16& chrome_exe,
|
| - int shell_change,
|
| - uint32 options) {
|
| - string16 shortcut_name;
|
| - if (!ShellUtil::GetChromeShortcutName(dist, false, L"", &shortcut_name))
|
| +bool ShellUtil::CreateOrUpdateChromeShortcut(
|
| + ShellUtil::ChromeShortcutLocation location,
|
| + BrowserDistribution* dist,
|
| + const ChromeShortcutProperties& properties,
|
| + ChromeShortcutOperation operation) {
|
| + DCHECK(dist);
|
| + // |pin_to_taskbar| is only acknowledged when first creating the shortcut.
|
| + DCHECK(!properties.pin_to_taskbar ||
|
| + operation == base::win::SHORTCUT_CREATE_ALWAYS);
|
| +
|
| + FilePath user_shortcut_path;
|
| + FilePath system_shortcut_path;
|
| + if (!GetShortcutPath(location, dist, CURRENT_USER, &user_shortcut_path) ||
|
| + !GetShortcutPath(location, dist, SYSTEM_LEVEL, &system_shortcut_path) ||
|
| + user_shortcut_path.empty() ||
|
| + system_shortcut_path.empty()) {
|
| + NOTREACHED();
|
| 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;
|
| - }
|
| + string16 shortcut_name(ExtractShortcutNameFromProperties(dist, properties));
|
| + user_shortcut_path = user_shortcut_path.Append(shortcut_name);
|
| + system_shortcut_path = system_shortcut_path.Append(shortcut_name);
|
| +
|
| + FilePath *chosen_path;
|
| + if (properties.level == SYSTEM_LEVEL) {
|
| + // Install the system-level shortcut if requested.
|
| + chosen_path = &system_shortcut_path;
|
| + } else if (operation != SHORTCUT_CREATE_IF_NO_SYSTEM_LEVEL ||
|
| + !file_util::PathExists(system_shortcut_path)){
|
| + // Otherwise install the user-level shortcut, unless the system-level
|
| + // variant of this shortcut is present on the machine and |operation| states
|
| + // not to create a user-level shortcut in that case.
|
| + chosen_path = &user_shortcut_path;
|
| + } else {
|
| + // Do not install anything if we are told to install a user-level shortcut,
|
| + // but the system-level variant of that shortcut is present.
|
| + chosen_path = &FilePath();
|
| }
|
|
|
| - // 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;
|
| + // No shortcut needs to be created/updated.
|
| + if (chosen_path->empty())
|
| + return true;
|
| +
|
| + // Make sure the parent directories exist when creating the shortcut.
|
| + if (operation == SHORTCUT_CREATE_ALWAYS &&
|
| + !file_util::CreateDirectory(chosen_path->DirName())) {
|
| + NOTREACHED();
|
| + return false;
|
| + }
|
| +
|
| + base::win::ShortcutOperation shortcut_operation =
|
| + (operation == SHORTCUT_UPDATE_EXISTING ?
|
| + base::win::SHORTCUT_UPDATE_EXISTING :
|
| + (operation == SHORTCUT_REPLACE_EXISTING ?
|
| + base::win::SHORTCUT_REPLACE_EXISTING :
|
| + base::win::SHORTCUT_CREATE_ALWAYS));
|
| + base::win::ShortcutProperties shortcut_properties(
|
| + GetShortcutPropertiesFromChromeShortcutProperties(dist, properties,
|
| + shortcut_operation));
|
| + bool ret = base::win::CreateOrUpdateShortcutLink(
|
| + *chosen_path, shortcut_properties, shortcut_operation);
|
| +
|
| + if (ret && operation == SHORTCUT_CREATE_ALWAYS && properties.pin_to_taskbar &&
|
| + base::win::GetVersion() >= base::win::VERSION_WIN7) {
|
| + ret = base::win::TaskbarPinShortcutLink(chosen_path->value().c_str());
|
| + if (!ret) {
|
| + LOG(ERROR) << "The shorcut at " << chosen_path->value()
|
| + << " was created, but the taskbar pin failed.";
|
| }
|
| }
|
|
|
| @@ -1108,33 +1199,6 @@ string16 ShellUtil::GetChromeDelegateCommand(const string16& chrome_exe) {
|
| return L"\"" + chrome_exe + L"\" -- %*";
|
| }
|
|
|
| -bool ShellUtil::GetChromeShortcutName(BrowserDistribution* dist,
|
| - bool alternate,
|
| - const string16& appended_name,
|
| - string16* shortcut) {
|
| - shortcut->assign(alternate ? dist->GetAlternateApplicationName() :
|
| - dist->GetAppShortCutName());
|
| - if (!appended_name.empty()) {
|
| - shortcut->append(L" (");
|
| - shortcut->append(appended_name);
|
| - shortcut->append(L")");
|
| - }
|
| - shortcut->append(L".lnk");
|
| - return true;
|
| -}
|
| -
|
| -bool ShellUtil::GetDesktopPath(bool system_level, FilePath* path) {
|
| - int dir_key = system_level ? base::DIR_COMMON_DESKTOP :
|
| - base::DIR_USER_DESKTOP;
|
| - return PathService::Get(dir_key, path);
|
| -}
|
| -
|
| -bool ShellUtil::GetQuickLaunchPath(bool system_level, FilePath* path) {
|
| - int dir_key = system_level ? base::DIR_DEFAULT_USER_QUICK_LAUNCH :
|
| - base::DIR_USER_QUICK_LAUNCH;
|
| - return PathService::Get(dir_key, path);
|
| -}
|
| -
|
| void ShellUtil::GetRegisteredBrowsers(
|
| BrowserDistribution* dist,
|
| std::map<string16, string16>* browsers) {
|
| @@ -1551,88 +1615,34 @@ 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(
|
| + ChromeShortcutLocation location,
|
| + BrowserDistribution* dist,
|
| + ShellChange level,
|
| + const string16* shortcut_name) {
|
| + bool delete_folder = (location == SHORTCUT_START_MENU);
|
|
|
| - string16 shortcut_name;
|
| - bool alternate = (options & ShellUtil::SHORTCUT_ALTERNATE) != 0;
|
| - if (!ShellUtil::GetChromeShortcutName(dist, alternate, L"",
|
| - &shortcut_name))
|
| + FilePath shortcut_folder;
|
| + if (!GetShortcutPath(location, dist, level, &shortcut_folder) ||
|
| + shortcut_folder.empty()) {
|
| + NOTREACHED();
|
| 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;
|
| - }
|
| }
|
|
|
| - 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;
|
| - } else {
|
| - ret = false;
|
| - }
|
| - }
|
| - return ret;
|
| -}
|
| + string16 shortcut_base_name(
|
| + (shortcut_name ? *shortcut_name : dist->GetAppShortCutName()) +
|
| + installer::kLnkExt);
|
| + FilePath shortcut_path(shortcut_folder.Append(shortcut_base_name));
|
|
|
| -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) {
|
| - FilePath delete_shortcut = shortcut_path.Append(*it);
|
| - ret = ret && file_util::Delete(delete_shortcut, false);
|
| - }
|
| - } else {
|
| - ret = false;
|
| - }
|
| - 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;
|
| - }
|
| - }
|
| + // Unpin the shortcut if it was ever pinned by the user or the installer.
|
| + VLOG(1) << "Trying to unpin " << shortcut_path.value();
|
| + if (!base::win::TaskbarUnpinShortcutLink(shortcut_path.value().c_str()))
|
| + VLOG(1) << shortcut_path.value() << " wasn't pinned (or the unpin failed).";
|
|
|
| - return ret;
|
| + if (delete_folder)
|
| + return file_util::Delete(shortcut_folder, true);
|
| + else
|
| + return file_util::Delete(shortcut_path, false);
|
| }
|
|
|
| void ShellUtil::RemoveChromeStartScreenShortcuts(BrowserDistribution* dist,
|
| @@ -1663,46 +1673,6 @@ void ShellUtil::RemoveChromeStartScreenShortcuts(BrowserDistribution* dist,
|
| }
|
| }
|
|
|
| -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,
|
| - InstallUtil::IsPerUserInstall(chrome_exe.c_str())));
|
| - const bool is_dual_mode = ((options & ShellUtil::SHORTCUT_DUAL_MODE) != 0);
|
| - const base::win::ShortcutOperation operation =
|
| - (options & ShellUtil::SHORTCUT_CREATE_ALWAYS) != 0 ?
|
| - base::win::SHORTCUT_CREATE_ALWAYS :
|
| - base::win::SHORTCUT_UPDATE_EXISTING;
|
| -
|
| - // TODO(gab): The shell_util interface will also be refactored in an upcoming
|
| - // CL to use a ShortcutProperties like interface for its shortcut methods.
|
| - base::win::ShortcutProperties shortcut_properties;
|
| - shortcut_properties.set_target(FilePath(chrome_exe));
|
| - shortcut_properties.set_working_dir(chrome_path);
|
| - shortcut_properties.set_arguments(arguments);
|
| - shortcut_properties.set_description(description);
|
| - shortcut_properties.set_icon(FilePath(icon_path), icon_index);
|
| - shortcut_properties.set_app_id(app_id);
|
| - shortcut_properties.set_dual_mode(is_dual_mode);
|
| - return base::win::CreateOrUpdateShortcutLink(
|
| - FilePath(shortcut), shortcut_properties, operation);
|
| -}
|
| -
|
| bool ShellUtil::GetUserSpecificRegistrySuffix(string16* suffix) {
|
| // Use a thread-safe cache for the user's suffix.
|
| static base::LazyInstance<UserSpecificRegistrySuffix>::Leaky suffix_instance =
|
|
|