1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 // 5 // This file declares methods that are useful for integrating Chrome in 6 // Windows shell. These methods are all static and currently part of 7 // ShellUtil class. 8 9 #ifndef CHROME_INSTALLER_UTIL_SHELL_UTIL_H_ 10 #define CHROME_INSTALLER_UTIL_SHELL_UTIL_H_ 11 12 #include <windows.h> 13 14 #include <stddef.h> 15 #include <stdint.h> 16 17 #include <map> 18 #include <memory> 19 #include <set> 20 #include <utility> 21 #include <vector> 22 23 #include "base/check.h" 24 #include "base/files/file_path.h" 25 #include "base/macros.h" 26 #include "base/memory/ref_counted.h" 27 #include "base/strings/string16.h" 28 #include "chrome/installer/util/work_item_list.h" 29 30 class RegistryEntry; 31 32 namespace base { 33 class AtomicFlag; 34 class CommandLine; 35 } // namespace base 36 37 // This is a utility class that provides common shell integration methods 38 // that can be used by installer as well as Chrome. 39 class ShellUtil { 40 public: 41 // Input to any methods that make changes to OS shell. 42 enum ShellChange { 43 CURRENT_USER = 0x1, // Make any shell changes only at the user level 44 SYSTEM_LEVEL = 0x2 // Make any shell changes only at the system level 45 }; 46 47 // Chrome's default handler state for a given protocol. If the current install 48 // mode is not default, the brand's other modes are checked. This allows 49 // callers to take specific action in case the current mode (e.g., Chrome Dev) 50 // is not the default handler, but another of the brand's modes (e.g., stable 51 // Chrome) is. 52 enum DefaultState { 53 // An error occurred while attempting to check the default handler for the 54 // protocol. 55 UNKNOWN_DEFAULT, 56 // No install mode for the brand is default for the protocol. 57 NOT_DEFAULT, 58 // The current install mode is default. 59 IS_DEFAULT, 60 // The current install mode is not default, although one of the brand's 61 // other install modes is. 62 OTHER_MODE_IS_DEFAULT, 63 }; 64 65 // Typical shortcut directories. Resolved in GetShortcutPath(). 66 // Also used in ShortcutLocationIsSupported(). 67 enum ShortcutLocation { 68 SHORTCUT_LOCATION_FIRST = 0, 69 SHORTCUT_LOCATION_DESKTOP = SHORTCUT_LOCATION_FIRST, 70 SHORTCUT_LOCATION_QUICK_LAUNCH, 71 SHORTCUT_LOCATION_START_MENU_ROOT, 72 SHORTCUT_LOCATION_START_MENU_CHROME_DIR_DEPRECATED, // now placed in root 73 SHORTCUT_LOCATION_START_MENU_CHROME_APPS_DIR, 74 SHORTCUT_LOCATION_TASKBAR_PINS, // base::win::Version::WIN7 + 75 SHORTCUT_LOCATION_APP_SHORTCUTS, // base::win::Version::WIN8 + 76 SHORTCUT_LOCATION_STARTUP, 77 NUM_SHORTCUT_LOCATIONS 78 }; 79 80 enum ShortcutOperation { 81 // Create a new shortcut (overwriting if necessary). 82 SHELL_SHORTCUT_CREATE_ALWAYS, 83 // Create the per-user shortcut only if its system-level equivalent (with 84 // the same name) is not present. 85 SHELL_SHORTCUT_CREATE_IF_NO_SYSTEM_LEVEL, 86 // Overwrite an existing shortcut (fail if the shortcut doesn't exist). 87 // If the arguments are not specified on the new shortcut, keep the old 88 // shortcut's arguments. 89 SHELL_SHORTCUT_REPLACE_EXISTING, 90 // Update specified properties only on an existing shortcut. 91 SHELL_SHORTCUT_UPDATE_EXISTING, 92 }; 93 94 // Properties for shortcuts. Properties set will be applied to 95 // the shortcut on creation/update. On update, unset properties are ignored; 96 // on create (and replaced) unset properties might have a default value (see 97 // individual property setters below for details). 98 // Callers are encouraged to use the setters provided which take care of 99 // setting |options| as desired. 100 struct ShortcutProperties { 101 enum IndividualProperties { 102 PROPERTIES_TARGET = 1 << 0, 103 PROPERTIES_ARGUMENTS = 1 << 1, 104 PROPERTIES_DESCRIPTION = 1 << 2, 105 PROPERTIES_ICON = 1 << 3, 106 PROPERTIES_APP_ID = 1 << 4, 107 PROPERTIES_SHORTCUT_NAME = 1 << 5, 108 PROPERTIES_DUAL_MODE = 1 << 6, 109 PROPERTIES_TOAST_ACTIVATOR_CLSID = 1 << 7, 110 }; 111 112 explicit ShortcutProperties(ShellChange level_in); 113 ShortcutProperties(const ShortcutProperties& other); 114 ~ShortcutProperties(); 115 116 // Sets the target executable to launch from this shortcut. 117 // This is mandatory when creating a shortcut. set_targetShortcutProperties118 void set_target(const base::FilePath& target_in) { 119 target = target_in; 120 options |= PROPERTIES_TARGET; 121 } 122 123 // Sets the arguments to be passed to |target| when launching from this 124 // shortcut. 125 // The length of this string must be less than MAX_PATH. set_argumentsShortcutProperties126 void set_arguments(const base::string16& arguments_in) { 127 // Size restriction as per MSDN at 128 // http://msdn.microsoft.com/library/windows/desktop/bb774954.aspx. 129 DCHECK(arguments_in.length() < MAX_PATH); 130 arguments = arguments_in; 131 options |= PROPERTIES_ARGUMENTS; 132 } 133 134 // Sets the localized description of the shortcut. 135 // The length of this string must be less than MAX_PATH. set_descriptionShortcutProperties136 void set_description(const base::string16& description_in) { 137 // Size restriction as per MSDN at 138 // http://msdn.microsoft.com/library/windows/desktop/bb774955.aspx. 139 DCHECK(description_in.length() < MAX_PATH); 140 description = description_in; 141 options |= PROPERTIES_DESCRIPTION; 142 } 143 144 // Sets the path to the icon (icon_index set to 0). 145 // icon index unless otherwise specified in master_preferences). set_iconShortcutProperties146 void set_icon(const base::FilePath& icon_in, int icon_index_in) { 147 icon = icon_in; 148 icon_index = icon_index_in; 149 options |= PROPERTIES_ICON; 150 } 151 152 // Sets the app model id for the shortcut. set_app_idShortcutProperties153 void set_app_id(const base::string16& app_id_in) { 154 app_id = app_id_in; 155 options |= PROPERTIES_APP_ID; 156 } 157 158 // Forces the shortcut's name to |shortcut_name_in|. 159 // Default: InstallUtil::GetShortcutName(). 160 // The ".lnk" extension will automatically be added to this name. set_shortcut_nameShortcutProperties161 void set_shortcut_name(const base::string16& shortcut_name_in) { 162 shortcut_name = shortcut_name_in; 163 options |= PROPERTIES_SHORTCUT_NAME; 164 } 165 166 // Sets the toast activator CLSID to |toast_activator_clsid_in|. set_toast_activator_clsidShortcutProperties167 void set_toast_activator_clsid(const CLSID& toast_activator_clsid_in) { 168 toast_activator_clsid = toast_activator_clsid_in; 169 options |= PROPERTIES_TOAST_ACTIVATOR_CLSID; 170 } 171 172 // Sets whether to pin this shortcut to the taskbar after creating it 173 // (ignored if the shortcut is only being updated). 174 // Note: This property doesn't have a mask in |options|. set_pin_to_taskbarShortcutProperties175 void set_pin_to_taskbar(bool pin_to_taskbar_in) { 176 pin_to_taskbar = pin_to_taskbar_in; 177 } 178 has_targetShortcutProperties179 bool has_target() const { return (options & PROPERTIES_TARGET) != 0; } 180 has_argumentsShortcutProperties181 bool has_arguments() const { return (options & PROPERTIES_ARGUMENTS) != 0; } 182 has_descriptionShortcutProperties183 bool has_description() const { 184 return (options & PROPERTIES_DESCRIPTION) != 0; 185 } 186 has_iconShortcutProperties187 bool has_icon() const { return (options & PROPERTIES_ICON) != 0; } 188 has_app_idShortcutProperties189 bool has_app_id() const { return (options & PROPERTIES_APP_ID) != 0; } 190 has_shortcut_nameShortcutProperties191 bool has_shortcut_name() const { 192 return (options & PROPERTIES_SHORTCUT_NAME) != 0; 193 } 194 has_toast_activator_clsidShortcutProperties195 bool has_toast_activator_clsid() const { 196 return (options & PROPERTIES_TOAST_ACTIVATOR_CLSID) != 0; 197 } 198 199 // The level to install this shortcut at (CURRENT_USER for a per-user 200 // shortcut and SYSTEM_LEVEL for an all-users shortcut). 201 ShellChange level; 202 203 base::FilePath target; 204 base::string16 arguments; 205 base::string16 description; 206 base::FilePath icon; 207 int icon_index; 208 base::string16 app_id; 209 base::string16 shortcut_name; 210 CLSID toast_activator_clsid; 211 bool pin_to_taskbar; 212 // Bitfield made of IndividualProperties. Properties set in |options| will 213 // be used to create/update the shortcut, others will be ignored on update 214 // and possibly replaced by default values on create (see individual 215 // property setters above for details on default values). 216 uint32_t options; 217 }; 218 219 struct FileAssociationsAndAppName { 220 FileAssociationsAndAppName(); 221 FileAssociationsAndAppName(FileAssociationsAndAppName&& other); 222 ~FileAssociationsAndAppName(); 223 224 std::set<base::string16> file_associations; 225 base::string16 app_name; 226 }; 227 228 // Relative path of the URL Protocol registry entry (prefixed with '\'). 229 static const wchar_t* kRegURLProtocol; 230 231 // Relative path of DefaultIcon registry entry (prefixed with '\'). 232 static const wchar_t* kRegDefaultIcon; 233 234 // Relative path of "shell" registry key. 235 static const wchar_t* kRegShellPath; 236 237 // Relative path of shell open command in Windows registry 238 // (i.e. \\shell\\open\\command). 239 static const wchar_t* kRegShellOpen; 240 241 // Relative path of registry key under which applications need to register 242 // to control Windows Start menu links. 243 static const wchar_t* kRegStartMenuInternet; 244 245 // Relative path of Classes registry entry under which file associations 246 // are added on Windows. 247 static const wchar_t* kRegClasses; 248 249 // Relative path of RegisteredApplications registry entry under which 250 // we add Chrome as a Windows application 251 static const wchar_t* kRegRegisteredApplications; 252 253 // The key path and key name required to register Chrome on Windows such 254 // that it can be launched from Start->Run just by name (chrome.exe). 255 static const wchar_t* kAppPathsRegistryKey; 256 static const wchar_t* kAppPathsRegistryPathName; 257 258 // Registry path that stores url associations on Vista. 259 static const wchar_t* kRegVistaUrlPrefs; 260 261 // File extensions that Chrome registers itself as the default handler 262 // for when the user makes Chrome the default browser. 263 static const wchar_t* kDefaultFileAssociations[]; 264 265 // File extensions that Chrome registers itself as being capable of 266 // handling. 267 static const wchar_t* kPotentialFileAssociations[]; 268 269 // Protocols that Chrome registers itself as the default handler for 270 // when the user makes Chrome the default browser. 271 static const wchar_t* kBrowserProtocolAssociations[]; 272 273 // Protocols that Chrome registers itself as being capable of handling. 274 static const wchar_t* kPotentialProtocolAssociations[]; 275 276 // Registry value name that is needed for ChromeHTML ProgId 277 static const wchar_t* kRegUrlProtocol; 278 279 // Relative registry path from \Software\Classes\ChromeHTML to the ProgId 280 // Application definitions. 281 static const wchar_t* kRegApplication; 282 283 // Registry value name for the AppUserModelId of an application. 284 static const wchar_t* kRegAppUserModelId; 285 286 // Registry value name for the description of an application. 287 static const wchar_t* kRegApplicationDescription; 288 289 // Registry value name for an application's name. 290 static const wchar_t* kRegApplicationName; 291 292 // Registry value name for the path to an application's icon. 293 static const wchar_t* kRegApplicationIcon; 294 295 // Registry value name for an application's company. 296 static const wchar_t* kRegApplicationCompany; 297 298 // Relative path of ".exe" registry key. 299 static const wchar_t* kRegExePath; 300 301 // Registry value name of the open verb. 302 static const wchar_t* kRegVerbOpen; 303 304 // Registry value name of the opennewwindow verb. 305 static const wchar_t* kRegVerbOpenNewWindow; 306 307 // Registry value name of the run verb. 308 static const wchar_t* kRegVerbRun; 309 310 // Registry value name for command entries. 311 static const wchar_t* kRegCommand; 312 313 // Registry value name for the DelegateExecute verb handler. 314 static const wchar_t* kRegDelegateExecute; 315 316 // Registry value name for the OpenWithProgids entry for file associations. 317 static const wchar_t* kRegOpenWithProgids; 318 319 // Returns true if |chrome_exe| is registered in HKLM with |suffix|. 320 // Note: This only checks one deterministic key in HKLM for |chrome_exe| and 321 // doesn't otherwise validate a full Chrome install in HKLM. 322 static bool QuickIsChromeRegisteredInHKLM(const base::FilePath& chrome_exe, 323 const base::string16& suffix); 324 325 // Returns true if the current Windows version supports the presence of 326 // shortcuts at |location|. 327 static bool ShortcutLocationIsSupported(ShortcutLocation location); 328 329 // Sets |path| to the path for a shortcut at the |location| desired for the 330 // given |level| (CURRENT_USER for per-user path and SYSTEM_LEVEL for 331 // all-users path). 332 // Returns false on failure. 333 static bool GetShortcutPath(ShortcutLocation location, 334 ShellChange level, 335 base::FilePath* path); 336 337 // Populates the uninitialized members of |properties| with default values. 338 static void AddDefaultShortcutProperties(const base::FilePath& target_exe, 339 ShortcutProperties* properties); 340 341 // Move an existing shortcut from |old_location| to |new_location| for the 342 // set |shortcut_level|. If the folder containing |old_location| is then 343 // empty, it will be removed. 344 static bool MoveExistingShortcut(ShortcutLocation old_location, 345 ShortcutLocation new_location, 346 const ShortcutProperties& properties); 347 348 // Updates shortcut in |location| (or creates it if |options| specify 349 // SHELL_SHORTCUT_CREATE_ALWAYS). 350 // |properties| and |operation| affect this method as described on their 351 // invidividual definitions above. 352 // |location| may be one of SHORTCUT_LOCATION_DESKTOP, 353 // SHORTCUT_LOCATION_QUICK_LAUNCH, SHORTCUT_LOCATION_START_MENU_ROOT, 354 // SHORTCUT_LOCATION_START_MENU_CHROME_DIR, or 355 // SHORTCUT_LOCATION_START_MENU_CHROME_APPS_DIR. 356 static bool CreateOrUpdateShortcut(ShortcutLocation location, 357 const ShortcutProperties& properties, 358 ShortcutOperation operation); 359 360 // Returns the string "|icon_path|,|icon_index|" (see, for example, 361 // http://msdn.microsoft.com/library/windows/desktop/dd391573.aspx). 362 static base::string16 FormatIconLocation(const base::FilePath& icon_path, 363 int icon_index); 364 365 // This method returns the command to open URLs/files using chrome. Typically 366 // this command is written to the registry under shell\open\command key. 367 // |chrome_exe|: the full path to chrome.exe 368 static base::string16 GetChromeShellOpenCmd(const base::FilePath& chrome_exe); 369 370 // This method returns the command to be called by the DelegateExecute verb 371 // handler to launch chrome on Windows 8. Typically this command is written to 372 // the registry under the HKCR\Chrome\.exe\shell\(open|run)\command key. 373 // |chrome_exe|: the full path to chrome.exe 374 static base::string16 GetChromeDelegateCommand( 375 const base::FilePath& chrome_exe); 376 377 // Gets a mapping of all registered browser names (excluding the current 378 // browser) and their reinstall command (which usually sets browser as 379 // default). 380 // Given browsers can be registered in HKCU (as of Win7) and/or in HKLM, this 381 // method looks in both and gives precedence to values in HKCU as per the msdn 382 // standard: http://goo.gl/xjczJ. 383 static void GetRegisteredBrowsers( 384 std::map<base::string16, base::string16>* browsers); 385 386 // Returns the suffix this user's Chrome install is registered with. 387 // Always returns the empty string on system-level installs. 388 // 389 // This method is meant for external methods which need to know the suffix of 390 // the current install at run-time, not for install-time decisions. 391 // There are no guarantees that this suffix will not change later: 392 // (e.g. if two user-level installs were previously installed in parallel on 393 // the same machine, both without admin rights and with no user-level install 394 // having claimed the non-suffixed HKLM registrations, they both have no 395 // suffix in their progId entries (as per the old suffix rules). If they were 396 // to both fully register (i.e. click "Make Chrome Default" and go through 397 // UAC; or upgrade to Win8 and get the automatic no UAC full registration) 398 // they would then both get a suffixed registration as per the new suffix 399 // rules). 400 // 401 // |chrome_exe| The path to the currently installed (or running) chrome.exe. 402 static base::string16 GetCurrentInstallationSuffix( 403 const base::FilePath& chrome_exe); 404 405 // Returns the AppUserModelId. This identifier is unconditionally suffixed 406 // with a unique id for this user on user-level installs (in contrast to other 407 // registration entries which are suffixed as described in 408 // GetCurrentInstallationSuffix() above). 409 static base::string16 GetBrowserModelId(bool is_per_user_install); 410 411 // Returns an AppUserModelId composed of each member of |components| separated 412 // by dots. 413 // The returned appid is guaranteed to be no longer than 414 // chrome::kMaxAppModelIdLength (some of the components might have been 415 // shortened to enforce this). 416 static base::string16 BuildAppUserModelId( 417 const std::vector<base::string16>& components); 418 419 // Returns true if Chrome can make itself the default browser without relying 420 // on the Windows shell to prompt the user. This is the case for versions of 421 // Windows prior to Windows 8. 422 static bool CanMakeChromeDefaultUnattended(); 423 424 enum InteractiveSetDefaultMode { 425 // The intent picker is opened with the different choices available to the 426 // user. 427 INTENT_PICKER, 428 // The Windows default apps settings page is opened with the current default 429 // app focused. 430 SYSTEM_SETTINGS, 431 }; 432 433 // Returns the interactive mode that should be used to set the default browser 434 // or default protocol client on Windows 8+. 435 static InteractiveSetDefaultMode GetInteractiveSetDefaultMode(); 436 437 // Returns the DefaultState of Chrome for HTTP and HTTPS and updates the 438 // default browser beacons as appropriate. 439 static DefaultState GetChromeDefaultState(); 440 441 // Returns the DefaultState of the Chrome instance with the specified path for 442 // HTTP and HTTPs and updates the default browser beacons as appropriate. 443 static DefaultState GetChromeDefaultStateFromPath( 444 const base::FilePath& chrome_exe); 445 446 // Returns the DefaultState of Chrome for |protocol|. 447 static DefaultState GetChromeDefaultProtocolClientState( 448 const base::string16& protocol); 449 450 // Make Chrome the default browser. This function works by going through 451 // the url protocols and file associations that are related to general 452 // browsing, e.g. http, https, .html etc., and requesting to become the 453 // default handler for each. If any of these fails the operation will return 454 // false to indicate failure, which is consistent with the return value of 455 // shell_integration::GetDefaultBrowser. 456 // 457 // In the case of failure any successful changes will be left, however no 458 // more changes will be attempted. 459 // TODO(benwells): Attempt to undo any changes that were successfully made. 460 // http://crbug.com/83970 461 // 462 // shell_change: Defined whether to register as default browser at system 463 // level or user level. If value has ShellChange::SYSTEM_LEVEL 464 // we should be running as admin user. 465 // chrome_exe: The chrome.exe path to register as default browser. 466 // elevate_if_not_admin: On Vista if user is not admin, try to elevate for 467 // Chrome registration. 468 static bool MakeChromeDefault(int shell_change, 469 const base::FilePath& chrome_exe, 470 bool elevate_if_not_admin); 471 472 // Opens the Apps & Features page in the Windows settings in branded builds. 473 // 474 // This function DCHECKS that it is only called on Windows 10 or higher. 475 static bool LaunchUninstallAppsSettings(); 476 477 // Windows 8: Shows and waits for the "How do you want to open webpages?" 478 // dialog if Chrome is not already the default HTTP/HTTPS handler. Also does 479 // XP-era registrations if Chrome is chosen or was already the default. Do 480 // not use on pre-Win8 OSes. 481 // 482 // Windows 10: The associations dialog cannot be launched so the settings 483 // dialog focused on default apps is launched. The function does not wait 484 // in this case. 485 // 486 // |chrome_exe| The chrome.exe path to register as default browser. 487 static bool ShowMakeChromeDefaultSystemUI(const base::FilePath& chrome_exe); 488 489 // Make Chrome the default application for a protocol. 490 // chrome_exe: The chrome.exe path to register as default browser. 491 // protocol: The protocol to register as the default handler for. 492 static bool MakeChromeDefaultProtocolClient(const base::FilePath& chrome_exe, 493 const base::string16& protocol); 494 495 // Shows and waits for the Windows 8 "How do you want to open links of this 496 // type?" dialog if Chrome is not already the default |protocol| 497 // handler. Also does XP-era registrations if Chrome is chosen or was already 498 // the default for |protocol|. Do not use on pre-Win8 OSes. 499 // 500 // |chrome_exe| The chrome.exe path to register as default browser. 501 // |protocol| is the protocol being registered. 502 static bool ShowMakeChromeDefaultProtocolClientSystemUI( 503 const base::FilePath& chrome_exe, 504 const base::string16& protocol); 505 506 // Registers Chrome as a potential default browser and handler for filetypes 507 // and protocols. 508 // If Chrome is already registered, this method is a no-op. 509 // This method requires write access to HKLM (prior to Win8) so is just a 510 // best effort deal. 511 // If write to HKLM is required, but fails, and: 512 // - |elevate_if_not_admin| is true (and OS is Vista or above): 513 // tries to launch setup.exe with admin privileges (by prompting the user 514 // with a UAC) to do these tasks. 515 // - |elevate_if_not_admin| is false (or OS is XP): 516 // adds the ProgId entries to HKCU. These entries will not make Chrome show 517 // in Default Programs but they are still useful because Chrome can be 518 // registered to run when the user clicks on an http link or an html file. 519 // 520 // |chrome_exe| full path to chrome.exe. 521 // |unique_suffix| Optional input. If given, this function appends the value 522 // to default browser entries names that it creates in the registry. 523 // Currently, this is only used to continue an install with the same suffix 524 // when elevating and calling setup.exe with admin privileges as described 525 // above. 526 // |elevate_if_not_admin| if true will make this method try alternate methods 527 // as described above. This should only be true when following a user action 528 // (e.g. "Make Chrome Default") as it allows this method to UAC. 529 // 530 // Returns true if Chrome is successfully registered (or already registered). 531 static bool RegisterChromeBrowser(const base::FilePath& chrome_exe, 532 const base::string16& unique_suffix, 533 bool elevate_if_not_admin); 534 535 // Same as RegisterChromeBrowser above, except that we don't stop early if 536 // there is an error adding registry entries and we disable rollback. 537 // |elevate_if_not_admin| is false and unique_suffix is empty. 538 static void RegisterChromeBrowserBestEffort(const base::FilePath& chrome_exe); 539 540 // This method declares to Windows that Chrome is capable of handling the 541 // given protocol. This function will call the RegisterChromeBrowser function 542 // to register with Windows as capable of handling the protocol, if it isn't 543 // currently registered as capable. 544 // Declaring the capability of handling a protocol is necessary to register 545 // as the default handler for the protocol in Vista and later versions of 546 // Windows. 547 // 548 // If called by the browser and elevation is required, it will elevate by 549 // calling setup.exe which will again call this function with elevate false. 550 // 551 // |chrome_exe| full path to chrome.exe. 552 // |unique_suffix| Optional input. If given, this function appends the value 553 // to default browser entries names that it creates in the registry. 554 // |protocol| The protocol to register as being capable of handling.s 555 // |elevate_if_not_admin| if true will make this method try alternate methods 556 // as described above. 557 static bool RegisterChromeForProtocol(const base::FilePath& chrome_exe, 558 const base::string16& unique_suffix, 559 const base::string16& protocol, 560 bool elevate_if_not_admin); 561 562 // Removes installed shortcut(s) at |location|. 563 // |level|: CURRENT_USER to remove per-user shortcuts, or SYSTEM_LEVEL to 564 // remove all-users shortcuts. 565 // |target_exe|: Shortcut target exe; shortcuts will only be deleted when 566 // their target is |target_exe|. 567 // If |location| is a Chrome-specific folder, it will be deleted as well. 568 // Returns true if all shortcuts pointing to |target_exe| are successfully 569 // deleted, including the case where no such shortcuts are found. 570 static bool RemoveShortcuts(ShortcutLocation location, 571 ShellChange level, 572 const base::FilePath& target_exe); 573 574 // Updates the target of all shortcuts in |location| that satisfy the 575 // following: 576 // - the shortcut's original target is |old_target_exe|, 577 // - the original arguments are non-empty. 578 // If the shortcut's icon points to |old_target_exe|, then it also gets 579 // redirected to |new_target_exe|. 580 // Returns true if all updates to matching shortcuts are successful, including 581 // the vacuous case where no matching shortcuts are found. 582 static bool RetargetShortcutsWithArgs(ShortcutLocation location, 583 ShellChange level, 584 const base::FilePath& old_target_exe, 585 const base::FilePath& new_target_exe); 586 587 typedef base::RefCountedData<base::AtomicFlag> SharedCancellationFlag; 588 589 // Appends Chrome shortcuts with disallowed arguments to |shortcuts| if 590 // not nullptr. If |do_removal|, also removes disallowed arguments from 591 // those shortcuts. This method will abort and return false if |cancel| is 592 // non-nullptr and gets set at any point during this call. 593 static bool ShortcutListMaybeRemoveUnknownArgs( 594 ShortcutLocation location, 595 ShellChange level, 596 const base::FilePath& chrome_exe, 597 bool do_removal, 598 const scoped_refptr<SharedCancellationFlag>& cancel, 599 std::vector<std::pair<base::FilePath, base::string16>>* shortcuts); 600 601 // Resets file attributes on shortcuts to a known good default value. 602 // Ensures that Chrome shortcuts are not hidden from the user. 603 // Returns true if all updates to matching shortcuts are successful or if no 604 // matching shortcuts were found. 605 static bool ResetShortcutFileAttributes(ShortcutLocation location, 606 ShellChange level, 607 const base::FilePath& chrome_exe); 608 609 // Sets |suffix| to the base 32 encoding of the md5 hash of this user's sid 610 // preceded by a dot. 611 // This is guaranteed to be unique on the machine and 27 characters long 612 // (including the '.'). 613 // This suffix is then meant to be added to all registration that may conflict 614 // with another user-level Chrome install. 615 // Note that prior to Chrome 21, the suffix registered used to be the user's 616 // username (see GetOldUserSpecificRegistrySuffix() below). We still honor old 617 // installs registered that way, but it was wrong because some of the 618 // characters allowed in a username are not allowed in a ProgId. 619 // Returns true unless the OS call to retrieve the username fails. 620 // NOTE: Only the installer should use this suffix directly. Other callers 621 // should call GetCurrentInstallationSuffix(). 622 static bool GetUserSpecificRegistrySuffix(base::string16* suffix); 623 624 // Sets |suffix| to this user's username preceded by a dot. This suffix should 625 // only be used to support legacy installs that used this suffixing 626 // style. 627 // Returns true unless the OS call to retrieve the username fails. 628 // NOTE: Only the installer should use this suffix directly. Other callers 629 // should call GetCurrentInstallationSuffix(). 630 static bool GetOldUserSpecificRegistrySuffix(base::string16* suffix); 631 632 // Associates a set of file extensions with a particular application in the 633 // Windows registry, for the current user only. If an extension has no 634 // existing default association, the given application becomes the default. 635 // Otherwise, the application is added to the Open With menu for this type, 636 // but does not become the default. 637 // 638 // |prog_id| is the ProgId used by Windows for file associations with this 639 // application. Must not be empty or start with a '.'. 640 // |command_line| is the command to execute when opening a file via this 641 // association. It must not contain the Windows filename placeholder "%1"; 642 // this function will register |command_line| plus the filename placeholder. 643 // |application_name| is the friendly name displayed for this application in 644 // the Open With menu. 645 // |file_type_name| is the friendly name for files of these types when 646 // associated with this application by default. 647 // |icon_path| is the path of the icon displayed for this application in the 648 // Open With menu, and used for files of these types when associated with this 649 // application by default. 650 // |file_extensions| is the set of extensions to associate. They must not be 651 // empty or start with a '.'. 652 // Returns true on success, false on failure. 653 static bool AddFileAssociations( 654 const base::string16& prog_id, 655 const base::CommandLine& command_line, 656 const base::string16& application_name, 657 const base::string16& file_type_name, 658 const base::FilePath& icon_path, 659 const std::set<base::string16>& file_extensions); 660 661 // Deletes all associations with a particular application in the Windows 662 // registry, for the current user only. 663 // |prog_id| is the ProgId used by Windows for file associations with this 664 // application, as given to AddFileAssociations. All information associated 665 // with this name will be deleted. 666 static bool DeleteFileAssociations(const base::string16& prog_id); 667 668 // Adds an application entry and metadata sub-entries to 669 // HKCU\SOFTWARE\classes\<prog_id> capable of handling file type / 670 // protocol associations. 671 // 672 // |prog_id| is the ProgId used by Windows to uniquely identity this 673 // application. Must not be empty or start with a '.'. 674 // |shell_open_command_line| is the command to execute when opening the app 675 // via association. 676 // |application_name| is the friendly name displayed for this application in 677 // the Open With menu. 678 // |application_description| is the description for this application to be 679 // displayed by certain Windows settings dialogs. 680 // |icon_path| is the path of the icon displayed for this application in the 681 // Open With menu, and used for default files / protocols associated with this 682 // application. 683 static bool AddApplicationClass( 684 const base::string16& prog_id, 685 const base::CommandLine& shell_open_command_line, 686 const base::string16& application_name, 687 const base::string16& application_description, 688 const base::FilePath& icon_path); 689 690 // Removes all entries of an application at HKCU\SOFTWARE\classes\<prog_id>. 691 static bool DeleteApplicationClass(const base::string16& prog_id); 692 693 // Returns the app name and file associations registered for a particular 694 // application in the Windows registry. If there is no entry in the registry 695 // for |prog_id|, nothing will be returned. 696 static FileAssociationsAndAppName GetFileAssociationsAndAppName( 697 const base::string16& prog_id); 698 699 // Retrieves the file path of the application registered as the 700 // shell->open->command for |prog_id|. This only queries the user's 701 // registered applications in HKCU. If |prog_id| is for an app that is 702 // unrelated to the user's browser, it will still return the application 703 // registered for |prog_id|. 704 static base::FilePath GetApplicationPathForProgId( 705 const base::string16& prog_id); 706 707 // This method converts all the RegistryEntries from the given list to 708 // Set/CreateRegWorkItems and runs them using WorkItemList. 709 // |best_effort_no_rollback| is used to set WorkItemList::set_rollback_enabled 710 // and WorkItemList::set_best_effort. 711 static bool AddRegistryEntries( 712 HKEY root, 713 const std::vector<std::unique_ptr<RegistryEntry>>& entries, 714 bool best_effort_no_rollback = false); 715 716 private: 717 DISALLOW_COPY_AND_ASSIGN(ShellUtil); 718 }; 719 720 #endif // CHROME_INSTALLER_UTIL_SHELL_UTIL_H_ 721