install_util.h revision effb81e5f8246d0db0270817048dc992db66e9fb
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
24class WorkItemList;
25
26namespace base {
27class 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.
33class 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 the path to |file| in the sentinel directory for
113  // |dist|. Returns false on error.
114  static bool GetSentinelFilePath(const base::FilePath::CharType* file,
115                                  BrowserDistribution* dist,
116                                  base::FilePath* path);
117
118  // Deletes the registry key at path key_path under the key given by root_key.
119  static bool DeleteRegistryKey(HKEY root_key, const base::string16& key_path);
120
121  // Deletes the registry value named value_name at path key_path under the key
122  // given by reg_root.
123  static bool DeleteRegistryValue(HKEY reg_root, const base::string16& key_path,
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      const wchar_t* value_name,
150      const RegistryValuePredicate& predicate);
151
152  // Deletes the value |value_name| in the key |key_path| under |root_key| iff
153  // its current value satisfies |predicate|.  |value_name| may be either NULL
154  // or an empty string to test/delete the key's default value.
155  static ConditionalDeleteResult DeleteRegistryValueIf(
156      HKEY root_key,
157      const wchar_t* key_path,
158      const wchar_t* value_name,
159      const RegistryValuePredicate& predicate);
160
161  // A predicate that performs a case-sensitive string comparison.
162  class ValueEquals : public RegistryValuePredicate {
163   public:
164    explicit ValueEquals(const base::string16& value_to_match)
165        : value_to_match_(value_to_match) { }
166    virtual bool Evaluate(const base::string16& value) const OVERRIDE;
167   protected:
168    base::string16 value_to_match_;
169   private:
170    DISALLOW_COPY_AND_ASSIGN(ValueEquals);
171  };
172
173  // Returns zero on install success, or an InstallStatus value otherwise.
174  static int GetInstallReturnCode(installer::InstallStatus install_status);
175
176  // Composes |program| and |arguments| into |command_line|.
177  static void MakeUninstallCommand(const base::string16& program,
178                                   const base::string16& arguments,
179                                   base::CommandLine* command_line);
180
181  // Returns a string in the form YYYYMMDD of the current date.
182  static base::string16 GetCurrentDate();
183
184  // A predicate that compares the program portion of a command line with a
185  // given file path.  First, the file paths are compared directly.  If they do
186  // not match, the filesystem is consulted to determine if the paths reference
187  // the same file.
188  class ProgramCompare : public RegistryValuePredicate {
189   public:
190    explicit ProgramCompare(const base::FilePath& path_to_match);
191    virtual ~ProgramCompare();
192    virtual bool Evaluate(const base::string16& value) const OVERRIDE;
193    bool EvaluatePath(const base::FilePath& path) const;
194
195   protected:
196    static bool OpenForInfo(const base::FilePath& path, base::File* file);
197    static bool GetInfo(const base::File& file,
198                        BY_HANDLE_FILE_INFORMATION* info);
199
200    base::FilePath path_to_match_;
201    base::File file_;
202    BY_HANDLE_FILE_INFORMATION file_info_;
203
204   private:
205    DISALLOW_COPY_AND_ASSIGN(ProgramCompare);
206  };  // class ProgramCompare
207
208 private:
209  DISALLOW_COPY_AND_ASSIGN(InstallUtil);
210};
211
212
213#endif  // CHROME_INSTALLER_UTIL_INSTALL_UTIL_H_
214