// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// This file declares utility functions for the installer. The original reason
// for putting these functions in installer\util library is so that we can
// separate out the critical logic and write unit tests for it.
#ifndef CHROME_INSTALLER_UTIL_INSTALL_UTIL_H_
#define CHROME_INSTALLER_UTIL_INSTALL_UTIL_H_
#include <windows.h>
#include <tchar.h>
#include "base/basictypes.h"
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/strings/string16.h"
#include "base/win/scoped_handle.h"
#include "chrome/installer/util/browser_distribution.h"
#include "chrome/installer/util/util_constants.h"
class WorkItemList;
namespace base {
class Version;
}
// This is a utility class that provides common installation related
// utility methods that can be used by installer and also unit tested
// independently.
class InstallUtil {
public:
// Get the path to this distribution's Active Setup registry entries.
// e.g. Software\Microsoft\Active Setup\Installed Components\<dist_guid>
static string16 GetActiveSetupPath(BrowserDistribution* dist);
// Attempts to trigger the command that would be run by Active Setup for a
// system-level Chrome. For use only when system-level Chrome is installed.
static void TriggerActiveSetupCommand();
// Launches given exe as admin on Vista.
static bool ExecuteExeAsAdmin(const CommandLine& cmd, DWORD* exit_code);
// Reads the uninstall command for Chromium from registry and returns it.
// If system_install is true the command is read from HKLM, otherwise
// from HKCU.
static CommandLine GetChromeUninstallCmd(
bool system_install,
BrowserDistribution::Type distribution_type);
// Find the version of Chrome installed on the system by checking the
// Google Update registry key. Fills |version| with the version or a
// default-constructed Version if no version is found.
// system_install: if true, looks for version number under the HKLM root,
// otherwise looks under the HKCU.
static void GetChromeVersion(BrowserDistribution* dist,
bool system_install,
base::Version* version);
// Find the last critical update (version) of Chrome. Fills |version| with the
// version or a default-constructed Version if no version is found. A critical
// update is a specially flagged version (by Google Update) that contains an
// important security fix.
// system_install: if true, looks for version number under the HKLM root,
// otherwise looks under the HKCU.
static void GetCriticalUpdateVersion(BrowserDistribution* dist,
bool system_install,
base::Version* version);
// This function checks if the current OS is supported for Chromium.
static bool IsOSSupported();
// Adds work items to |install_list|, which should be a
// NoRollbackWorkItemList, to set installer error information in the registry
// for consumption by Google Update. |state_key| must be the full path to an
// app's ClientState key. See InstallerState::WriteInstallerResult for more
// details.
static void AddInstallerResultItems(bool system_install,
const string16& state_key,
installer::InstallStatus status,
int string_resource_id,
const string16* const launch_cmd,
WorkItemList* install_list);
// Update the installer stage reported by Google Update. |state_key_path|
// should be obtained via the state_key method of an InstallerState instance
// created before the machine state is modified by the installer.
static void UpdateInstallerStage(bool system_install,
const string16& state_key_path,
installer::InstallerStage stage);
// Returns true if this installation path is per user, otherwise returns
// false (per machine install, meaning: the exe_path contains path to
// Program Files).
static bool IsPerUserInstall(const wchar_t* const exe_path);
// Returns true if the installation represented by the pair of |dist| and
// |system_level| is a multi install.
static bool IsMultiInstall(BrowserDistribution* dist, bool system_install);
// Returns true if this is running setup process for Chrome SxS (as
// indicated by the presence of --chrome-sxs on the command line) or if this
// is running Chrome process from the Chrome SxS installation (as indicated
// by either --chrome-sxs or the executable path).
static bool IsChromeSxSProcess();
// Populates |path| with the path to |file| in the sentinel directory. This is
// the application directory for user-level installs, and the default user
// data dir for system-level installs. Returns false on error.
static bool GetSentinelFilePath(const base::FilePath::CharType* file,
BrowserDistribution* dist,
base::FilePath* path);
// Deletes the registry key at path key_path under the key given by root_key.
static bool DeleteRegistryKey(HKEY root_key, const string16& key_path);
// Deletes the registry value named value_name at path key_path under the key
// given by reg_root.
static bool DeleteRegistryValue(HKEY reg_root, const string16& key_path,
const string16& value_name);
// An interface to a predicate function for use by DeleteRegistryKeyIf and
// DeleteRegistryValueIf.
class RegistryValuePredicate {
public:
virtual ~RegistryValuePredicate() { }
virtual bool Evaluate(const string16& value) const = 0;
};
// The result of a conditional delete operation (i.e., DeleteFOOIf).
enum ConditionalDeleteResult {
NOT_FOUND, // The condition was not satisfied.
DELETED, // The condition was satisfied and the delete succeeded.
DELETE_FAILED // The condition was satisfied but the delete failed.
};
// Deletes the key |key_to_delete_path| under |root_key| iff the value
// |value_name| in the key |key_to_test_path| under |root_key| satisfies
// |predicate|. |value_name| may be either NULL or an empty string to test
// the key's default value.
static ConditionalDeleteResult DeleteRegistryKeyIf(
HKEY root_key,
const string16& key_to_delete_path,
const string16& key_to_test_path,
const wchar_t* value_name,
const RegistryValuePredicate& predicate);
// Deletes the value |value_name| in the key |key_path| under |root_key| iff
// its current value satisfies |predicate|. |value_name| may be either NULL
// or an empty string to test/delete the key's default value.
static ConditionalDeleteResult DeleteRegistryValueIf(
HKEY root_key,
const wchar_t* key_path,
const wchar_t* value_name,
const RegistryValuePredicate& predicate);
// A predicate that performs a case-sensitive string comparison.
class ValueEquals : public RegistryValuePredicate {
public:
explicit ValueEquals(const string16& value_to_match)
: value_to_match_(value_to_match) { }
virtual bool Evaluate(const string16& value) const OVERRIDE;
protected:
string16 value_to_match_;
private:
DISALLOW_COPY_AND_ASSIGN(ValueEquals);
};
// Returns zero on install success, or an InstallStatus value otherwise.
static int GetInstallReturnCode(installer::InstallStatus install_status);
// Composes |program| and |arguments| into |command_line|.
static void MakeUninstallCommand(const string16& program,
const string16& arguments,
CommandLine* command_line);
// Returns a string in the form YYYYMMDD of the current date.
static string16 GetCurrentDate();
// A predicate that compares the program portion of a command line with a
// given file path. First, the file paths are compared directly. If they do
// not match, the filesystem is consulted to determine if the paths reference
// the same file.
class ProgramCompare : public RegistryValuePredicate {
public:
explicit ProgramCompare(const base::FilePath& path_to_match);
virtual ~ProgramCompare();
virtual bool Evaluate(const string16& value) const OVERRIDE;
bool EvaluatePath(const base::FilePath& path) const;
protected:
static bool OpenForInfo(const base::FilePath& path,
base::win::ScopedHandle* handle);
static bool GetInfo(const base::win::ScopedHandle& handle,
BY_HANDLE_FILE_INFORMATION* info);
base::FilePath path_to_match_;
base::win::ScopedHandle file_handle_;
BY_HANDLE_FILE_INFORMATION file_info_;
private:
DISALLOW_COPY_AND_ASSIGN(ProgramCompare);
}; // class ProgramCompare
private:
DISALLOW_COPY_AND_ASSIGN(InstallUtil);
};
#endif // CHROME_INSTALLER_UTIL_INSTALL_UTIL_H_