Chromium Code Reviews| Index: chrome/browser/importer/ie_importer_test_registry_overrider_win.cc |
| diff --git a/chrome/browser/importer/ie_importer_test_registry_overrider_win.cc b/chrome/browser/importer/ie_importer_test_registry_overrider_win.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..8375b0f4888a6a436c3c3375e566e725a37c5762 |
| --- /dev/null |
| +++ b/chrome/browser/importer/ie_importer_test_registry_overrider_win.cc |
| @@ -0,0 +1,135 @@ |
| +// Copyright (c) 2013 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. |
| + |
| +#include "chrome/browser/importer/ie_importer_test_registry_overrider_win.h" |
| + |
| +#include <windows.h> |
| + |
| +#include <string> |
| + |
| +#include "base/environment.h" |
| +#include "base/guid.h" |
| +#include "base/memory/scoped_ptr.h" |
| +#include "base/strings/string_number_conversions.h" |
| +#include "base/utf_string_conversions.h" |
| +#include "base/win/registry.h" |
| + |
| +namespace { |
| + |
| +// The key to which a random subkey will be appended. This key itself will never |
| +// be deleted. |
| +const wchar_t kTestHKCUOverrideKey[] = L"SOFTWARE\\Chromium Unit Tests"; |
| +const char kTestHKCUOverrideEnvironmentVariable[] = |
| + "IE_IMPORTER_TEST_OVERRIDE_HKCU"; |
| + |
| +base::string16 GetTestKeyFromSubKey(const base::string16& subkey) { |
| + base::string16 key(kTestHKCUOverrideKey); |
| + key.push_back(L'\\'); |
| + key.append(subkey); |
| + return key; |
| +} |
| + |
| +bool GetSubKeyFromEnvironment(base::string16* subkey) { |
| + scoped_ptr<base::Environment> env(base::Environment::Create()); |
| + std::string value; |
| + bool result = env->GetVar(kTestHKCUOverrideEnvironmentVariable, &value); |
| + if (result && subkey) |
| + *subkey = UTF8ToUTF16(value); |
| + return result; |
| +} |
| + |
| +} // namespace |
| + |
| +//////////////////////////////////////////////////////////////////////////////// |
| +// IEImporterTestRegistryOverrider, public: |
| + |
| +IEImporterTestRegistryOverrider::IEImporterTestRegistryOverrider() |
| + : override_performed_(false), override_initiated_(false) { |
| +} |
| + |
| +IEImporterTestRegistryOverrider::~IEImporterTestRegistryOverrider() { |
| + base::AutoLock auto_lock(lock_.Get()); |
| + if (override_performed_) { |
| + override_active_in_process_ = false; |
| + |
| + DWORD result = RegOverridePredefKey(HKEY_CURRENT_USER, NULL); |
| + DLOG_IF(ERROR, result != ERROR_SUCCESS) |
| + << "Failed to unset current override"; |
| + |
| + if (override_initiated_) { |
| + base::string16 subkey; |
| + if (!GetSubKeyFromEnvironment(&subkey)) { |
| + NOTREACHED(); |
| + } else { |
| + base::string16 key(GetTestKeyFromSubKey(subkey)); |
| + base::win::RegKey reg_key(HKEY_CURRENT_USER, key.c_str(), |
| + KEY_ALL_ACCESS); |
| + DCHECK(reg_key.Valid()); |
| + reg_key.DeleteKey(L""); |
| + } |
| + |
| + scoped_ptr<base::Environment> env(base::Environment::Create()); |
| + env->UnSetVar(kTestHKCUOverrideEnvironmentVariable); |
| + } |
| + } |
| +} |
| + |
| +bool IEImporterTestRegistryOverrider::SetRegistryOverride() { |
| + base::AutoLock auto_lock(lock_.Get()); |
| + DCHECK(!GetSubKeyFromEnvironment(NULL)); |
| + override_initiated_ = true; |
| + scoped_ptr<base::Environment> env(base::Environment::Create()); |
| + const base::string16 random_subkey(UTF8ToUTF16(base::GenerateGUID())); |
| + return StartRegistryOverride(random_subkey) && |
| + env->SetVar(kTestHKCUOverrideEnvironmentVariable, |
| + UTF16ToUTF8(random_subkey)); |
| +} |
| + |
| +bool IEImporterTestRegistryOverrider::StartRegistryOverrideIfNeeded() { |
| + base::string16 subkey; |
| + if (!GetSubKeyFromEnvironment(&subkey)) |
|
robertshield
2013/05/03 13:52:37
why is it safe to not have this line protected by
gab
2013/05/03 14:49:10
Done.
|
| + return true; |
| + |
| + base::AutoLock auto_lock(lock_.Get()); |
| + return StartRegistryOverride(subkey); |
| +} |
| + |
| +//////////////////////////////////////////////////////////////////////////////// |
| +// IEImporterTestRegistryOverrider, private: |
| + |
| +bool IEImporterTestRegistryOverrider::StartRegistryOverride( |
| + const base::string16& subkey) { |
| + lock_.Get().AssertAcquired(); |
| + // Override the registry whether |override_active_in_process_| or not as some |
|
robertshield
2013/05/03 13:52:37
It seems like it would be better to allow only a s
gab
2013/05/03 14:49:10
Not doing this as per F2F discussion.
|
| + // Windows API calls seem to reset the override. However, make sure to undo |
|
robertshield
2013/05/03 13:52:37
which API calls reset the override? If the overrid
gab
2013/05/03 14:49:10
Seems to be IUrlHistoryStg2::AddUrl (as per the co
|
| + // any existing override as this method will otherwise generate a fake key |
| + // within the current fake key. |
| + DWORD result = RegOverridePredefKey(HKEY_CURRENT_USER, NULL); |
| + DLOG_IF(ERROR, result != ERROR_SUCCESS) << "Failed to unset current override"; |
| + |
| + const base::string16 key(GetTestKeyFromSubKey(subkey)); |
| + base::win::RegKey temp_hkcu_hive_key; |
| + result = temp_hkcu_hive_key.Create(HKEY_CURRENT_USER, key.c_str(), |
| + KEY_ALL_ACCESS); |
| + if (result != ERROR_SUCCESS || !temp_hkcu_hive_key.Valid()) { |
| + DPLOG(ERROR) << result; |
| + return false; |
| + } |
| + |
| + if (!override_active_in_process_) { |
| + // Only take ownership of the override if it wasn't already set in this |
| + // process. |
| + override_performed_ = true; |
| + override_active_in_process_ = true; |
| + } |
| + return RegOverridePredefKey(HKEY_CURRENT_USER, |
| + temp_hkcu_hive_key.Handle()) == ERROR_SUCCESS; |
| +} |
| + |
| +// static |
| +bool IEImporterTestRegistryOverrider::override_active_in_process_ = false; |
| + |
| +// static |
| +base::LazyInstance<base::Lock>::Leaky IEImporterTestRegistryOverrider::lock_ = |
| + LAZY_INSTANCE_INITIALIZER; |