Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(9292)

Unified Diff: chrome/installer/setup/install.cc

Issue 10836247: Refactor ShellUtil shortcut code -- single multi-purpose methods as opposed to many slighlty diffe… (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: adress comments about shell_util interface Created 8 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/installer/setup/install.cc
diff --git a/chrome/installer/setup/install.cc b/chrome/installer/setup/install.cc
index 63687fa3f34dba9f099789932de21f906826ce55..8d1e0473ee75c0990fdae95ad4eefeda11c9e6ea 100644
--- a/chrome/installer/setup/install.cc
+++ b/chrome/installer/setup/install.cc
@@ -8,6 +8,8 @@
#include <time.h>
#include <winuser.h>
+#include <string>
+
#include "base/command_line.h"
#include "base/file_path.h"
#include "base/file_util.h"
@@ -29,9 +31,11 @@
#include "chrome/installer/util/google_update_constants.h"
#include "chrome/installer/util/helper.h"
#include "chrome/installer/util/install_util.h"
+#include "chrome/installer/util/master_preferences.h"
#include "chrome/installer/util/master_preferences_constants.h"
#include "chrome/installer/util/set_reg_value_work_item.h"
#include "chrome/installer/util/shell_util.h"
+#include "chrome/installer/util/util_constants.h"
#include "chrome/installer/util/work_item_list.h"
// Build-time generated include file.
@@ -43,6 +47,78 @@ using installer::Product;
namespace {
+void LogShortcutOperation(ShellUtil::ChromeShortcutLocation location,
+ BrowserDistribution* dist,
+ const ShellUtil::ChromeShortcutProperties& properties,
+ ShellUtil::ChromeShortcutOperation operation,
+ bool failed) {
+ // SHORTCUT_UPDATE_EXISTING should not be used at install and thus this method
+ // does not handle logging a message for it.
+ DCHECK(operation != ShellUtil::SHORTCUT_UPDATE_EXISTING);
+ std::string message;
+ if (failed)
+ message.append("Failed: ");
+ message.append(operation == ShellUtil::SHORTCUT_CREATE_ALWAYS ?
+ "Creating " : "Overwriting ");
+ if (failed && operation == ShellUtil::SHORTCUT_REPLACE_EXISTING)
+ message.append("(maybe the shortcut doesn't exist?) ");
+ message.append((properties.level == ShellUtil::CURRENT_USER) ? "per-user " :
+ "all-users ");
+ switch (location) {
+ case ShellUtil::SHORTCUT_DESKTOP:
+ message.append("Desktop ");
+ break;
+ case ShellUtil::SHORTCUT_QUICK_LAUNCH:
+ message.append("Quick Launch ");
+ break;
+ case ShellUtil::SHORTCUT_START_MENU:
+ message.append("Start menu ");
+ break;
+ default:
+ NOTREACHED();
+ }
+
+ message.push_back('"');
+ if (properties.options &
+ ShellUtil::ChromeShortcutProperties::PROPERTIES_SHORTCUT_NAME) {
+ message.append(UTF16ToUTF8(properties.shortcut_name));
+ } else {
+ message.append(UTF16ToUTF8(dist->GetAppShortCutName()));
+ }
+ message.push_back('"');
+
+ message.append(" shortcut to ");
robertshield 2012/10/04 00:25:23 shouldn't this line be inside the if below?
gab 2012/10/04 04:10:32 No, there is always a |chrome_exe| (in CREATE and
+ message.append(UTF16ToUTF8(properties.chrome_exe.value()));
+ if (properties.options &
+ ShellUtil::ChromeShortcutProperties::PROPERTIES_ARGUMENTS) {
+ message.append(UTF16ToUTF8(properties.arguments));
+ }
+
+ if (properties.pin_to_taskbar &&
+ base::win::GetVersion() >= base::win::VERSION_WIN7) {
+ message.append(" and pinning to the taskbar.");
+ } else {
+ message.push_back('.');
+ }
+
+ if (failed)
+ LOG(WARNING) << message;
+ else
+ VLOG(1) << message;
+}
+
+void ExecuteAndLogShortcutOperation(
+ ShellUtil::ChromeShortcutLocation location,
+ BrowserDistribution* dist,
+ const ShellUtil::ChromeShortcutProperties& properties,
+ ShellUtil::ChromeShortcutOperation operation) {
+ LogShortcutOperation(location, dist, properties, operation, false);
+ if (!ShellUtil::CreateOrUpdateChromeShortcut(location, dist, properties,
+ operation)) {
+ LogShortcutOperation(location, dist, properties, operation, true);
+ }
+}
+
void AddChromeToMediaPlayerList() {
string16 reg_path(installer::kMediaPlayerRegPath);
// registry paths can also be appended like file system path
@@ -257,133 +333,108 @@ bool CreateVisualElementsManifest(const FilePath& src_path,
}
}
-void CreateOrUpdateStartMenuAndTaskbarShortcuts(
- const InstallerState& installer_state,
- const FilePath& setup_exe,
- const Product& product,
- uint32 options) {
+void CreateOrUpdateShortcuts(const InstallerState& installer_state,
+ const FilePath& setup_exe,
+ const Product& product,
+ InstallShortcutOperation install_operation,
+ bool alternate_desktop_shortcut) {
// TODO(tommi): Change this function to use WorkItemList.
DCHECK(product.is_chrome());
- // Information used for all shortcut types
- BrowserDistribution* browser_dist = product.distribution();
- const string16 product_name(browser_dist->GetAppShortCutName());
- const string16 product_desc(browser_dist->GetAppDescription());
- // Chrome link target
- FilePath chrome_exe(
+ BrowserDistribution* dist = product.distribution();
+ const FilePath chrome_exe(
installer_state.target_path().Append(installer::kChromeExe));
-
- bool create_always = ((options & ShellUtil::SHORTCUT_CREATE_ALWAYS) != 0);
- const char* operation = create_always ? "Creating" : "Updating";
-
- // Create Start Menu shortcuts.
- // The location of Start->Programs->Google Chrome folder
- FilePath start_menu_folder_path;
- int dir_enum = installer_state.system_install() ?
- base::DIR_COMMON_START_MENU : base::DIR_START_MENU;
- if (!PathService::Get(dir_enum, &start_menu_folder_path)) {
- LOG(ERROR) << "Failed to get start menu path.";
- return;
- }
-
- start_menu_folder_path = start_menu_folder_path.Append(product_name);
-
- // Create/update Chrome link (points to chrome.exe) & Uninstall Chrome link
- // (which points to setup.exe) under |start_menu_folder_path|.
-
- // Chrome link (launches Chrome)
- FilePath chrome_link(start_menu_folder_path.Append(product_name + L".lnk"));
-
- if (create_always && !file_util::PathExists(start_menu_folder_path))
- file_util::CreateDirectoryW(start_menu_folder_path);
-
- VLOG(1) << operation << " shortcut to " << chrome_exe.value() << " at "
- << chrome_link.value();
- if (!ShellUtil::UpdateChromeShortcut(browser_dist, chrome_exe.value(),
- chrome_link.value(), string16(), product_desc, chrome_exe.value(),
- browser_dist->GetIconIndex(), options)) {
- LOG(WARNING) << operation << " shortcut at " << chrome_link.value()
- << " failed.";
- } else if (create_always &&
- base::win::GetVersion() >= base::win::VERSION_WIN7) {
- // If the Start Menu shortcut was successfully created and |create_always|,
- // proceed to pin the Start Menu shortcut to the taskbar on Win7+.
- VLOG(1) << "Pinning new shortcut at " << chrome_link.value()
- << " to taskbar";
- if (!base::win::TaskbarPinShortcutLink(chrome_link.value().c_str())) {
- LOG(ERROR) << "Failed to pin shortcut to taskbar: "
- << chrome_link.value();
- }
+ ShellUtil::ShellChange install_level =
+ installer_state.system_install() ? ShellUtil::SYSTEM_LEVEL :
+ ShellUtil::CURRENT_USER;
+
+ // The default operation on update is to overwrite shortcuts with the
+ // currently desired properties, but do so only for shortcuts that still
+ // exist.
+ ShellUtil::ChromeShortcutOperation operation =
robertshield 2012/10/04 00:25:23 please call this shortcut_operation instead.
gab 2012/10/04 04:10:32 Done.
+ ShellUtil::SHORTCUT_REPLACE_EXISTING;
+ // |base_properties|: The basic properties to set on every shortcut installed
+ // (to be refined on a per-shortcut basis).
+ ShellUtil::ChromeShortcutProperties base_properties(install_level);
+ base_properties.set_chrome_exe(chrome_exe);
+ // The DUAL_MODE property is technically only needed on the Start Screen
+ // shortcut on Win8, but we set it on all shortcuts so that pinning any of the
+ // shortcuts to the Start Screen results in a shortcut with Metro properties.
+ base_properties.set_dual_mode(true);
robertshield 2012/10/04 00:25:23 imo some lines of whitespace here would make this
gab 2012/10/04 04:10:32 Done.
+ // Handle Desktop and Quick Launch shortcuts creation.
+ // If |install_operation| is INSTALL_SHORTCUT_CREATE_ALL, create optional
+ // shortcuts immediately; otherwise delay their creation until first run (if
+ // they already exist, (i.e. on update) update them).
+ if (install_operation == INSTALL_SHORTCUT_CREATE_ALL)
+ operation = ShellUtil::SHORTCUT_CREATE_ALWAYS;
+ ShellUtil::ChromeShortcutProperties desktop_properties(base_properties);
+ // Use the alternate name for the Desktop shortcut if indicated.
+ if (alternate_desktop_shortcut)
+ desktop_properties.set_shortcut_name(dist->GetAlternateApplicationName());
+ ExecuteAndLogShortcutOperation(
+ ShellUtil::SHORTCUT_DESKTOP, dist, desktop_properties, operation);
+
+ // |base_properties| are sufficient for the Quick Launch shortcut.
+ ExecuteAndLogShortcutOperation(
+ ShellUtil::SHORTCUT_QUICK_LAUNCH, dist, base_properties, operation);
+ if (installer_state.system_install() &&
+ operation == ShellUtil::SHORTCUT_CREATE_ALWAYS) {
+ // On system-level installs, also create the quick launch shortcut for this
+ // user (as the all-users shortcut created is in "Default User" and only
+ // affects new users).
+ ShellUtil::ChromeShortcutProperties user_ql_properties(base_properties);
+ user_ql_properties.level = ShellUtil::CURRENT_USER;
+ ExecuteAndLogShortcutOperation(
+ ShellUtil::SHORTCUT_QUICK_LAUNCH, dist, user_ql_properties, operation);
}
- // Create/update uninstall link if we are not an MSI install. MSI
- // installations are, for the time being, managed only through the
- // Add/Remove Programs dialog.
+ // |operation| could already have been set to SHORTCUT_CREATE_ALWAYS above if
+ // |install_operation| is INSTALL_SHORTCUT_CREATE_ALL, but make sure it is set
+ // at this point even if |install_operation| is
+ // INSTALL_SHORTCUT_CREATE_MANDATORY.
robertshield 2012/10/04 00:25:23 I find the comment above unclear. Perhaps somethin
gab 2012/10/04 04:10:32 Done and simplified all the other comments, let me
+ if (install_operation == INSTALL_SHORTCUT_CREATE_MANDATORY)
+ operation = ShellUtil::SHORTCUT_CREATE_ALWAYS;
+
+ ShellUtil::ChromeShortcutProperties start_menu_properties(base_properties);
+ if (operation == ShellUtil::SHORTCUT_CREATE_ALWAYS)
+ start_menu_properties.set_pin_to_taskbar(true);
+ ExecuteAndLogShortcutOperation(
+ ShellUtil::SHORTCUT_START_MENU, dist, start_menu_properties, operation);
+
+ // Create/update uninstall link in the Start menu if we are not an MSI
+ // install. MSI installations are, for the time being, managed only through
+ // the Add/Remove Programs dialog.
// TODO(robertshield): We could add a shortcut to msiexec /X {GUID} here.
if (!installer_state.is_msi()) {
- // Uninstall Chrome link
- FilePath uninstall_link(start_menu_folder_path.Append(
- browser_dist->GetUninstallLinkName() + L".lnk"));
-
+ FilePath shortcut_path;
+ if (!ShellUtil::GetShortcutPath(ShellUtil::SHORTCUT_START_MENU, dist,
+ install_level, &shortcut_path)) {
+ NOTREACHED();
+ return;
+ }
+ shortcut_path = shortcut_path.Append(dist->GetUninstallLinkName() +
+ kLnkExt);
CommandLine arguments(CommandLine::NO_PROGRAM);
AppendUninstallCommandLineFlags(installer_state, product, &arguments);
- VLOG(1) << operation << " uninstall link at " << uninstall_link.value();
- base::win::ShortcutProperties shortcut_properties;
- shortcut_properties.set_target(setup_exe);
- shortcut_properties.set_arguments(arguments.GetCommandLineString());
- shortcut_properties.set_icon(setup_exe, 0);
+
+ base::win::ShortcutProperties uninstall_properties;
+ uninstall_properties.set_target(setup_exe);
+ uninstall_properties.set_arguments(arguments.GetCommandLineString());
+ base::win::ShortcutOperation shortcut_operation =
+ (operation == ShellUtil::SHORTCUT_CREATE_ALWAYS ?
+ base::win::SHORTCUT_CREATE_ALWAYS :
+ base::win::SHORTCUT_REPLACE_EXISTING);
+ const char* operation_str =
+ (shortcut_operation == base::win::SHORTCUT_CREATE_ALWAYS ?
+ "Creating" : "Updating");
+ VLOG(1) << operation_str << " uninstall link at " << shortcut_path.value();
if (!base::win::CreateOrUpdateShortcutLink(
- uninstall_link, shortcut_properties,
- create_always ? base::win::SHORTCUT_CREATE_ALWAYS :
- base::win::SHORTCUT_UPDATE_EXISTING)) {
- LOG(WARNING) << operation << " uninstall link at "
- << uninstall_link.value() << " failed.";
+ shortcut_path, uninstall_properties, shortcut_operation)) {
+ LOG(WARNING) << operation_str << " uninstall link failed.";
}
}
}
-void CreateOrUpdateDesktopAndQuickLaunchShortcuts(
- const InstallerState& installer_state,
- const Product& product,
- uint32 options) {
- // TODO(tommi): Change this function to use WorkItemList.
- DCHECK(product.is_chrome());
-
- // Information used for all shortcut types
- BrowserDistribution* browser_dist = product.distribution();
- const string16 product_name(browser_dist->GetAppShortCutName());
- const string16 product_desc(browser_dist->GetAppDescription());
- // Chrome link target
- FilePath chrome_exe(
- installer_state.target_path().Append(installer::kChromeExe));
-
- bool create_always = ((options & ShellUtil::SHORTCUT_CREATE_ALWAYS) != 0);
- const char* operation = create_always ? "Creating" : "Updating";
-
- ShellUtil::ShellChange desktop_level = ShellUtil::CURRENT_USER;
- int quick_launch_levels = ShellUtil::CURRENT_USER;
- if (installer_state.system_install()) {
- desktop_level = ShellUtil::SYSTEM_LEVEL;
- quick_launch_levels |= ShellUtil::SYSTEM_LEVEL;
- }
-
- VLOG(1) << operation << " desktop shortcut for " << chrome_exe.value();
- if (!ShellUtil::CreateChromeDesktopShortcut(
- browser_dist, chrome_exe.value(), product_desc, string16(),
- string16(), chrome_exe.value(), browser_dist->GetIconIndex(),
- desktop_level, options)) {
- LOG(WARNING) << operation << " desktop shortcut for " << chrome_exe.value()
- << " failed.";
- }
-
- VLOG(1) << operation << " quick launch shortcut for " << chrome_exe.value();
- if (!ShellUtil::CreateChromeQuickLaunchShortcut(
- browser_dist, chrome_exe.value(), quick_launch_levels, options)) {
- LOG(WARNING) << operation << " quick launch shortcut for "
- << chrome_exe.value() << " failed.";
- }
-}
-
void RegisterChromeOnMachine(const InstallerState& installer_state,
const Product& product,
bool make_chrome_default) {
@@ -479,34 +530,23 @@ InstallStatus InstallOrUpdateProduct(
&create_all_shortcuts);
bool alt_shortcut = false;
prefs.GetBool(master_preferences::kAltShortcutText, &alt_shortcut);
- // The DUAL_MODE property is technically only needed on the Start Screen
- // shortcut on Win8, but we set it on all shortcuts so that pinning any
- // of the shortcuts to the Start Screen results in a shortcut with
- // Metro properties.
- uint32 shortcut_options = ShellUtil::SHORTCUT_DUAL_MODE;
- // Handle Desktop and Quick Launch shortcuts creation.
- // If --create-all-shortcuts is specified, create them immediately;
- // otherwise delay their creation until first run (if they already exist,
- // (i.e. on update) update them).
- if (create_all_shortcuts)
- shortcut_options |= ShellUtil::SHORTCUT_CREATE_ALWAYS;
- // Use the alternate name for the Desktop shortcut if indicated.
- if (alt_shortcut)
- shortcut_options |= ShellUtil::SHORTCUT_ALTERNATE;
- CreateOrUpdateDesktopAndQuickLaunchShortcuts(
- installer_state, *chrome_install, shortcut_options);
-
- if (result == installer::FIRST_INSTALL_SUCCESS ||
- result == installer::INSTALL_REPAIRED) {
- // On new installs and repaired installs, always create Start Menu
- // and taskbar shortcuts (i.e. even if they were previously deleted by
- // the user).
- shortcut_options |= ShellUtil::SHORTCUT_CREATE_ALWAYS;
+
+ InstallShortcutOperation install_operation =
+ INSTALL_SHORTCUT_REPLACE_EXISTING;
+ if (create_all_shortcuts) {
+ install_operation = INSTALL_SHORTCUT_CREATE_ALL;
+ } else if (result == installer::FIRST_INSTALL_SUCCESS ||
+ result == installer::INSTALL_REPAIRED) {
+ // On new and repaired installs, always create Start Menu, taskbar, and
+ // uninstall shortcuts (i.e. even if they were previously deleted by the
+ // user).
+ install_operation = INSTALL_SHORTCUT_CREATE_MANDATORY;
}
+
FilePath setup_exe(installer_state.GetInstallerDirectory(new_version)
.Append(setup_path.BaseName()));
- CreateOrUpdateStartMenuAndTaskbarShortcuts(
- installer_state, setup_exe, *chrome_install, shortcut_options);
+ CreateOrUpdateShortcuts(installer_state, setup_exe, *chrome_install,
+ install_operation, alt_shortcut);
bool make_chrome_default = false;
prefs.GetBool(master_preferences::kMakeChromeDefault,
@@ -563,11 +603,9 @@ void HandleOsUpgradeForBrowser(const InstallerState& installer_state,
// Chrome, so that Metro Chrome would work if Chrome is the default browser.
if (base::win::GetVersion() >= base::win::VERSION_WIN8) {
VLOG(1) << "Updating and registering shortcuts.";
- uint32 shortcut_options = ShellUtil::SHORTCUT_DUAL_MODE;
- CreateOrUpdateDesktopAndQuickLaunchShortcuts(
- installer_state, chrome, shortcut_options);
- CreateOrUpdateStartMenuAndTaskbarShortcuts(
- installer_state, setup_exe, chrome, shortcut_options);
+ CreateOrUpdateShortcuts(
+ installer_state, setup_exe, chrome, INSTALL_SHORTCUT_REPLACE_EXISTING,
+ false);
RegisterChromeOnMachine(installer_state, chrome, false);
}
}

Powered by Google App Engine
This is Rietveld 408576698