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