| Index: base/win/registry.cc
|
| diff --git a/base/win/registry.cc b/base/win/registry.cc
|
| index e8fb8922bc63cbefeaa34fce9ee942e3a07af685..23ad12cad649391cdf87d04c552c2ab0e5153ec0 100644
|
| --- a/base/win/registry.cc
|
| +++ b/base/win/registry.cc
|
| @@ -34,23 +34,67 @@ const REGSAM kWow64AccessMask = KEY_WOW64_32KEY | KEY_WOW64_64KEY;
|
|
|
| } // 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 (!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()
|
| - : key_(NULL),
|
| - watch_event_(0),
|
| - wow64access_(0) {
|
| +RegKey::RegKey() : key_(NULL), wow64access_(0) {
|
| }
|
|
|
| -RegKey::RegKey(HKEY key)
|
| - : key_(key),
|
| - watch_event_(0),
|
| - wow64access_(0) {
|
| +RegKey::RegKey(HKEY key) : key_(key), wow64access_(0) {
|
| }
|
|
|
| RegKey::RegKey(HKEY rootkey, const wchar_t* subkey, REGSAM access)
|
| : key_(NULL),
|
| - watch_event_(0),
|
| wow64access_(0) {
|
| if (rootkey) {
|
| if (access & (KEY_SET_VALUE | KEY_CREATE_SUB_KEY | KEY_CREATE_LINK))
|
| @@ -150,7 +194,6 @@ LONG RegKey::OpenKey(const wchar_t* relative_key_name, REGSAM access) {
|
| }
|
|
|
| void RegKey::Close() {
|
| - StopWatching();
|
| if (key_) {
|
| ::RegCloseKey(key_);
|
| key_ = NULL;
|
| @@ -168,7 +211,6 @@ void RegKey::Set(HKEY key) {
|
|
|
| HKEY RegKey::Take() {
|
| DCHECK(wow64access_ == 0);
|
| - StopWatching();
|
| HKEY key = key_;
|
| key_ = NULL;
|
| return key;
|
| @@ -367,44 +409,14 @@ LONG RegKey::WriteValue(const wchar_t* name,
|
| return result;
|
| }
|
|
|
| -LONG RegKey::StartWatching() {
|
| - DCHECK(key_);
|
| - if (!watch_event_)
|
| - watch_event_ = CreateEvent(NULL, TRUE, FALSE, NULL);
|
| -
|
| - 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_, TRUE);
|
| - if (result != ERROR_SUCCESS) {
|
| - CloseHandle(watch_event_);
|
| - watch_event_ = 0;
|
| - }
|
| +bool RegKey::StartWatching(const ChangeCallback& callback) {
|
| + if (!key_watcher_)
|
| + key_watcher_.reset(new Watcher(this));
|
|
|
| - return result;
|
| -}
|
| -
|
| -bool RegKey::HasChanged() {
|
| - if (watch_event_) {
|
| - if (WaitForSingleObject(watch_event_, 0) == WAIT_OBJECT_0) {
|
| - StartWatching();
|
| - return true;
|
| - }
|
| - }
|
| - return false;
|
| -}
|
| + if (!key_watcher_.get()->StartWatching(key_, callback))
|
| + return false;
|
|
|
| -LONG RegKey::StopWatching() {
|
| - LONG result = ERROR_INVALID_HANDLE;
|
| - if (watch_event_) {
|
| - CloseHandle(watch_event_);
|
| - watch_event_ = 0;
|
| - result = ERROR_SUCCESS;
|
| - }
|
| - return result;
|
| + return true;
|
| }
|
|
|
| // static
|
|
|