diff options
-rw-r--r-- | chrome/browser/rlz/rlz_unittest.cc | 74 | ||||
-rw-r--r-- | chrome/chrome_tests_unit.gypi | 1 | ||||
-rw-r--r-- | rlz/lib/rlz_lib.h | 16 | ||||
-rw-r--r-- | rlz/rlz.gyp | 18 | ||||
-rw-r--r-- | rlz/test/rlz_test_helpers.cc | 139 | ||||
-rw-r--r-- | rlz/test/rlz_test_helpers.h | 13 | ||||
-rw-r--r-- | rlz/win/dll/exports.cc | 2 | ||||
-rw-r--r-- | rlz/win/lib/machine_deal.h | 2 | ||||
-rw-r--r-- | rlz/win/lib/rlz_lib.h | 56 | ||||
-rw-r--r-- | rlz/win/lib/rlz_lib_win.cc | 53 |
10 files changed, 152 insertions, 222 deletions
diff --git a/chrome/browser/rlz/rlz_unittest.cc b/chrome/browser/rlz/rlz_unittest.cc index 0726ce2..198c62a 100644 --- a/chrome/browser/rlz/rlz_unittest.cc +++ b/chrome/browser/rlz/rlz_unittest.cc @@ -4,32 +4,23 @@ #include "chrome/browser/rlz/rlz.h" -#include "base/files/scoped_temp_dir.h" #include "base/memory/scoped_ptr.h" -#include "base/message_loop/message_loop.h" -#include "base/path_service.h" -#include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" -#include "base/threading/thread.h" #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/google/google_util.h" #include "chrome/browser/omnibox/omnibox_log.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/common/env_vars.h" #include "chrome/installer/util/browser_distribution.h" #include "chrome/installer/util/google_update_constants.h" #include "content/public/browser/navigation_entry.h" #include "content/public/browser/notification_details.h" #include "content/public/browser/notification_service.h" #include "content/public/browser/notification_source.h" +#include "rlz/test/rlz_test_helpers.h" #include "testing/gtest/include/gtest/gtest.h" #if defined(OS_WIN) -#include "base/test/test_reg_util_win.h" #include "base/win/registry.h" -#include "rlz/win/lib/rlz_lib.h" // InitializeTempHivesForTesting -#elif defined(OS_POSIX) -#include "rlz/lib/rlz_value_store.h" // SetRlzStoreDirectory #endif using content::NavigationEntry; @@ -39,17 +30,10 @@ using testing::AssertionFailure; #if defined(OS_WIN) using base::win::RegKey; -using registry_util::RegistryOverrideManager; #endif namespace { -#if defined(OS_WIN) -// Registry path to overridden hive. -const wchar_t kRlzTempHkcu[] = L"rlz_hkcu"; -const wchar_t kRlzTempHklm[] = L"rlz_hklm"; -#endif - // Dummy RLZ string for the access points. const char kOmniboxRlzString[] = "test_omnibox"; const char kHomepageRlzString[] = "test_homepage"; @@ -170,12 +154,10 @@ class TestRLZTracker : public RLZTracker { DISALLOW_COPY_AND_ASSIGN(TestRLZTracker); }; -class RlzLibTest : public testing::Test { - public: +class RlzLibTest : public RlzLibTestNoMachineState { + protected: virtual void SetUp() OVERRIDE; - virtual void TearDown() OVERRIDE; - protected: void SetMainBrand(const char* brand); void SetReactivationBrand(const char* brand); #if defined(OS_WIN) @@ -191,52 +173,13 @@ class RlzLibTest : public testing::Test { void ExpectReactivationRlzPingSent(bool expected); TestRLZTracker tracker_; -#if defined(OS_WIN) - RegistryOverrideManager override_manager_; -#elif defined(OS_POSIX) - base::ScopedTempDir temp_dir_; +#if defined(OS_POSIX) scoped_ptr<google_util::BrandForTesting> brand_override_; #endif }; void RlzLibTest::SetUp() { - testing::Test::SetUp(); - -#if defined(OS_WIN) - // Before overriding HKLM for the tests, we need to set it up correctly - // so that the rlz_lib calls work. This needs to be done before we do the - // override. - - string16 temp_hklm_path = base::StringPrintf( - L"%ls\\%ls", - RegistryOverrideManager::kTempTestKeyPath, - kRlzTempHklm); - - base::win::RegKey hklm; - ASSERT_EQ(ERROR_SUCCESS, hklm.Create(HKEY_CURRENT_USER, - temp_hklm_path.c_str(), - KEY_READ)); - - string16 temp_hkcu_path = base::StringPrintf( - L"%ls\\%ls", - RegistryOverrideManager::kTempTestKeyPath, - kRlzTempHkcu); - - base::win::RegKey hkcu; - ASSERT_EQ(ERROR_SUCCESS, hkcu.Create(HKEY_CURRENT_USER, - temp_hkcu_path.c_str(), - KEY_READ)); - - rlz_lib::InitializeTempHivesForTesting(hklm, hkcu); - - // Its important to override HKLM before HKCU because of the registry - // initialization performed above. - override_manager_.OverrideRegistry(HKEY_LOCAL_MACHINE, kRlzTempHklm); - override_manager_.OverrideRegistry(HKEY_CURRENT_USER, kRlzTempHkcu); -#elif defined(OS_POSIX) - ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); - rlz_lib::testing::SetRlzStoreDirectory(temp_dir_.path()); -#endif + RlzLibTestNoMachineState::SetUp(); // Make sure a non-organic brand code is set in the registry or the RLZTracker // is pretty much a no-op. @@ -244,13 +187,6 @@ void RlzLibTest::SetUp() { SetReactivationBrand(""); } -void RlzLibTest::TearDown() { -#if defined(OS_POSIX) - rlz_lib::testing::SetRlzStoreDirectory(base::FilePath()); -#endif - testing::Test::TearDown(); -} - void RlzLibTest::SetMainBrand(const char* brand) { #if defined(OS_WIN) SetRegistryBrandValue(google_update::kRegRLZBrandField, brand); diff --git a/chrome/chrome_tests_unit.gypi b/chrome/chrome_tests_unit.gypi index 1b4fd467..ca3b88f 100644 --- a/chrome/chrome_tests_unit.gypi +++ b/chrome/chrome_tests_unit.gypi @@ -472,6 +472,7 @@ '../content/content.gyp:content_app_both', '../net/net.gyp:net', '../net/net.gyp:net_test_support', + '../rlz/rlz.gyp:test_support_rlz', '../sync/sync.gyp:test_support_sync_api', '../sync/sync.gyp:test_support_sync_core', '../sync/sync.gyp:test_support_sync_internal_api', diff --git a/rlz/lib/rlz_lib.h b/rlz/lib/rlz_lib.h index 1f8be5c..6e3f451 100644 --- a/rlz/lib/rlz_lib.h +++ b/rlz/lib/rlz_lib.h @@ -52,6 +52,22 @@ class URLRequestContextGetter; namespace rlz_lib { +// All functions return true on success and false on error. +// This implemenation is thread safe. +// +// Each prototype mentions the registry access requirements: +// +// HKLM read: Will work from any process and at any privilege level on Vista. +// HKCU read: Calls made from the SYSTEM account must pass the current user's +// SID as the optional 'sid' param. Can be called from low integrity +// process on Vista. +// HKCU write: Calls made from the SYSTEM account must pass the current user's +// SID as the optional 'sid' param. Calls require at least medium +// integrity on Vista (e.g. Toolbar will need to use their broker) +// HKLM write: Calls must be made from an account with admin rights. No SID +// need be passed when running as SYSTEM. +// Functions which do not access registry will be marked with "no restrictions". + class ScopedRlzValueStoreLock; // The maximum length of an access points RLZ in bytes. diff --git a/rlz/rlz.gyp b/rlz/rlz.gyp index 18637058..bd0fe23 100644 --- a/rlz/rlz.gyp +++ b/rlz/rlz.gyp @@ -68,7 +68,6 @@ 'win/lib/process_info.h', 'win/lib/registry_util.cc', 'win/lib/registry_util.h', - 'win/lib/rlz_lib.h', 'win/lib/rlz_lib_win.cc', 'win/lib/rlz_value_store_registry.cc', 'win/lib/rlz_value_store_registry.h', @@ -111,10 +110,25 @@ 'msvs_disabled_warnings': [ 4267, ], }, { + 'target_name': 'test_support_rlz', + 'type': 'static_library', + 'dependencies': [ + ':rlz_lib', + '../base/base.gyp:base', + '../base/base.gyp:test_support_base', + '../testing/gtest.gyp:gtest', + ], + 'sources': [ + 'test/rlz_test_helpers.cc', + 'test/rlz_test_helpers.h', + ], + }, + { 'target_name': 'rlz_unittests', 'type': 'executable', 'dependencies': [ ':rlz_lib', + ':test_support_rlz', '../base/base.gyp:base', '../base/base.gyp:base_prefs', '../testing/gmock.gyp:gmock', @@ -129,8 +143,6 @@ 'lib/machine_id_unittest.cc', 'lib/rlz_lib_test.cc', 'lib/string_utils_unittest.cc', - 'test/rlz_test_helpers.cc', - 'test/rlz_test_helpers.h', 'test/rlz_unittest_main.cc', 'win/lib/machine_deal_test.cc', ], diff --git a/rlz/test/rlz_test_helpers.cc b/rlz/test/rlz_test_helpers.cc index db34cd9..af08836 100644 --- a/rlz/test/rlz_test_helpers.cc +++ b/rlz/test/rlz_test_helpers.cc @@ -6,62 +6,129 @@ #include "rlz_test_helpers.h" +#include <map> +#include <vector> + +#include "base/strings/string16.h" #include "rlz/lib/rlz_lib.h" #include "testing/gtest/include/gtest/gtest.h" #if defined(OS_WIN) #include <shlwapi.h> #include "base/win/registry.h" -#include "rlz/win/lib/rlz_lib.h" +#include "base/win/windows_version.h" #elif defined(OS_POSIX) #include "base/files/file_path.h" #include "rlz/lib/rlz_value_store.h" #endif #if defined(OS_WIN) + namespace { -const wchar_t* kHKCUReplacement = L"Software\\Google\\RlzUtilUnittest\\HKCU"; -const wchar_t* kHKLMReplacement = L"Software\\Google\\RlzUtilUnittest\\HKLM"; - -void OverrideRegistryHives() { - // Wipe the keys we redirect to. - // This gives us a stable run, even in the presence of previous - // crashes or failures. - LSTATUS err = SHDeleteKey(HKEY_CURRENT_USER, kHKCUReplacement); - EXPECT_TRUE(err == ERROR_SUCCESS || err == ERROR_FILE_NOT_FOUND); - err = SHDeleteKey(HKEY_CURRENT_USER, kHKLMReplacement); - EXPECT_TRUE(err == ERROR_SUCCESS || err == ERROR_FILE_NOT_FOUND); - - // Create the keys we're redirecting HKCU and HKLM to. - base::win::RegKey hkcu; - base::win::RegKey hklm; - ASSERT_EQ(ERROR_SUCCESS, - hkcu.Create(HKEY_CURRENT_USER, kHKCUReplacement, KEY_READ)); - ASSERT_EQ(ERROR_SUCCESS, - hklm.Create(HKEY_CURRENT_USER, kHKLMReplacement, KEY_READ)); - - rlz_lib::InitializeTempHivesForTesting(hklm, hkcu); - - // And do the switcharoo. - ASSERT_EQ(ERROR_SUCCESS, - ::RegOverridePredefKey(HKEY_CURRENT_USER, hkcu.Handle())); - ASSERT_EQ(ERROR_SUCCESS, - ::RegOverridePredefKey(HKEY_LOCAL_MACHINE, hklm.Handle())); +// Path to recursively copy into the replacemment hives. These are needed +// to make sure certain win32 APIs continue to run correctly once the real +// hives are replaced. +const wchar_t kHKLMAccessProviders[] = + L"System\\CurrentControlSet\\Control\\Lsa\\AccessProviders"; + +struct RegistryValue { + string16 name; + DWORD type; + std::vector<uint8> data; +}; + +struct RegistryKeyData { + std::vector<RegistryValue> values; + std::map<string16, RegistryKeyData> keys; +}; + +void ReadRegistryTree(const base::win::RegKey& src, RegistryKeyData* data) { + // First read values. + { + base::win::RegistryValueIterator i(src.Handle(), L""); + data->values.clear(); + data->values.reserve(i.ValueCount()); + for (; i.Valid(); ++i) { + RegistryValue& value = *data->values.insert(data->values.end(), + RegistryValue()); + const uint8* data = reinterpret_cast<const uint8*>(i.Value()); + value.name.assign(i.Name()); + value.type = i.Type(); + value.data.assign(data, data + i.ValueSize()); + } + } + + // Next read subkeys recursively. + for (base::win::RegistryKeyIterator i(src.Handle(), L""); + i.Valid(); ++i) { + ReadRegistryTree(base::win::RegKey(src.Handle(), i.Name(), KEY_READ), + &data->keys[string16(i.Name())]); + } +} + +void WriteRegistryTree(const RegistryKeyData& data, base::win::RegKey* dest) { + // First write values. + for (size_t i = 0; i < data.values.size(); ++i) { + const RegistryValue& value = data.values[i]; + dest->WriteValue(value.name.c_str(), + value.data.size() ? &value.data[0] : NULL, + static_cast<DWORD>(value.data.size()), + value.type); + } + + // Next write values recursively. + for (std::map<string16, RegistryKeyData>::const_iterator iter = + data.keys.begin(); + iter != data.keys.end(); ++iter) { + WriteRegistryTree(iter->second, + &base::win::RegKey(dest->Handle(), iter->first.c_str(), + KEY_ALL_ACCESS)); + } } -void UndoOverrideRegistryHives() { - // Undo the redirection. - EXPECT_EQ(ERROR_SUCCESS, ::RegOverridePredefKey(HKEY_CURRENT_USER, NULL)); - EXPECT_EQ(ERROR_SUCCESS, ::RegOverridePredefKey(HKEY_LOCAL_MACHINE, NULL)); +// Initialize temporary HKLM/HKCU registry hives used for testing. +// Testing RLZ requires reading and writing to the Windows registry. To keep +// the tests isolated from the machine's state, as well as to prevent the tests +// from causing side effects in the registry, HKCU and HKLM are overridden for +// the duration of the tests. RLZ tests don't expect the HKCU and KHLM hives to +// be empty though, and this function initializes the minimum value needed so +// that the test will run successfully. +void InitializeRegistryOverridesForTesting( + registry_util::RegistryOverrideManager* override_manager) { + // For the moment, the HKCU hive requires no initialization. + const bool do_copy = (base::win::GetVersion() >= base::win::VERSION_WIN7); + RegistryKeyData data; + + if (do_copy) { + // Copy the following HKLM subtrees to the temporary location so that the + // win32 APIs used by the tests continue to work: + // + // HKLM\System\CurrentControlSet\Control\Lsa\AccessProviders + // + // This seems to be required since Win7. + ReadRegistryTree(base::win::RegKey(HKEY_LOCAL_MACHINE, + kHKLMAccessProviders, + KEY_READ), &data); + } + + override_manager->OverrideRegistry(HKEY_LOCAL_MACHINE, L"rlz_temp_hklm"); + override_manager->OverrideRegistry(HKEY_CURRENT_USER, L"rlz_temp_hkcu"); + + if (do_copy) { + WriteRegistryTree(data, &base::win::RegKey(HKEY_LOCAL_MACHINE, + kHKLMAccessProviders, + KEY_ALL_ACCESS)); + } } } // namespace + #endif // defined(OS_WIN) void RlzLibTestNoMachineState::SetUp() { #if defined(OS_WIN) - OverrideRegistryHives(); + InitializeRegistryOverridesForTesting(&override_manager_); #elif defined(OS_MACOSX) base::mac::ScopedNSAutoreleasePool pool; #endif // defined(OS_WIN) @@ -72,11 +139,9 @@ void RlzLibTestNoMachineState::SetUp() { } void RlzLibTestNoMachineState::TearDown() { -#if defined(OS_WIN) - UndoOverrideRegistryHives(); -#elif defined(OS_POSIX) +#if defined(OS_POSIX) rlz_lib::testing::SetRlzStoreDirectory(base::FilePath()); -#endif // defined(OS_WIN) +#endif // defined(OS_POSIX) } void RlzLibTestBase::SetUp() { diff --git a/rlz/test/rlz_test_helpers.h b/rlz/test/rlz_test_helpers.h index a78764f..ec067fe 100644 --- a/rlz/test/rlz_test_helpers.h +++ b/rlz/test/rlz_test_helpers.h @@ -14,20 +14,27 @@ #include "base/files/scoped_temp_dir.h" #endif +#if defined(OS_WIN) +#include "base/test/test_reg_util_win.h" +#endif + class RlzLibTestNoMachineState : public ::testing::Test { protected: virtual void SetUp() OVERRIDE; virtual void TearDown() OVERRIDE; - #if defined(OS_POSIX) - base::ScopedTempDir temp_dir_; + base::ScopedTempDir temp_dir_; +#endif + +#if defined(OS_WIN) + registry_util::RegistryOverrideManager override_manager_; #endif }; class RlzLibTestBase : public RlzLibTestNoMachineState { + protected: virtual void SetUp() OVERRIDE; }; - #endif // RLZ_TEST_RLZ_TEST_HELPERS_H diff --git a/rlz/win/dll/exports.cc b/rlz/win/dll/exports.cc index efe5cd98..eb7d88d 100644 --- a/rlz/win/dll/exports.cc +++ b/rlz/win/dll/exports.cc @@ -4,7 +4,7 @@ // // Functions exported by the RLZ DLL. -#include "rlz/win/lib/rlz_lib.h" +#include "rlz/lib/rlz_lib.h" #define RLZ_DLL_EXPORT extern "C" __declspec(dllexport) diff --git a/rlz/win/lib/machine_deal.h b/rlz/win/lib/machine_deal.h index 5b8b84a..b6156c4 100644 --- a/rlz/win/lib/machine_deal.h +++ b/rlz/win/lib/machine_deal.h @@ -8,7 +8,7 @@ #define RLZ_WIN_LIB_MACHINE_DEAL_H_ #include <string> -#include "rlz/win/lib/rlz_lib.h" +#include "rlz/lib/rlz_lib.h" namespace rlz_lib { diff --git a/rlz/win/lib/rlz_lib.h b/rlz/win/lib/rlz_lib.h deleted file mode 100644 index 3adbf97..0000000 --- a/rlz/win/lib/rlz_lib.h +++ /dev/null @@ -1,56 +0,0 @@ -// 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. -// -// A library to manage RLZ information for access-points shared -// across different client applications. -// -// All functions return true on success and false on error. -// This implemenation is thread safe. -// -// Each prototype mentions the registry access requirements: -// -// HKLM read: Will work from any process and at any privilege level on Vista. -// HKCU read: Calls made from the SYSTEM account must pass the current user's -// SID as the optional 'sid' param. Can be called from low integrity -// process on Vista. -// HKCU write: Calls made from the SYSTEM account must pass the current user's -// SID as the optional 'sid' param. Calls require at least medium -// integrity on Vista (e.g. Toolbar will need to use their broker) -// HKLM write: Calls must be made from an account with admin rights. No SID -// need be passed when running as SYSTEM. -// Functions which do not access registry will be marked with "no restrictions". - -#ifndef RLZ_WIN_LIB_RLZ_LIB_H_ -#define RLZ_WIN_LIB_RLZ_LIB_H_ - -// Clients can get away by just including rlz/lib/rlz_lib.h. This file only -// contains function definitions for files used by tests. It's mostly kept -// around for backwards-compatibility. - -#include "rlz/lib/rlz_lib.h" - -#include "base/win/registry.h" - -namespace rlz_lib { - -#if defined(OS_WIN) - -// Initialize temporary HKLM/HKCU registry hives used for testing. -// Testing RLZ requires reading and writing to the Windows registry. To keep -// the tests isolated from the machine's state, as well as to prevent the tests -// from causing side effects in the registry, HKCU and HKLM are overridden for -// the duration of the tests. RLZ tests don't expect the HKCU and KHLM hives to -// be empty though, and this function initializes the minimum value needed so -// that the test will run successfully. -// -// The two arguments to this function should be the keys that will represent -// the HKLM and HKCU registry hives during the tests. This function should be -// called *before* the hives are overridden. -void InitializeTempHivesForTesting(const base::win::RegKey& temp_hklm_key, - const base::win::RegKey& temp_hkcu_key); -#endif // defined(OS_WIN) - -} // namespace rlz_lib - -#endif // RLZ_WIN_LIB_RLZ_LIB_H_ diff --git a/rlz/win/lib/rlz_lib_win.cc b/rlz/win/lib/rlz_lib_win.cc index d8b1c1e..c765560 100644 --- a/rlz/win/lib/rlz_lib_win.cc +++ b/rlz/win/lib/rlz_lib_win.cc @@ -5,7 +5,7 @@ // A library to manage RLZ information for access-points shared // across different client applications. -#include "rlz/win/lib/rlz_lib.h" +#include "rlz/lib/rlz_lib.h" #include <windows.h> #include <aclapi.h> @@ -13,42 +13,11 @@ #include "base/basictypes.h" #include "base/win/registry.h" -#include "base/win/windows_version.h" #include "rlz/lib/assert.h" #include "rlz/lib/rlz_value_store.h" #include "rlz/win/lib/machine_deal.h" #include "rlz/win/lib/rlz_value_store_registry.h" -namespace { - -// Path to recursively copy into the replacemment hives. These are needed -// to make sure certain win32 APIs continue to run correctly once the real -// hives are replaced. -const wchar_t* kHKLMAccessProviders = - L"System\\CurrentControlSet\\Control\\Lsa\\AccessProviders"; - -// Helper functions - -void CopyRegistryTree(const base::win::RegKey& src, base::win::RegKey* dest) { - // First copy values. - for (base::win::RegistryValueIterator i(src.Handle(), L""); - i.Valid(); ++i) { - dest->WriteValue(i.Name(), reinterpret_cast<const void*>(i.Value()), - i.ValueSize(), i.Type()); - } - - // Next copy subkeys recursively. - for (base::win::RegistryKeyIterator i(src.Handle(), L""); - i.Valid(); ++i) { - base::win::RegKey subkey(dest->Handle(), i.Name(), KEY_ALL_ACCESS); - CopyRegistryTree(base::win::RegKey(src.Handle(), i.Name(), KEY_READ), - &subkey); - } -} - -} // namespace anonymous - - namespace rlz_lib { // OEM Deal confirmation storage functions. @@ -237,24 +206,4 @@ bool SetMachineDealCodeFromPingResponse(const char* response) { return MachineDealCode::SetFromPingResponse(response); } -void InitializeTempHivesForTesting(const base::win::RegKey& temp_hklm_key, - const base::win::RegKey& temp_hkcu_key) { - // For the moment, the HKCU hive requires no initialization. - - if (base::win::GetVersion() >= base::win::VERSION_WIN7) { - // Copy the following HKLM subtrees to the temporary location so that the - // win32 APIs used by the tests continue to work: - // - // HKLM\System\CurrentControlSet\Control\Lsa\AccessProviders - // - // This seems to be required since Win7. - base::win::RegKey dest(temp_hklm_key.Handle(), kHKLMAccessProviders, - KEY_ALL_ACCESS); - CopyRegistryTree(base::win::RegKey(HKEY_LOCAL_MACHINE, - kHKLMAccessProviders, - KEY_READ), - &dest); - } -} - } // namespace rlz_lib |