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 utility functions for the installer. The original reason 6 // for putting these functions in installer\util library is so that we can 7 // separate out the critical logic and write unit tests for it. 8 9 #ifndef CHROME_INSTALLER_UTIL_INSTALL_UTIL_H_ 10 #define CHROME_INSTALLER_UTIL_INSTALL_UTIL_H_ 11 12 #include <windows.h> 13 #include <string> 14 #include <utility> 15 #include <vector> 16 17 #include "base/command_line.h" 18 #include "base/files/file.h" 19 #include "base/files/file_path.h" 20 #include "base/macros.h" 21 #include "base/optional.h" 22 #include "base/strings/string16.h" 23 #include "base/strings/string_piece.h" 24 #include "base/util/type_safety/strong_alias.h" 25 #include "base/version.h" 26 #include "base/win/registry.h" 27 #include "base/win/scoped_handle.h" 28 #include "chrome/installer/util/util_constants.h" 29 30 class WorkItemList; 31 32 // This is a utility class that provides common installation related 33 // utility methods that can be used by installer and also unit tested 34 // independently. 35 class InstallUtil { 36 public: 37 // Attempts to trigger the command that would be run by Active Setup for a 38 // system-level Chrome. For use only when system-level Chrome is installed. 39 static void TriggerActiveSetupCommand(); 40 41 // Launches given exe as admin on Vista. 42 static bool ExecuteExeAsAdmin(const base::CommandLine& cmd, DWORD* exit_code); 43 44 // Reads the uninstall command for Chromium from the Windows registry and 45 // returns it. If |system_install| is true the command is read from HKLM, 46 // otherwise from HKCU. Returns an empty CommandLine if Chrome is not 47 // installed. 48 static base::CommandLine GetChromeUninstallCmd(bool system_install); 49 50 // Returns the version of Chrome registered with Google Update, or an invalid 51 // Version in case no such value could be found. |system_install| indicates 52 // whether HKLM (true) or HKCU (false) should be checked. 53 static base::Version GetChromeVersion(bool system_install); 54 55 // Returns the last critical update (version) of Chrome, or an invalid Version 56 // in case no such value is found. A critical update is a specially flagged 57 // version (by Google Update) that contains an important security fix. 58 static base::Version GetCriticalUpdateVersion(); 59 60 // This function checks if the current OS is supported for Chromium. 61 static bool IsOSSupported(); 62 63 // Adds work items to |install_list| to set installer error information in the 64 // registry for consumption by Google Update. |install_list| must be best- 65 // effort with rollback disabled. |state_key| must be the full path to an 66 // app's ClientState key. See InstallerState::WriteInstallerResult for more 67 // details. 68 static void AddInstallerResultItems(bool system_install, 69 const base::string16& state_key, 70 installer::InstallStatus status, 71 int string_resource_id, 72 const base::string16* const launch_cmd, 73 WorkItemList* install_list); 74 75 // Returns true if this installation path is per user, otherwise returns false 76 // (per machine install, meaning: the exe_path contains the path to Program 77 // Files). 78 // TODO(grt): consider replacing all callers with direct use of 79 // InstallDetails. 80 static bool IsPerUserInstall(); 81 82 // Returns true if the sentinel file exists (or the path cannot be obtained). 83 static bool IsFirstRunSentinelPresent(); 84 85 // Test to see if a Start menu shortcut exists with the right toast activator 86 // CLSID registered. 87 static bool IsStartMenuShortcutWithActivatorGuidInstalled(); 88 89 // Returns the toast activator registry path. 90 static base::string16 GetToastActivatorRegistryPath(); 91 92 // Populates |path| with EULA sentinel file path. Returns false on error. 93 static bool GetEulaSentinelFilePath(base::FilePath* path); 94 95 // Deletes the registry key at path key_path under the key given by root_key. 96 static bool DeleteRegistryKey(HKEY root_key, 97 const base::string16& key_path, 98 REGSAM wow64_access); 99 100 // Deletes the registry value named value_name at path key_path under the key 101 // given by reg_root. 102 static bool DeleteRegistryValue(HKEY reg_root, 103 const base::string16& key_path, 104 REGSAM wow64_access, 105 const base::string16& value_name); 106 107 // An interface to a predicate function for use by DeleteRegistryKeyIf and 108 // DeleteRegistryValueIf. 109 class RegistryValuePredicate { 110 public: ~RegistryValuePredicate()111 virtual ~RegistryValuePredicate() {} 112 virtual bool Evaluate(const base::string16& value) const = 0; 113 }; 114 115 // The result of a conditional delete operation (i.e., DeleteFOOIf). 116 enum ConditionalDeleteResult { 117 NOT_FOUND, // The condition was not satisfied. 118 DELETED, // The condition was satisfied and the delete succeeded. 119 DELETE_FAILED // The condition was satisfied but the delete failed. 120 }; 121 122 // Deletes the key |key_to_delete_path| under |root_key| iff the value 123 // |value_name| in the key |key_to_test_path| under |root_key| satisfies 124 // |predicate|. |value_name| may be either nullptr or an empty string to test 125 // the key's default value. 126 static ConditionalDeleteResult DeleteRegistryKeyIf( 127 HKEY root_key, 128 const base::string16& key_to_delete_path, 129 const base::string16& key_to_test_path, 130 REGSAM wow64_access, 131 const wchar_t* value_name, 132 const RegistryValuePredicate& predicate); 133 134 // Deletes the value |value_name| in the key |key_path| under |root_key| iff 135 // its current value satisfies |predicate|. |value_name| may be either 136 // nullptr or an empty string to test/delete the key's default value. 137 static ConditionalDeleteResult DeleteRegistryValueIf( 138 HKEY root_key, 139 const wchar_t* key_path, 140 REGSAM wow64_access, 141 const wchar_t* value_name, 142 const RegistryValuePredicate& predicate); 143 144 // A predicate that performs a case-sensitive string comparison. 145 class ValueEquals : public RegistryValuePredicate { 146 public: ValueEquals(const base::string16 & value_to_match)147 explicit ValueEquals(const base::string16& value_to_match) 148 : value_to_match_(value_to_match) {} 149 bool Evaluate(const base::string16& value) const override; 150 151 protected: 152 base::string16 value_to_match_; 153 154 private: 155 DISALLOW_COPY_AND_ASSIGN(ValueEquals); 156 }; 157 158 // Returns zero on install success, or an InstallStatus value otherwise. 159 static int GetInstallReturnCode(installer::InstallStatus install_status); 160 161 // Composes |program| and |arguments| into |command_line|. 162 static void ComposeCommandLine(const base::string16& program, 163 const base::string16& arguments, 164 base::CommandLine* command_line); 165 166 // Appends the installer switch that selects the current install mode and 167 // policy-specified channel (see install_static::InstallDetails). 168 static void AppendModeAndChannelSwitches(base::CommandLine* command_line); 169 170 // Returns a string in the form YYYYMMDD of the current date. 171 static base::string16 GetCurrentDate(); 172 173 // Returns the highest Chrome version that was installed prior to a downgrade, 174 // or no value if Chrome was not previously downgraded from a newer version. 175 static base::Optional<base::Version> GetDowngradeVersion(); 176 177 // Adds or removes downgrade version registry value. This function should only 178 // be used for Chrome install. 179 static void AddUpdateDowngradeVersionItem( 180 HKEY root, 181 const base::Version& current_version, 182 const base::Version& new_version, 183 WorkItemList* list); 184 185 // Returns pairs of registry key paths and value names where the enrollment 186 // token is stored for machine level user cloud policies. The locations are 187 // returned in order of preference. 188 static std::vector<std::pair<std::wstring, std::wstring>> 189 GetCloudManagementEnrollmentTokenRegistryPaths(); 190 191 using ReadOnly = util::StrongAlias<class ReadOnlyTag, bool>; 192 using BrowserLocation = util::StrongAlias<class BrowserLocationTag, bool>; 193 194 // Returns the registry key and value name from/to which a cloud management DM 195 // token may be read/written. |read_only| indicates whether they key is opened 196 // for reading the value or writing it. |browser_location| indicates whether 197 // the legacy browser-specific location is returned rather than the 198 // app-neutral location. The returned key will be invalid if it could not be 199 // opened/created. 200 static std::pair<base::win::RegKey, std::wstring> 201 GetCloudManagementDmTokenLocation(ReadOnly read_only, 202 BrowserLocation browser_location); 203 204 // Returns the token used to enroll this chrome instance for machine level 205 // user cloud policies. Returns an empty string if this machine should not 206 // be enrolled. 207 static base::string16 GetCloudManagementEnrollmentToken(); 208 209 // Returns true if cloud management enrollment is mandatory. 210 static bool ShouldCloudManagementBlockOnFailure(); 211 212 // Returns the localized name of the browser. 213 static base::string16 GetDisplayName(); 214 215 // Returns the app description for shortcuts. 216 static base::string16 GetAppDescription(); 217 218 // Returns the name of the browser's publisher. 219 static base::string16 GetPublisherName(); 220 221 // Returns the name of Chrome's shortcut in the Start Menu (among other 222 // places). 223 static base::string16 GetShortcutName(); 224 225 // Returns the name of the subdirectory in which Chrome's Start Menu shortcut 226 // was once placed. This remains purely to migrate old installs to the new 227 // style. 228 static base::string16 GetChromeShortcutDirNameDeprecated(); 229 230 // Returns the name of the subdirectory in the Start Menu in which Chrome 231 // apps' shortcuts are placed. 232 static base::string16 GetChromeAppsShortcutDirName(); 233 234 // Returns the long description of Chrome used when registering as a browser 235 // with Windows. 236 static base::string16 GetLongAppDescription(); 237 238 // A predicate that compares the program portion of a command line with a 239 // given file path. First, the file paths are compared directly. If they do 240 // not match, the filesystem is consulted to determine if the paths reference 241 // the same file. 242 class ProgramCompare : public RegistryValuePredicate { 243 public: 244 explicit ProgramCompare(const base::FilePath& path_to_match); 245 ~ProgramCompare() override; 246 bool Evaluate(const base::string16& value) const override; 247 bool EvaluatePath(const base::FilePath& path) const; 248 249 protected: 250 static bool OpenForInfo(const base::FilePath& path, base::File* file); 251 static bool GetInfo(const base::File& file, 252 BY_HANDLE_FILE_INFORMATION* info); 253 254 base::FilePath path_to_match_; 255 base::File file_; 256 BY_HANDLE_FILE_INFORMATION file_info_; 257 258 private: 259 DISALLOW_COPY_AND_ASSIGN(ProgramCompare); 260 }; // class ProgramCompare 261 262 // Converts a product GUID into a SQuished gUID that is used for MSI installer 263 // registry entries. 264 static base::string16 GuidToSquid(base::StringPiece16 guid); 265 266 private: 267 DISALLOW_COPY_AND_ASSIGN(InstallUtil); 268 }; 269 270 #endif // CHROME_INSTALLER_UTIL_INSTALL_UTIL_H_ 271