diff options
author | gab@chromium.org <gab@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-05-31 19:25:35 +0000 |
---|---|---|
committer | gab@chromium.org <gab@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-05-31 19:25:35 +0000 |
commit | 0b8f24ee0f797709bc74370289c8717d4ad260ec (patch) | |
tree | 9fd87ef38905db244689b6880f0132191483733a /chrome/installer/util | |
parent | 72b88641d0b1f10147600f66b3d24a681211cb3e (diff) | |
download | chromium_src-0b8f24ee0f797709bc74370289c8717d4ad260ec.zip chromium_src-0b8f24ee0f797709bc74370289c8717d4ad260ec.tar.gz chromium_src-0b8f24ee0f797709bc74370289c8717d4ad260ec.tar.bz2 |
Move ProgramCompare from setup_util to install_util.
...and switch to oh so ever beautiful string16s.
BUG=None
TEST=setup_util_unittests
installer_util_unittests --gtest_filter=InstallUtilTest.ProgramCompare
Review URL: https://chromiumcodereview.appspot.com/10446095
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@139837 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/installer/util')
-rw-r--r-- | chrome/installer/util/install_util.cc | 106 | ||||
-rw-r--r-- | chrome/installer/util/install_util.h | 57 | ||||
-rw-r--r-- | chrome/installer/util/install_util_unittest.cc | 48 |
3 files changed, 176 insertions, 35 deletions
diff --git a/chrome/installer/util/install_util.cc b/chrome/installer/util/install_util.cc index 5f4e238..d61c0b9 100644 --- a/chrome/installer/util/install_util.cc +++ b/chrome/installer/util/install_util.cc @@ -179,7 +179,7 @@ Version* InstallUtil::GetChromeVersion(BrowserDistribution* dist, LONG result = key.Open(reg_root, dist->GetVersionKey().c_str(), KEY_QUERY_VALUE); - std::wstring version_str; + string16 version_str; if (result == ERROR_SUCCESS) result = key.ReadValue(google_update::kRegVersionField, &version_str); @@ -235,10 +235,10 @@ bool InstallUtil::IsOSSupported() { } void InstallUtil::AddInstallerResultItems(bool system_install, - const std::wstring& state_key, + const string16& state_key, installer::InstallStatus status, int string_resource_id, - const std::wstring* const launch_cmd, + const string16* const launch_cmd, WorkItemList* install_list) { DCHECK(install_list); const HKEY root = system_install ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; @@ -251,7 +251,7 @@ void InstallUtil::AddInstallerResultItems(bool system_install, installer::kInstallerError, static_cast<DWORD>(status), true); if (string_resource_id != 0) { - std::wstring msg = installer::GetLocalizedString(string_resource_id); + string16 msg = installer::GetLocalizedString(string_resource_id); install_list->AddSetRegValueWorkItem(root, state_key, installer::kInstallerResultUIString, msg, true); } @@ -262,7 +262,7 @@ void InstallUtil::AddInstallerResultItems(bool system_install, } void InstallUtil::UpdateInstallerStage(bool system_install, - const std::wstring& state_key_path, + const string16& state_key_path, installer::InstallerStage stage) { DCHECK_LE(static_cast<installer::InstallerStage>(0), stage); DCHECK_GT(installer::NUM_STAGES, stage); @@ -328,7 +328,7 @@ bool CheckIsChromeSxSProcess() { // Also return true if we are running from Chrome SxS installed path. FilePath exe_dir; PathService::Get(base::DIR_EXE, &exe_dir); - std::wstring chrome_sxs_dir(installer::kGoogleChromeInstallSubDir2); + string16 chrome_sxs_dir(installer::kGoogleChromeInstallSubDir2); chrome_sxs_dir.append(installer::kSxSSuffix); return FilePath::CompareEqualIgnoreCase(exe_dir.BaseName().value(), installer::kInstallBinaryDir) && @@ -363,7 +363,7 @@ bool InstallUtil::HasDelegateExecuteHandler(BrowserDistribution* dist, // in case of failure. It returns true if deletion is successful, // otherwise false. bool InstallUtil::DeleteRegistryKey(HKEY root_key, - const std::wstring& key_path) { + const string16& key_path) { VLOG(1) << "Deleting registry key " << key_path; LONG result = ::SHDeleteKey(root_key, key_path.c_str()); if (result != ERROR_SUCCESS && result != ERROR_FILE_NOT_FOUND) { @@ -378,8 +378,8 @@ bool InstallUtil::DeleteRegistryKey(HKEY root_key, // in case of failure. It returns true if deletion is successful, // otherwise false. bool InstallUtil::DeleteRegistryValue(HKEY reg_root, - const std::wstring& key_path, - const std::wstring& value_name) { + const string16& key_path, + const string16& value_name) { RegKey key(reg_root, key_path.c_str(), KEY_ALL_ACCESS); VLOG(1) << "Deleting registry value " << value_name; if (key.HasValue(value_name.c_str())) { @@ -396,15 +396,15 @@ bool InstallUtil::DeleteRegistryValue(HKEY reg_root, // static InstallUtil::ConditionalDeleteResult InstallUtil::DeleteRegistryKeyIf( HKEY root_key, - const std::wstring& key_to_delete_path, - const std::wstring& key_to_test_path, + const string16& key_to_delete_path, + const string16& key_to_test_path, const wchar_t* value_name, const RegistryValuePredicate& predicate) { DCHECK(root_key); DCHECK(value_name); ConditionalDeleteResult delete_result = NOT_FOUND; RegKey key; - std::wstring actual_value; + string16 actual_value; if (key.Open(root_key, key_to_test_path.c_str(), KEY_QUERY_VALUE) == ERROR_SUCCESS && key.ReadValue(value_name, &actual_value) == ERROR_SUCCESS && @@ -427,7 +427,7 @@ InstallUtil::ConditionalDeleteResult InstallUtil::DeleteRegistryValueIf( DCHECK(value_name); ConditionalDeleteResult delete_result = NOT_FOUND; RegKey key; - std::wstring actual_value; + string16 actual_value; if (key.Open(root_key, key_path, KEY_QUERY_VALUE | KEY_SET_VALUE) == ERROR_SUCCESS && key.ReadValue(value_name, &actual_value) == ERROR_SUCCESS && @@ -443,7 +443,7 @@ InstallUtil::ConditionalDeleteResult InstallUtil::DeleteRegistryValueIf( return delete_result; } -bool InstallUtil::ValueEquals::Evaluate(const std::wstring& value) const { +bool InstallUtil::ValueEquals::Evaluate(const string16& value) const { return value == value_to_match_; } @@ -461,13 +461,13 @@ int InstallUtil::GetInstallReturnCode(installer::InstallStatus status) { } // static -void InstallUtil::MakeUninstallCommand(const std::wstring& program, - const std::wstring& arguments, +void InstallUtil::MakeUninstallCommand(const string16& program, + const string16& arguments, CommandLine* command_line) { *command_line = CommandLine::FromString(L"\"" + program + L"\" " + arguments); } -std::wstring InstallUtil::GetCurrentDate() { +string16 InstallUtil::GetCurrentDate() { static const wchar_t kDateFormat[] = L"yyyyMMdd"; wchar_t date_str[arraysize(kDateFormat)] = {0}; int len = GetDateFormatW(LOCALE_INVARIANT, 0, NULL, kDateFormat, @@ -478,5 +478,75 @@ std::wstring InstallUtil::GetCurrentDate() { PLOG(DFATAL) << "GetDateFormat"; } - return std::wstring(date_str, len); + return string16(date_str, len); +} + +// Open |path| with minimal access to obtain information about it, returning +// true and populating |handle| on success. +// static +bool InstallUtil::ProgramCompare::OpenForInfo(const FilePath& path, + base::win::ScopedHandle* handle) { + DCHECK(handle); + handle->Set(base::CreatePlatformFile(path, base::PLATFORM_FILE_OPEN, NULL, + NULL)); + return handle->IsValid(); +} + +// Populate |info| for |handle|, returning true on success. +// static +bool InstallUtil::ProgramCompare::GetInfo(const base::win::ScopedHandle& handle, + BY_HANDLE_FILE_INFORMATION* info) { + DCHECK(handle.IsValid()); + return GetFileInformationByHandle( + const_cast<base::win::ScopedHandle&>(handle), info) != 0; +} + +InstallUtil::ProgramCompare::ProgramCompare(const FilePath& path_to_match) + : path_to_match_(path_to_match), + file_handle_(base::kInvalidPlatformFileValue), + file_info_() { + DCHECK(!path_to_match_.empty()); + if (!OpenForInfo(path_to_match_, &file_handle_)) { + PLOG(WARNING) << "Failed opening " << path_to_match_.value() + << "; falling back to path string comparisons."; + } else if (!GetInfo(file_handle_, &file_info_)) { + PLOG(WARNING) << "Failed getting information for " + << path_to_match_.value() + << "; falling back to path string comparisons."; + file_handle_.Close(); + } +} + +InstallUtil::ProgramCompare::~ProgramCompare() { +} + +bool InstallUtil::ProgramCompare::Evaluate(const string16& value) const { + // Suss out the exe portion of the value, which is expected to be a command + // line kinda (or exactly) like: + // "c:\foo\bar\chrome.exe" -- "%1" + FilePath program(CommandLine::FromString(value).GetProgram()); + if (program.empty()) { + LOG(WARNING) << "Failed to parse an executable name from command line: \"" + << value << "\""; + return false; + } + + // Try the simple thing first: do the paths happen to match? + if (FilePath::CompareEqualIgnoreCase(path_to_match_.value(), program.value())) + return true; + + // If the paths don't match and we couldn't open the expected file, we've done + // our best. + if (!file_handle_.IsValid()) + return false; + + // Open the program and see if it references the expected file. + base::win::ScopedHandle handle; + BY_HANDLE_FILE_INFORMATION info = {}; + + return (OpenForInfo(program, &handle) && + GetInfo(handle, &info) && + info.dwVolumeSerialNumber == file_info_.dwVolumeSerialNumber && + info.nFileIndexHigh == file_info_.nFileIndexHigh && + info.nFileIndexLow == file_info_.nFileIndexLow); } diff --git a/chrome/installer/util/install_util.h b/chrome/installer/util/install_util.h index 5c4cb26..682290f 100644 --- a/chrome/installer/util/install_util.h +++ b/chrome/installer/util/install_util.h @@ -12,10 +12,11 @@ #include <tchar.h> #include <windows.h> -#include <string> #include "base/basictypes.h" #include "base/command_line.h" +#include "base/string16.h" +#include "base/win/scoped_handle.h" #include "chrome/installer/util/browser_distribution.h" #include "chrome/installer/util/util_constants.h" @@ -62,17 +63,17 @@ class InstallUtil { // app's ClientState key. See InstallerState::WriteInstallerResult for more // details. static void AddInstallerResultItems(bool system_install, - const std::wstring& state_key, + const string16& state_key, installer::InstallStatus status, int string_resource_id, - const std::wstring* const launch_cmd, + 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 std::wstring& state_key_path, + const string16& state_key_path, installer::InstallerStage stage); // Returns true if this installation path is per user, otherwise returns @@ -96,19 +97,19 @@ class InstallUtil { const string16& chrome_exe); // Deletes the registry key at path key_path under the key given by root_key. - static bool DeleteRegistryKey(HKEY root_key, const std::wstring& key_path); + 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 std::wstring& key_path, - const std::wstring& value_name); + 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 std::wstring& value) const = 0; + virtual bool Evaluate(const string16& value) const = 0; }; // The result of a conditional delete operation (i.e., DeleteFOOIf). @@ -124,8 +125,8 @@ class InstallUtil { // default value. static ConditionalDeleteResult DeleteRegistryKeyIf( HKEY root_key, - const std::wstring& key_to_delete_path, - const std::wstring& key_to_test_path, + const string16& key_to_delete_path, + const string16& key_to_test_path, const wchar_t* value_name, const RegistryValuePredicate& predicate); @@ -141,11 +142,11 @@ class InstallUtil { // A predicate that performs a case-sensitive string comparison. class ValueEquals : public RegistryValuePredicate { public: - explicit ValueEquals(const std::wstring& value_to_match) + explicit ValueEquals(const string16& value_to_match) : value_to_match_(value_to_match) { } - virtual bool Evaluate(const std::wstring& value) const OVERRIDE; + virtual bool Evaluate(const string16& value) const OVERRIDE; protected: - std::wstring value_to_match_; + string16 value_to_match_; private: DISALLOW_COPY_AND_ASSIGN(ValueEquals); }; @@ -154,12 +155,36 @@ class InstallUtil { static int GetInstallReturnCode(installer::InstallStatus install_status); // Composes |program| and |arguments| into |command_line|. - static void MakeUninstallCommand(const std::wstring& program, - const std::wstring& arguments, + static void MakeUninstallCommand(const string16& program, + const string16& arguments, CommandLine* command_line); // Returns a string in the form YYYYMMDD of the current date. - static std::wstring GetCurrentDate(); + 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 FilePath& path_to_match); + virtual ~ProgramCompare(); + virtual bool Evaluate(const string16& value) const OVERRIDE; + + protected: + static bool OpenForInfo(const FilePath& path, + base::win::ScopedHandle* handle); + static bool GetInfo(const base::win::ScopedHandle& handle, + BY_HANDLE_FILE_INFORMATION* info); + + 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); diff --git a/chrome/installer/util/install_util_unittest.cc b/chrome/installer/util/install_util_unittest.cc index ef0c39b..89c870d 100644 --- a/chrome/installer/util/install_util_unittest.cc +++ b/chrome/installer/util/install_util_unittest.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// 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. @@ -6,6 +6,7 @@ #include <utility> #include "base/command_line.h" +#include "base/string_util.h" #include "base/test/test_reg_util_win.h" #include "base/win/registry.h" #include "chrome/installer/util/google_update_constants.h" @@ -356,3 +357,48 @@ TEST_F(InstallUtilTest, ValueEquals) { EXPECT_FALSE(pred.Evaluate(L"!howdy")); EXPECT_TRUE(pred.Evaluate(L"howdy")); } + +TEST_F(InstallUtilTest, ProgramCompare) { + FilePath some_long_dir(test_dir_.path().Append(L"Some Long Directory Name")); + FilePath expect(some_long_dir.Append(L"file.txt")); + FilePath expect_upcase(some_long_dir.Append(L"FILE.txt")); + FilePath other(some_long_dir.Append(L"otherfile.txt")); + + // Tests where the expected file doesn't exist. + + // Paths don't match. + EXPECT_FALSE(InstallUtil::ProgramCompare(expect).Evaluate( + L"\"" + other.value() + L"\"")); + // Paths match exactly. + EXPECT_TRUE(InstallUtil::ProgramCompare(expect).Evaluate( + L"\"" + expect.value() + L"\"")); + // Paths differ by case. + EXPECT_TRUE(InstallUtil::ProgramCompare(expect).Evaluate( + L"\"" + expect_upcase.value() + L"\"")); + + // Tests where the expected file exists. + static const char data[] = "data"; + ASSERT_TRUE(file_util::CreateDirectory(some_long_dir)); + ASSERT_NE(-1, file_util::WriteFile(expect, data, arraysize(data) - 1)); + // Paths don't match. + EXPECT_FALSE(InstallUtil::ProgramCompare(expect).Evaluate( + L"\"" + other.value() + L"\"")); + // Paths match exactly. + EXPECT_TRUE(InstallUtil::ProgramCompare(expect).Evaluate( + L"\"" + expect.value() + L"\"")); + // Paths differ by case. + EXPECT_TRUE(InstallUtil::ProgramCompare(expect).Evaluate( + L"\"" + expect_upcase.value() + L"\"")); + + // Test where strings don't match, but the same file is indicated. + std::wstring short_expect; + DWORD short_len = GetShortPathName(expect.value().c_str(), + WriteInto(&short_expect, MAX_PATH), + MAX_PATH); + ASSERT_NE(static_cast<DWORD>(0), short_len); + ASSERT_GT(static_cast<DWORD>(MAX_PATH), short_len); + short_expect.resize(short_len); + ASSERT_FALSE(FilePath::CompareEqualIgnoreCase(expect.value(), short_expect)); + EXPECT_TRUE(InstallUtil::ProgramCompare(expect).Evaluate( + L"\"" + short_expect + L"\"")); +} |