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 <tchar.h> 14 15 #include "base/basictypes.h" 16 #include "base/command_line.h" 17 #include "base/files/file.h" 18 #include "base/files/file_path.h" 19 #include "base/strings/string16.h" 20 #include "base/win/scoped_handle.h" 21 #include "chrome/installer/util/browser_distribution.h" 22 #include "chrome/installer/util/util_constants.h" 23 24 class WorkItemList; 25 26 namespace base { 27 class Version; 28 } 29 30 // This is a utility class that provides common installation related 31 // utility methods that can be used by installer and also unit tested 32 // independently. 33 class InstallUtil { 34 public: 35 // Get the path to this distribution's Active Setup registry entries. 36 // e.g. Software\Microsoft\Active Setup\Installed Components\<dist_guid> 37 static base::string16 GetActiveSetupPath(BrowserDistribution* dist); 38 39 // Attempts to trigger the command that would be run by Active Setup for a 40 // system-level Chrome. For use only when system-level Chrome is installed. 41 static void TriggerActiveSetupCommand(); 42 43 // Launches given exe as admin on Vista. 44 static bool ExecuteExeAsAdmin(const base::CommandLine& cmd, DWORD* exit_code); 45 46 // Reads the uninstall command for Chromium from registry and returns it. 47 // If system_install is true the command is read from HKLM, otherwise 48 // from HKCU. 49 static base::CommandLine GetChromeUninstallCmd( 50 bool system_install, 51 BrowserDistribution::Type distribution_type); 52 53 // Find the version of Chrome installed on the system by checking the 54 // Google Update registry key. Fills |version| with the version or a 55 // default-constructed Version if no version is found. 56 // system_install: if true, looks for version number under the HKLM root, 57 // otherwise looks under the HKCU. 58 static void GetChromeVersion(BrowserDistribution* dist, 59 bool system_install, 60 base::Version* version); 61 62 // Find the last critical update (version) of Chrome. Fills |version| with the 63 // version or a default-constructed Version if no version is found. A critical 64 // update is a specially flagged version (by Google Update) that contains an 65 // important security fix. 66 // system_install: if true, looks for version number under the HKLM root, 67 // otherwise looks under the HKCU. 68 static void GetCriticalUpdateVersion(BrowserDistribution* dist, 69 bool system_install, 70 base::Version* version); 71 72 // This function checks if the current OS is supported for Chromium. 73 static bool IsOSSupported(); 74 75 // Adds work items to |install_list|, which should be a 76 // NoRollbackWorkItemList, to set installer error information in the registry 77 // for consumption by Google Update. |state_key| must be the full path to an 78 // app's ClientState key. See InstallerState::WriteInstallerResult for more 79 // details. 80 static void AddInstallerResultItems(bool system_install, 81 const base::string16& state_key, 82 installer::InstallStatus status, 83 int string_resource_id, 84 const base::string16* const launch_cmd, 85 WorkItemList* install_list); 86 87 // Update the installer stage reported by Google Update. |state_key_path| 88 // should be obtained via the state_key method of an InstallerState instance 89 // created before the machine state is modified by the installer. 90 static void UpdateInstallerStage(bool system_install, 91 const base::string16& state_key_path, 92 installer::InstallerStage stage); 93 94 // Returns true if this installation path is per user, otherwise returns 95 // false (per machine install, meaning: the exe_path contains path to 96 // Program Files). 97 static bool IsPerUserInstall(const wchar_t* const exe_path); 98 99 // Returns true if the installation represented by the pair of |dist| and 100 // |system_level| is a multi install. 101 static bool IsMultiInstall(BrowserDistribution* dist, bool system_install); 102 103 // Returns true if this is running setup process for Chrome SxS (as 104 // indicated by the presence of --chrome-sxs on the command line) or if this 105 // is running Chrome process from the Chrome SxS installation (as indicated 106 // by either --chrome-sxs or the executable path). 107 static bool IsChromeSxSProcess(); 108 109 // Returns true if the sentinel file exists (or the path cannot be obtained). 110 static bool IsFirstRunSentinelPresent(); 111 112 // Populates |path| with EULA sentinel file path. Returns false on error. 113 static bool GetEULASentinelFilePath(base::FilePath* path); 114 115 // Deletes the registry key at path key_path under the key given by root_key. 116 static bool DeleteRegistryKey(HKEY root_key, 117 const base::string16& key_path, 118 REGSAM wow64_access); 119 120 // Deletes the registry value named value_name at path key_path under the key 121 // given by reg_root. 122 static bool DeleteRegistryValue(HKEY reg_root, const base::string16& key_path, 123 REGSAM wow64_access, 124 const base::string16& value_name); 125 126 // An interface to a predicate function for use by DeleteRegistryKeyIf and 127 // DeleteRegistryValueIf. 128 class RegistryValuePredicate { 129 public: 130 virtual ~RegistryValuePredicate() { } 131 virtual bool Evaluate(const base::string16& value) const = 0; 132 }; 133 134 // The result of a conditional delete operation (i.e., DeleteFOOIf). 135 enum ConditionalDeleteResult { 136 NOT_FOUND, // The condition was not satisfied. 137 DELETED, // The condition was satisfied and the delete succeeded. 138 DELETE_FAILED // The condition was satisfied but the delete failed. 139 }; 140 141 // Deletes the key |key_to_delete_path| under |root_key| iff the value 142 // |value_name| in the key |key_to_test_path| under |root_key| satisfies 143 // |predicate|. |value_name| may be either NULL or an empty string to test 144 // the key's default value. 145 static ConditionalDeleteResult DeleteRegistryKeyIf( 146 HKEY root_key, 147 const base::string16& key_to_delete_path, 148 const base::string16& key_to_test_path, 149 REGSAM wow64_access, 150 const wchar_t* value_name, 151 const RegistryValuePredicate& predicate); 152 153 // Deletes the value |value_name| in the key |key_path| under |root_key| iff 154 // its current value satisfies |predicate|. |value_name| may be either NULL 155 // or an empty string to test/delete the key's default value. 156 static ConditionalDeleteResult DeleteRegistryValueIf( 157 HKEY root_key, 158 const wchar_t* key_path, 159 REGSAM wow64_access, 160 const wchar_t* value_name, 161 const RegistryValuePredicate& predicate); 162 163 // A predicate that performs a case-sensitive string comparison. 164 class ValueEquals : public RegistryValuePredicate { 165 public: 166 explicit ValueEquals(const base::string16& value_to_match) 167 : value_to_match_(value_to_match) { } 168 virtual bool Evaluate(const base::string16& value) const OVERRIDE; 169 protected: 170 base::string16 value_to_match_; 171 private: 172 DISALLOW_COPY_AND_ASSIGN(ValueEquals); 173 }; 174 175 // Returns zero on install success, or an InstallStatus value otherwise. 176 static int GetInstallReturnCode(installer::InstallStatus install_status); 177 178 // Composes |program| and |arguments| into |command_line|. 179 static void MakeUninstallCommand(const base::string16& program, 180 const base::string16& arguments, 181 base::CommandLine* command_line); 182 183 // Returns a string in the form YYYYMMDD of the current date. 184 static base::string16 GetCurrentDate(); 185 186 // A predicate that compares the program portion of a command line with a 187 // given file path. First, the file paths are compared directly. If they do 188 // not match, the filesystem is consulted to determine if the paths reference 189 // the same file. 190 class ProgramCompare : public RegistryValuePredicate { 191 public: 192 explicit ProgramCompare(const base::FilePath& path_to_match); 193 virtual ~ProgramCompare(); 194 virtual bool Evaluate(const base::string16& value) const OVERRIDE; 195 bool EvaluatePath(const base::FilePath& path) const; 196 197 protected: 198 static bool OpenForInfo(const base::FilePath& path, base::File* file); 199 static bool GetInfo(const base::File& file, 200 BY_HANDLE_FILE_INFORMATION* info); 201 202 base::FilePath path_to_match_; 203 base::File file_; 204 BY_HANDLE_FILE_INFORMATION file_info_; 205 206 private: 207 DISALLOW_COPY_AND_ASSIGN(ProgramCompare); 208 }; // class ProgramCompare 209 210 private: 211 DISALLOW_COPY_AND_ASSIGN(InstallUtil); 212 }; 213 214 215 #endif // CHROME_INSTALLER_UTIL_INSTALL_UTIL_H_ 216