Commit 4fe6ccad authored by dcheng's avatar dcheng Committed by Commit bot

Revert of Remove raw handles from base::win::RegKey (patchset #6 id:330001 of...

Revert of Remove raw handles from base::win::RegKey (patchset #6 id:330001 of https://codereview.chromium.org/632833002/)

Reason for revert:
Causing base_unittests failures on XP Tests (1)

Original issue's description:
> Remove raw handles from base::win::RegKey
>
> BUG=419210, 423634
> R=cpu@chromium.org, eroman@chromium.org, sky@chromium.org
>
> Committed: https://crrev.com/1aa0fa75b65f403e08ae0f3f2fcb053c02cd9ef2
> Cr-Commit-Position: refs/heads/master@{#299737}

TBR=cpu@chromium.org,eroman@chromium.org,jam@chromium.org,rvargas@chromium.org
NOTREECHECKS=true
NOTRY=true
BUG=419210, 423634

Review URL: https://codereview.chromium.org/652903005

Cr-Commit-Position: refs/heads/master@{#299828}
parent 5b154b85
...@@ -34,74 +34,23 @@ const REGSAM kWow64AccessMask = KEY_WOW64_32KEY | KEY_WOW64_64KEY; ...@@ -34,74 +34,23 @@ const REGSAM kWow64AccessMask = KEY_WOW64_32KEY | KEY_WOW64_64KEY;
} // namespace } // namespace
// Watches for modifications to a key.
class RegKey::Watcher : public ObjectWatcher::Delegate {
public:
explicit Watcher(RegKey* owner) : owner_(owner) {}
~Watcher() {}
bool StartWatching(HKEY key, const ChangeCallback& callback);
// Implementation of ObjectWatcher::Delegate.
void OnObjectSignaled(HANDLE object) override {
DCHECK(watch_event_.IsValid() && watch_event_.Get() == object);
ChangeCallback callback = callback_;
callback_.Reset();
callback.Run();
}
private:
RegKey* owner_;
ScopedHandle watch_event_;
ObjectWatcher object_watcher_;
ChangeCallback callback_;
DISALLOW_COPY_AND_ASSIGN(Watcher);
};
bool RegKey::Watcher::StartWatching(HKEY key, const ChangeCallback& callback) {
DCHECK(key);
DCHECK(callback_.is_null());
if (GetVersion() < VERSION_VISTA) {
// It is an error to register multiple times before Vista.
if (watch_event_.IsValid()) {
callback_ = callback;
return true;
}
}
if (!watch_event_.IsValid())
watch_event_.Set(CreateEvent(NULL, TRUE, FALSE, NULL));
if (!watch_event_.IsValid())
return false;
DWORD filter = REG_NOTIFY_CHANGE_NAME |
REG_NOTIFY_CHANGE_ATTRIBUTES |
REG_NOTIFY_CHANGE_LAST_SET |
REG_NOTIFY_CHANGE_SECURITY;
// Watch the registry key for a change of value.
LONG result = RegNotifyChangeKeyValue(key, TRUE, filter, watch_event_.Get(),
TRUE);
if (result != ERROR_SUCCESS) {
watch_event_.Close();
return false;
}
callback_ = callback;
return object_watcher_.StartWatching(watch_event_.Get(), this);
}
// RegKey ---------------------------------------------------------------------- // RegKey ----------------------------------------------------------------------
RegKey::RegKey() : key_(NULL), wow64access_(0) { RegKey::RegKey()
: key_(NULL),
watch_event_(0),
wow64access_(0) {
} }
RegKey::RegKey(HKEY key) : key_(key), wow64access_(0) { RegKey::RegKey(HKEY key)
: key_(key),
watch_event_(0),
wow64access_(0) {
} }
RegKey::RegKey(HKEY rootkey, const wchar_t* subkey, REGSAM access) RegKey::RegKey(HKEY rootkey, const wchar_t* subkey, REGSAM access)
: key_(NULL), : key_(NULL),
watch_event_(0),
wow64access_(0) { wow64access_(0) {
if (rootkey) { if (rootkey) {
if (access & (KEY_SET_VALUE | KEY_CREATE_SUB_KEY | KEY_CREATE_LINK)) if (access & (KEY_SET_VALUE | KEY_CREATE_SUB_KEY | KEY_CREATE_LINK))
...@@ -201,6 +150,7 @@ LONG RegKey::OpenKey(const wchar_t* relative_key_name, REGSAM access) { ...@@ -201,6 +150,7 @@ LONG RegKey::OpenKey(const wchar_t* relative_key_name, REGSAM access) {
} }
void RegKey::Close() { void RegKey::Close() {
StopWatching();
if (key_) { if (key_) {
::RegCloseKey(key_); ::RegCloseKey(key_);
key_ = NULL; key_ = NULL;
...@@ -218,6 +168,7 @@ void RegKey::Set(HKEY key) { ...@@ -218,6 +168,7 @@ void RegKey::Set(HKEY key) {
HKEY RegKey::Take() { HKEY RegKey::Take() {
DCHECK(wow64access_ == 0); DCHECK(wow64access_ == 0);
StopWatching();
HKEY key = key_; HKEY key = key_;
key_ = NULL; key_ = NULL;
return key; return key;
...@@ -416,14 +367,44 @@ LONG RegKey::WriteValue(const wchar_t* name, ...@@ -416,14 +367,44 @@ LONG RegKey::WriteValue(const wchar_t* name,
return result; return result;
} }
bool RegKey::StartWatching(const ChangeCallback& callback) { LONG RegKey::StartWatching() {
if (!key_watcher_) DCHECK(key_);
key_watcher_.reset(new Watcher(this)); if (!watch_event_)
watch_event_ = CreateEvent(NULL, TRUE, FALSE, NULL);
if (!key_watcher_.get()->StartWatching(key_, callback)) DWORD filter = REG_NOTIFY_CHANGE_NAME |
return false; REG_NOTIFY_CHANGE_ATTRIBUTES |
REG_NOTIFY_CHANGE_LAST_SET |
REG_NOTIFY_CHANGE_SECURITY;
return true; // Watch the registry key for a change of value.
LONG result = RegNotifyChangeKeyValue(key_, TRUE, filter, watch_event_, TRUE);
if (result != ERROR_SUCCESS) {
CloseHandle(watch_event_);
watch_event_ = 0;
}
return result;
}
bool RegKey::HasChanged() {
if (watch_event_) {
if (WaitForSingleObject(watch_event_, 0) == WAIT_OBJECT_0) {
StartWatching();
return true;
}
}
return false;
}
LONG RegKey::StopWatching() {
LONG result = ERROR_INVALID_HANDLE;
if (watch_event_) {
CloseHandle(watch_event_);
watch_event_ = 0;
result = ERROR_SUCCESS;
}
return result;
} }
// static // static
......
...@@ -12,8 +12,6 @@ ...@@ -12,8 +12,6 @@
#include "base/base_export.h" #include "base/base_export.h"
#include "base/basictypes.h" #include "base/basictypes.h"
#include "base/stl_util.h" #include "base/stl_util.h"
#include "base/win/object_watcher.h"
#include "base/win/scoped_handle.h"
namespace base { namespace base {
namespace win { namespace win {
...@@ -27,9 +25,6 @@ namespace win { ...@@ -27,9 +25,6 @@ namespace win {
// are not touched in case of failure. // are not touched in case of failure.
class BASE_EXPORT RegKey { class BASE_EXPORT RegKey {
public: public:
// Called from the MessageLoop when the key changes.
typedef base::Callback<void()> ChangeCallback;
RegKey(); RegKey();
explicit RegKey(HKEY key); explicit RegKey(HKEY key);
RegKey(HKEY rootkey, const wchar_t* subkey, REGSAM access); RegKey(HKEY rootkey, const wchar_t* subkey, REGSAM access);
...@@ -125,16 +120,22 @@ class BASE_EXPORT RegKey { ...@@ -125,16 +120,22 @@ class BASE_EXPORT RegKey {
// Starts watching the key to see if any of its values have changed. // Starts watching the key to see if any of its values have changed.
// The key must have been opened with the KEY_NOTIFY access privilege. // The key must have been opened with the KEY_NOTIFY access privilege.
// Returns true on success. LONG StartWatching();
// To stop watching, delete this RegKey object. To continue watching the
// object after the callback is invoked, call StartWatching again. // If StartWatching hasn't been called, always returns false.
bool StartWatching(const ChangeCallback& callback); // Otherwise, returns true if anything under the key has changed.
// This can't be const because the |watch_event_| may be refreshed.
bool HasChanged();
// Will automatically be called by destructor if not manually called
// beforehand. Returns true if it was watching, false otherwise.
LONG StopWatching();
inline bool IsWatching() const { return watch_event_ != 0; }
HANDLE watch_event() const { return watch_event_; }
HKEY Handle() const { return key_; } HKEY Handle() const { return key_; }
private: private:
class Watcher;
// Calls RegDeleteKeyEx on supported platforms, alternatively falls back to // Calls RegDeleteKeyEx on supported platforms, alternatively falls back to
// RegDeleteKey. // RegDeleteKey.
static LONG RegDeleteKeyExWrapper(HKEY hKey, static LONG RegDeleteKeyExWrapper(HKEY hKey,
...@@ -146,10 +147,9 @@ class BASE_EXPORT RegKey { ...@@ -146,10 +147,9 @@ class BASE_EXPORT RegKey {
static LONG RegDelRecurse(HKEY root_key, static LONG RegDelRecurse(HKEY root_key,
const std::wstring& name, const std::wstring& name,
REGSAM access); REGSAM access);
HKEY key_; // The registry key being iterated. HKEY key_; // The registry key being iterated.
HANDLE watch_event_;
REGSAM wow64access_; REGSAM wow64access_;
scoped_ptr<Watcher> key_watcher_;
DISALLOW_COPY_AND_ASSIGN(RegKey); DISALLOW_COPY_AND_ASSIGN(RegKey);
}; };
......
...@@ -7,10 +7,7 @@ ...@@ -7,10 +7,7 @@
#include <cstring> #include <cstring>
#include <vector> #include <vector>
#include "base/bind.h"
#include "base/compiler_specific.h" #include "base/compiler_specific.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/stl_util.h" #include "base/stl_util.h"
#include "base/win/windows_version.h" #include "base/win/windows_version.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
...@@ -352,68 +349,6 @@ TEST_F(RegistryTest, OpenSubKey) { ...@@ -352,68 +349,6 @@ TEST_F(RegistryTest, OpenSubKey) {
ASSERT_EQ(ERROR_SUCCESS, key.DeleteKey(L"foo")); ASSERT_EQ(ERROR_SUCCESS, key.DeleteKey(L"foo"));
} }
class TestChangeDelegate {
public:
TestChangeDelegate() : called_(false) {}
~TestChangeDelegate() {}
void OnKeyChanged() {
MessageLoop::current()->QuitWhenIdle();
called_ = true;
}
bool WasCalled() {
bool was_called = called_;
called_ = false;
return was_called;
}
private:
bool called_;
};
TEST_F(RegistryTest, ChangeCallback) {
RegKey key;
TestChangeDelegate delegate;
MessageLoop message_loop;
std::wstring foo_key(kRootKey);
foo_key += L"\\Foo";
ASSERT_EQ(ERROR_SUCCESS, key.Create(HKEY_CURRENT_USER, foo_key.c_str(),
KEY_READ));
ASSERT_TRUE(key.StartWatching(Bind(&TestChangeDelegate::OnKeyChanged,
Unretained(&delegate))));
EXPECT_FALSE(delegate.WasCalled());
// Make some change.
RegKey key2;
ASSERT_EQ(ERROR_SUCCESS, key2.Open(HKEY_CURRENT_USER, foo_key.c_str(),
KEY_READ | KEY_SET_VALUE));
ASSERT_TRUE(key2.Valid());
EXPECT_EQ(ERROR_SUCCESS, key2.WriteValue(L"name", L"data"));
// Allow delivery of the notification.
EXPECT_FALSE(delegate.WasCalled());
base::RunLoop().Run();
ASSERT_TRUE(delegate.WasCalled());
EXPECT_FALSE(delegate.WasCalled());
ASSERT_TRUE(key.StartWatching(Bind(&TestChangeDelegate::OnKeyChanged,
Unretained(&delegate))));
// Change something else.
EXPECT_EQ(ERROR_SUCCESS, key2.WriteValue(L"name2", L"data2"));
base::RunLoop().Run();
ASSERT_TRUE(delegate.WasCalled());
ASSERT_TRUE(key.StartWatching(Bind(&TestChangeDelegate::OnKeyChanged,
Unretained(&delegate))));
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(delegate.WasCalled());
}
} // namespace } // namespace
} // namespace win } // namespace win
......
...@@ -157,6 +157,15 @@ PluginServiceImpl::PluginServiceImpl() ...@@ -157,6 +157,15 @@ PluginServiceImpl::PluginServiceImpl()
} }
PluginServiceImpl::~PluginServiceImpl() { PluginServiceImpl::~PluginServiceImpl() {
#if defined(OS_WIN)
// Release the events since they're owned by RegKey, not WaitableEvent.
hkcu_watcher_.StopWatching();
hklm_watcher_.StopWatching();
if (hkcu_event_)
hkcu_event_->Release();
if (hklm_event_)
hklm_event_->Release();
#endif
// Make sure no plugin channel requests have been leaked. // Make sure no plugin channel requests have been leaked.
DCHECK(pending_plugin_clients_.empty()); DCHECK(pending_plugin_clients_.empty());
} }
...@@ -191,18 +200,24 @@ void PluginServiceImpl::StartWatchingPlugins() { ...@@ -191,18 +200,24 @@ void PluginServiceImpl::StartWatchingPlugins() {
if (hkcu_key_.Create(HKEY_CURRENT_USER, if (hkcu_key_.Create(HKEY_CURRENT_USER,
kRegistryMozillaPlugins, kRegistryMozillaPlugins,
KEY_NOTIFY) == ERROR_SUCCESS) { KEY_NOTIFY) == ERROR_SUCCESS) {
base::win::RegKey::ChangeCallback callback = if (hkcu_key_.StartWatching() == ERROR_SUCCESS) {
base::Bind(&PluginServiceImpl::OnKeyChanged, base::Unretained(this), hkcu_event_.reset(new base::WaitableEvent(hkcu_key_.watch_event()));
base::Unretained(&hkcu_key_)); base::WaitableEventWatcher::EventCallback callback =
hkcu_key_.StartWatching(callback); base::Bind(&PluginServiceImpl::OnWaitableEventSignaled,
base::Unretained(this));
hkcu_watcher_.StartWatching(hkcu_event_.get(), callback);
}
} }
if (hklm_key_.Create(HKEY_LOCAL_MACHINE, if (hklm_key_.Create(HKEY_LOCAL_MACHINE,
kRegistryMozillaPlugins, kRegistryMozillaPlugins,
KEY_NOTIFY) == ERROR_SUCCESS) { KEY_NOTIFY) == ERROR_SUCCESS) {
base::win::RegKey::ChangeCallback callback = if (hklm_key_.StartWatching() == ERROR_SUCCESS) {
base::Bind(&PluginServiceImpl::OnKeyChanged, base::Unretained(this), hklm_event_.reset(new base::WaitableEvent(hklm_key_.watch_event()));
base::Unretained(&hkcu_key_)); base::WaitableEventWatcher::EventCallback callback =
hklm_key_.StartWatching(callback); base::Bind(&PluginServiceImpl::OnWaitableEventSignaled,
base::Unretained(this));
hklm_watcher_.StartWatching(hklm_event_.get(), callback);
}
} }
#endif #endif
#if defined(OS_POSIX) && !defined(OS_OPENBSD) && !defined(OS_ANDROID) #if defined(OS_POSIX) && !defined(OS_OPENBSD) && !defined(OS_ANDROID)
...@@ -627,16 +642,22 @@ void PluginServiceImpl::GetPluginsOnIOThread( ...@@ -627,16 +642,22 @@ void PluginServiceImpl::GetPluginsOnIOThread(
} }
#endif #endif
void PluginServiceImpl::OnWaitableEventSignaled(
base::WaitableEvent* waitable_event) {
#if defined(OS_WIN) #if defined(OS_WIN)
void PluginServiceImpl::OnKeyChanged(base::win::RegKey* key) { if (waitable_event == hkcu_event_) {
key->StartWatching(base::Bind(&PluginServiceImpl::OnKeyChanged, hkcu_key_.StartWatching();
base::Unretained(this), } else {
base::Unretained(&hkcu_key_))); hklm_key_.StartWatching();
}
PluginList::Singleton()->RefreshPlugins(); PluginList::Singleton()->RefreshPlugins();
PurgePluginListCache(NULL, false); PurgePluginListCache(NULL, false);
} #else
// This event should only get signaled on a Windows machine.
NOTREACHED();
#endif // defined(OS_WIN) #endif // defined(OS_WIN)
}
void PluginServiceImpl::RegisterPepperPlugins() { void PluginServiceImpl::RegisterPepperPlugins() {
ComputePepperPluginList(&ppapi_plugins_); ComputePepperPluginList(&ppapi_plugins_);
......
...@@ -166,9 +166,7 @@ class CONTENT_EXPORT PluginServiceImpl ...@@ -166,9 +166,7 @@ class CONTENT_EXPORT PluginServiceImpl
PluginServiceImpl(); PluginServiceImpl();
virtual ~PluginServiceImpl(); virtual ~PluginServiceImpl();
#if defined(OS_WIN) void OnWaitableEventSignaled(base::WaitableEvent* waitable_event);
void OnKeyChanged(base::win::RegKey* key);
#endif
// Returns the plugin process host corresponding to the plugin process that // Returns the plugin process host corresponding to the plugin process that
// has been started by this service. Returns NULL if no process has been // has been started by this service. Returns NULL if no process has been
...@@ -226,6 +224,10 @@ class CONTENT_EXPORT PluginServiceImpl ...@@ -226,6 +224,10 @@ class CONTENT_EXPORT PluginServiceImpl
// Registry keys for getting notifications when new plugins are installed. // Registry keys for getting notifications when new plugins are installed.
base::win::RegKey hkcu_key_; base::win::RegKey hkcu_key_;
base::win::RegKey hklm_key_; base::win::RegKey hklm_key_;
scoped_ptr<base::WaitableEvent> hkcu_event_;
scoped_ptr<base::WaitableEvent> hklm_event_;
base::WaitableEventWatcher hkcu_watcher_;
base::WaitableEventWatcher hklm_watcher_;
#endif #endif
#if defined(OS_POSIX) && !defined(OS_OPENBSD) && !defined(OS_ANDROID) #if defined(OS_POSIX) && !defined(OS_OPENBSD) && !defined(OS_ANDROID)
......
...@@ -23,8 +23,8 @@ ...@@ -23,8 +23,8 @@
#include "base/threading/non_thread_safe.h" #include "base/threading/non_thread_safe.h"
#include "base/threading/thread_restrictions.h" #include "base/threading/thread_restrictions.h"
#include "base/time/time.h" #include "base/time/time.h"
#include "base/win/object_watcher.h"
#include "base/win/registry.h" #include "base/win/registry.h"
#include "base/win/scoped_handle.h"
#include "base/win/windows_version.h" #include "base/win/windows_version.h"
#include "net/base/net_util.h" #include "net/base/net_util.h"
#include "net/base/network_change_notifier.h" #include "net/base/network_change_notifier.h"
...@@ -292,7 +292,8 @@ HostsParseWinResult AddLocalhostEntries(DnsHosts* hosts) { ...@@ -292,7 +292,8 @@ HostsParseWinResult AddLocalhostEntries(DnsHosts* hosts) {
} }
// Watches a single registry key for changes. // Watches a single registry key for changes.
class RegistryWatcher : public base::NonThreadSafe { class RegistryWatcher : public base::win::ObjectWatcher::Delegate,
public base::NonThreadSafe {
public: public:
typedef base::Callback<void(bool succeeded)> CallbackType; typedef base::Callback<void(bool succeeded)> CallbackType;
RegistryWatcher() {} RegistryWatcher() {}
...@@ -304,31 +305,35 @@ class RegistryWatcher : public base::NonThreadSafe { ...@@ -304,31 +305,35 @@ class RegistryWatcher : public base::NonThreadSafe {
callback_ = callback; callback_ = callback;
if (key_.Open(HKEY_LOCAL_MACHINE, key, KEY_NOTIFY) != ERROR_SUCCESS) if (key_.Open(HKEY_LOCAL_MACHINE, key, KEY_NOTIFY) != ERROR_SUCCESS)
return false; return false;
if (key_.StartWatching() != ERROR_SUCCESS)
return key_.StartWatching(base::Bind(&RegistryWatcher::OnObjectSignaled, return false;
base::Unretained(this))); if (!watcher_.StartWatching(key_.watch_event(), this))
return false;
return true;
} }
void OnObjectSignaled() { virtual void OnObjectSignaled(HANDLE object) override {
// TODO(vadimt): Remove ScopedProfile below once crbug.com/418183 is fixed. // TODO(vadimt): Remove ScopedProfile below once crbug.com/418183 is fixed.
tracked_objects::ScopedProfile tracking_profile( tracked_objects::ScopedProfile tracking_profile(
FROM_HERE_WITH_EXPLICIT_FUNCTION( FROM_HERE_WITH_EXPLICIT_FUNCTION(
"RegistryWatcher_OnObjectSignaled")); "RegistryWatcher_OnObjectSignaled"));
DCHECK(CalledOnValidThread()); DCHECK(CalledOnValidThread());
DCHECK(!callback_.is_null()); bool succeeded = (key_.StartWatching() == ERROR_SUCCESS) &&
if (key_.StartWatching(base::Bind(&RegistryWatcher::OnObjectSignaled, watcher_.StartWatching(key_.watch_event(), this);
base::Unretained(this)))) { if (!succeeded && key_.Valid()) {
callback_.Run(true); watcher_.StopWatching();
} else { key_.StopWatching();
key_.Close(); key_.Close();
callback_.Run(false);
} }
if (!callback_.is_null())
callback_.Run(succeeded);
} }
private: private:
CallbackType callback_; CallbackType callback_;
base::win::RegKey key_; base::win::RegKey key_;
base::win::ObjectWatcher watcher_;
DISALLOW_COPY_AND_ASSIGN(RegistryWatcher); DISALLOW_COPY_AND_ASSIGN(RegistryWatcher);
}; };
...@@ -735,8 +740,9 @@ bool DnsConfigServiceWin::StartWatching() { ...@@ -735,8 +740,9 @@ bool DnsConfigServiceWin::StartWatching() {
void DnsConfigServiceWin::OnConfigChanged(bool succeeded) { void DnsConfigServiceWin::OnConfigChanged(bool succeeded) {
InvalidateConfig(); InvalidateConfig();
config_reader_->WorkNow(); if (succeeded) {
if (!succeeded) { config_reader_->WorkNow();
} else {
LOG(ERROR) << "DNS config watch failed."; LOG(ERROR) << "DNS config watch failed.";
set_watch_failed(true); set_watch_failed(true);
UMA_HISTOGRAM_ENUMERATION("AsyncDNS.WatchStatus", UMA_HISTOGRAM_ENUMERATION("AsyncDNS.WatchStatus",
......
...@@ -7,8 +7,6 @@ ...@@ -7,8 +7,6 @@
#include <windows.h> #include <windows.h>
#include <winhttp.h> #include <winhttp.h>
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/memory/scoped_ptr.h" #include "base/memory/scoped_ptr.h"
#include "base/profiler/scoped_profile.h" #include "base/profiler/scoped_profile.h"
...@@ -18,7 +16,6 @@ ...@@ -18,7 +16,6 @@
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "base/threading/thread_restrictions.h" #include "base/threading/thread_restrictions.h"
#include "base/win/registry.h" #include "base/win/registry.h"
#include "base/win/scoped_handle.h"
#include "net/base/net_errors.h" #include "net/base/net_errors.h"
#include "net/proxy/proxy_config.h" #include "net/proxy/proxy_config.h"
...@@ -41,6 +38,36 @@ void FreeIEConfig(WINHTTP_CURRENT_USER_IE_PROXY_CONFIG* ie_config) { ...@@ -41,6 +38,36 @@ void FreeIEConfig(WINHTTP_CURRENT_USER_IE_PROXY_CONFIG* ie_config) {
} // namespace } // namespace
// RegKey and ObjectWatcher pair.
class ProxyConfigServiceWin::KeyEntry {
public:
bool StartWatching(base::win::ObjectWatcher::Delegate* delegate) {
// Try to create a watch event for the registry key (which watches the
// sibling tree as well).
if (key_.StartWatching() != ERROR_SUCCESS)
return false;
// Now setup an ObjectWatcher for this event, so we get OnObjectSignaled()
// invoked on this message loop once it is signalled.
if (!watcher_.StartWatching(key_.watch_event(), delegate))
return false;
return true;
}
bool CreateRegKey(HKEY rootkey, const wchar_t* subkey) {
return key_.Create(rootkey, subkey, KEY_NOTIFY) == ERROR_SUCCESS;
}
HANDLE watch_event() const {
return key_.watch_event();
}
private:
base::win::RegKey key_;
base::win::ObjectWatcher watcher_;
};
ProxyConfigServiceWin::ProxyConfigServiceWin() ProxyConfigServiceWin::ProxyConfigServiceWin()
: PollingProxyConfigService( : PollingProxyConfigService(
base::TimeDelta::FromSeconds(kPollIntervalSec), base::TimeDelta::FromSeconds(kPollIntervalSec),
...@@ -98,38 +125,35 @@ void ProxyConfigServiceWin::StartWatchingRegistryForChanges() { ...@@ -98,38 +125,35 @@ void ProxyConfigServiceWin::StartWatchingRegistryForChanges() {
bool ProxyConfigServiceWin::AddKeyToWatchList(HKEY rootkey, bool ProxyConfigServiceWin::AddKeyToWatchList(HKEY rootkey,
const wchar_t* subkey) { const wchar_t* subkey) {
scoped_ptr<base::win::RegKey> key(new base::win::RegKey); scoped_ptr<KeyEntry> entry(new KeyEntry);
if (key->Create(rootkey, subkey, KEY_NOTIFY) != ERROR_SUCCESS) if (!entry->CreateRegKey(rootkey, subkey))
return false; return false;
if (!key->StartWatching(base::Bind(&ProxyConfigServiceWin::OnObjectSignaled, if (!entry->StartWatching(this))
base::Unretained(this),
base::Unretained(key.get())))) {
return false; return false;
}
keys_to_watch_.push_back(key.release()); keys_to_watch_.push_back(entry.release());
return true; return true;
} }
void ProxyConfigServiceWin::OnObjectSignaled(base::win::RegKey* key) { void ProxyConfigServiceWin::OnObjectSignaled(HANDLE object) {
// TODO(vadimt): Remove ScopedProfile below once crbug.com/418183 is fixed. // TODO(vadimt): Remove ScopedProfile below once crbug.com/418183 is fixed.
tracked_objects::ScopedProfile tracking_profile( tracked_objects::ScopedProfile tracking_profile(
FROM_HERE_WITH_EXPLICIT_FUNCTION( FROM_HERE_WITH_EXPLICIT_FUNCTION(
"ProxyConfigServiceWin_OnObjectSignaled")); "ProxyConfigServiceWin_OnObjectSignaled"));
// Figure out which registry key signalled this change. // Figure out which registry key signalled this change.
RegKeyList::iterator it = KeyEntryList::iterator it;
std::find(keys_to_watch_.begin(), keys_to_watch_.end(), key); for (it = keys_to_watch_.begin(); it != keys_to_watch_.end(); ++it) {
if ((*it)->watch_event() == object)
break;
}
DCHECK(it != keys_to_watch_.end()); DCHECK(it != keys_to_watch_.end());
// Keep watching the registry key. // Keep watching the registry key.
if (!key->StartWatching(base::Bind(&ProxyConfigServiceWin::OnObjectSignaled, if (!(*it)->StartWatching(this))
base::Unretained(this),
base::Unretained(key)))) {
delete *it;
keys_to_watch_.erase(it); keys_to_watch_.erase(it);
}
// Have the PollingProxyConfigService test for changes. // Have the PollingProxyConfigService test for changes.
CheckForChangesNow(); CheckForChangesNow();
......
...@@ -12,14 +12,9 @@ ...@@ -12,14 +12,9 @@
#include "base/compiler_specific.h" #include "base/compiler_specific.h"
#include "base/gtest_prod_util.h" #include "base/gtest_prod_util.h"
#include "base/win/object_watcher.h"
#include "net/proxy/polling_proxy_config_service.h" #include "net/proxy/polling_proxy_config_service.h"
namespace base {
namespace win {
class RegKey;
}
} // namespace base.
namespace net { namespace net {
// Implementation of ProxyConfigService that retrieves the system proxy // Implementation of ProxyConfigService that retrieves the system proxy
...@@ -45,7 +40,8 @@ namespace net { ...@@ -45,7 +40,8 @@ namespace net {
// change, or in case we got it wrong (and are not checking all possible // change, or in case we got it wrong (and are not checking all possible
// registry dependencies). // registry dependencies).
class NET_EXPORT_PRIVATE ProxyConfigServiceWin class NET_EXPORT_PRIVATE ProxyConfigServiceWin
: public PollingProxyConfigService { : public PollingProxyConfigService,
public base::win::ObjectWatcher::Delegate {
public: public:
ProxyConfigServiceWin(); ProxyConfigServiceWin();
virtual ~ProxyConfigServiceWin(); virtual ~ProxyConfigServiceWin();
...@@ -55,17 +51,19 @@ class NET_EXPORT_PRIVATE ProxyConfigServiceWin ...@@ -55,17 +51,19 @@ class NET_EXPORT_PRIVATE ProxyConfigServiceWin
private: private:
FRIEND_TEST_ALL_PREFIXES(ProxyConfigServiceWinTest, SetFromIEConfig); FRIEND_TEST_ALL_PREFIXES(ProxyConfigServiceWinTest, SetFromIEConfig);
typedef std::vector<base::win::RegKey*> RegKeyList; class KeyEntry;
typedef std::vector<KeyEntry*> KeyEntryList;
// Registers change observers on the registry keys relating to proxy settings. // Registers change observers on the registry keys relating to proxy settings.
void StartWatchingRegistryForChanges(); void StartWatchingRegistryForChanges();
// Creates a new key and appends it to |keys_to_watch_|. If the key fails to // Creates a new KeyEntry and appends it to |keys_to_watch_|. If the key
// be created, it is not appended to the list and we return false. // fails to be created, it is not appended to the list and we return false.
bool AddKeyToWatchList(HKEY rootkey, const wchar_t* subkey); bool AddKeyToWatchList(HKEY rootkey, const wchar_t* subkey);
// ObjectWatcher::Delegate methods:
// This is called whenever one of the registry keys we are watching change. // This is called whenever one of the registry keys we are watching change.
void OnObjectSignaled(base::win::RegKey* key); virtual void OnObjectSignaled(HANDLE object) override;
static void GetCurrentProxyConfig(ProxyConfig* config); static void GetCurrentProxyConfig(ProxyConfig* config);
...@@ -74,7 +72,7 @@ class NET_EXPORT_PRIVATE ProxyConfigServiceWin ...@@ -74,7 +72,7 @@ class NET_EXPORT_PRIVATE ProxyConfigServiceWin
ProxyConfig* config, ProxyConfig* config,
const WINHTTP_CURRENT_USER_IE_PROXY_CONFIG& ie_config); const WINHTTP_CURRENT_USER_IE_PROXY_CONFIG& ie_config);
RegKeyList keys_to_watch_; KeyEntryList keys_to_watch_;
}; };
} // namespace net } // namespace net
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment