install_util.h revision c2e0dbddbe15c98d52c4786dac06cb8952a8ae6d
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This file declares utility functions for the installer. The original reason 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// for putting these functions in installer\util library is so that we can 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// separate out the critical logic and write unit tests for it. 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef CHROME_INSTALLER_UTIL_INSTALL_UTIL_H_ 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define CHROME_INSTALLER_UTIL_INSTALL_UTIL_H_ 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <windows.h> 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <tchar.h> 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h" 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/string16.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/scoped_handle.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/util/browser_distribution.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/util/util_constants.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class WorkItemList; 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace base { 26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class Version; 27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This is a utility class that provides common installation related 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// utility methods that can be used by installer and also unit tested 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// independently. 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class InstallUtil { 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get the path to this distribution's Active Setup registry entries. 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // e.g. Software\Microsoft\Active Setup\Installed Components\<dist_guid> 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static string16 GetActiveSetupPath(BrowserDistribution* dist); 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Attempts to trigger the command that would be run by Active Setup for a 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // system-level Chrome. For use only when system-level Chrome is installed. 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static void TriggerActiveSetupCommand(); 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Launches given exe as admin on Vista. 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static bool ExecuteExeAsAdmin(const CommandLine& cmd, DWORD* exit_code); 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Reads the uninstall command for Chromium from registry and returns it. 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If system_install is true the command is read from HKLM, otherwise 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // from HKCU. 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static CommandLine GetChromeUninstallCmd( 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool system_install, 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserDistribution::Type distribution_type); 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Find the version of Chrome installed on the system by checking the 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Google Update registry key. Fills |version| with the version or a 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // default-constructed Version if no version is found. 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // system_install: if true, looks for version number under the HKLM root, 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // otherwise looks under the HKCU. 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static void GetChromeVersion(BrowserDistribution* dist, 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool system_install, 59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Version* version); 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Find the last critical update (version) of Chrome. Fills |version| with the 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // version or a default-constructed Version if no version is found. A critical 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // update is a specially flagged version (by Google Update) that contains an 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // important security fix. 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // system_install: if true, looks for version number under the HKLM root, 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // otherwise looks under the HKCU. 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static void GetCriticalUpdateVersion(BrowserDistribution* dist, 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool system_install, 69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Version* version); 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This function checks if the current OS is supported for Chromium. 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static bool IsOSSupported(); 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Adds work items to |install_list|, which should be a 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // NoRollbackWorkItemList, to set installer error information in the registry 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // for consumption by Google Update. |state_key| must be the full path to an 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // app's ClientState key. See InstallerState::WriteInstallerResult for more 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // details. 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static void AddInstallerResultItems(bool system_install, 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const string16& state_key, 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) installer::InstallStatus status, 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int string_resource_id, 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const string16* const launch_cmd, 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WorkItemList* install_list); 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Update the installer stage reported by Google Update. |state_key_path| 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // should be obtained via the state_key method of an InstallerState instance 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // created before the machine state is modified by the installer. 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static void UpdateInstallerStage(bool system_install, 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const string16& state_key_path, 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) installer::InstallerStage stage); 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns true if this installation path is per user, otherwise returns 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // false (per machine install, meaning: the exe_path contains path to 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Program Files). 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static bool IsPerUserInstall(const wchar_t* const exe_path); 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns true if the installation represented by the pair of |dist| and 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |system_level| is a multi install. 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static bool IsMultiInstall(BrowserDistribution* dist, bool system_install); 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns true if this is running setup process for Chrome SxS (as 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // indicated by the presence of --chrome-sxs on the command line) or if this 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // is running Chrome process from the Chrome SxS installation (as indicated 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // by either --chrome-sxs or the executable path). 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static bool IsChromeSxSProcess(); 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Populates |path| with the path to |file| in the sentinel directory. This is 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the application directory for user-level installs, and the default user 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // data dir for system-level installs. Returns false on error. 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static bool GetSentinelFilePath(const base::FilePath::CharType* file, 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserDistribution* dist, 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath* path); 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Deletes the registry key at path key_path under the key given by root_key. 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static bool DeleteRegistryKey(HKEY root_key, const string16& key_path); 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Deletes the registry value named value_name at path key_path under the key 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // given by reg_root. 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static bool DeleteRegistryValue(HKEY reg_root, const string16& key_path, 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const string16& value_name); 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // An interface to a predicate function for use by DeleteRegistryKeyIf and 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // DeleteRegistryValueIf. 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) class RegistryValuePredicate { 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~RegistryValuePredicate() { } 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual bool Evaluate(const string16& value) const = 0; 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The result of a conditional delete operation (i.e., DeleteFOOIf). 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) enum ConditionalDeleteResult { 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOT_FOUND, // The condition was not satisfied. 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DELETED, // The condition was satisfied and the delete succeeded. 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DELETE_FAILED // The condition was satisfied but the delete failed. 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Deletes the key |key_to_delete_path| under |root_key| iff the value 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |value_name| in the key |key_to_test_path| under |root_key| satisfies 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |predicate|. |value_name| may be either NULL or an empty string to test 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the key's default value. 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static ConditionalDeleteResult DeleteRegistryKeyIf( 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HKEY root_key, 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const string16& key_to_delete_path, 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const string16& key_to_test_path, 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const wchar_t* value_name, 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const RegistryValuePredicate& predicate); 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Deletes the value |value_name| in the key |key_path| under |root_key| iff 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // its current value satisfies |predicate|. |value_name| may be either NULL 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // or an empty string to test/delete the key's default value. 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static ConditionalDeleteResult DeleteRegistryValueIf( 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HKEY root_key, 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const wchar_t* key_path, 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const wchar_t* value_name, 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const RegistryValuePredicate& predicate); 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // A predicate that performs a case-sensitive string comparison. 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) class ValueEquals : public RegistryValuePredicate { 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit ValueEquals(const string16& value_to_match) 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : value_to_match_(value_to_match) { } 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual bool Evaluate(const string16& value) const OVERRIDE; 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected: 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string16 value_to_match_; 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(ValueEquals); 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns zero on install success, or an InstallStatus value otherwise. 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static int GetInstallReturnCode(installer::InstallStatus install_status); 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Composes |program| and |arguments| into |command_line|. 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static void MakeUninstallCommand(const string16& program, 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const string16& arguments, 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CommandLine* command_line); 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns a string in the form YYYYMMDD of the current date. 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static string16 GetCurrentDate(); 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // A predicate that compares the program portion of a command line with a 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // given file path. First, the file paths are compared directly. If they do 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // not match, the filesystem is consulted to determine if the paths reference 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the same file. 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) class ProgramCompare : public RegistryValuePredicate { 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) explicit ProgramCompare(const base::FilePath& path_to_match); 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~ProgramCompare(); 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual bool Evaluate(const string16& value) const OVERRIDE; 1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool EvaluatePath(const base::FilePath& path) const; 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected: 1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static bool OpenForInfo(const base::FilePath& path, 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::win::ScopedHandle* handle); 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static bool GetInfo(const base::win::ScopedHandle& handle, 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BY_HANDLE_FILE_INFORMATION* info); 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath path_to_match_; 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::win::ScopedHandle file_handle_; 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BY_HANDLE_FILE_INFORMATION file_info_; 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(ProgramCompare); 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; // class ProgramCompare 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(InstallUtil); 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // CHROME_INSTALLER_UTIL_INSTALL_UTIL_H_ 212