diff options
author | robertshield@chromium.org <robertshield@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-05-27 16:44:31 +0000 |
---|---|---|
committer | robertshield@chromium.org <robertshield@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-05-27 16:44:31 +0000 |
commit | 6a7748e79cb7118089d5857291cb76d57c5c8162 (patch) | |
tree | bdfe13aba5f79d4c090bd27fdf75173ff751bb3c /chrome_frame/registry_watcher.cc | |
parent | 13ffa32ea65d5fda56bcb030643b989d5564c586 (diff) | |
download | chromium_src-6a7748e79cb7118089d5857291cb76d57c5c8162.zip chromium_src-6a7748e79cb7118089d5857291cb76d57c5c8162.tar.gz chromium_src-6a7748e79cb7118089d5857291cb76d57c5c8162.tar.bz2 |
Add a self-destruct mechanism to user-level Chrome Frame when it detects that system-level Chrome Frame is present. This is a first step to handling user-to-system-level handoff.
It will cause a user-level install to be correctly replaced with a system-level one once the user logs out and back in again. Additional changelists
will follow that:
1) Ensure full clean-up of the user-level installation.
2) Handle notifications such that logging out and in again isn't required.
BUG=82816
TEST=Install user-level Chrome Frame.
Review URL: http://codereview.chromium.org/7065024
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@87033 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome_frame/registry_watcher.cc')
-rw-r--r-- | chrome_frame/registry_watcher.cc | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/chrome_frame/registry_watcher.cc b/chrome_frame/registry_watcher.cc new file mode 100644 index 0000000..dcbf8b9 --- /dev/null +++ b/chrome_frame/registry_watcher.cc @@ -0,0 +1,101 @@ +// Copyright (c) 2011 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 utility class that makes it easy to register for registry change +// notifications. +// + +#include "chrome_frame/registry_watcher.h" + +#include "chrome_frame/chrome_frame_helper_util.h" + +namespace { +const wchar_t kRegistryWatcherEventName[] = L"chrome_registry_watcher_event"; +} // namespace + +RegistryWatcher::RegistryWatcher(HKEY hive, + const wchar_t* path, + NotifyFunc callback) + : callback_(callback), + wait_event_(NULL), + wait_handle_(NULL), + stopping_(false) { + // Enforce that we can open the given registry path with the KEY_NOTIFY + // permission. + LONG result = RegOpenKeyEx(hive, path, 0, KEY_NOTIFY, ®istry_key_); + if (result != ERROR_SUCCESS) { + registry_key_ = NULL; + } +} + +RegistryWatcher::~RegistryWatcher() { + StopWatching(); + if (registry_key_) { + RegCloseKey(registry_key_); + registry_key_ = NULL; + } +} + +bool RegistryWatcher::StartWatching() { + if (!registry_key_ || wait_event_ || !callback_) { + return false; + } + + bool result = false; + wait_event_ = CreateEvent(NULL, + FALSE, // Auto-resets + FALSE, // Initially non-signalled + kRegistryWatcherEventName); + if (wait_event_ != NULL) { + LONG notify_result = RegNotifyChangeKeyValue( + registry_key_, + TRUE, // Watch subtree + REG_NOTIFY_CHANGE_NAME, // Notifies if a subkey is added. + wait_event_, + TRUE); // Asynchronous, signal the event when a change occurs. + + if (notify_result == ERROR_SUCCESS) { + if (RegisterWaitForSingleObject(&wait_handle_, + wait_event_, + &RegistryWatcher::WaitCallback, + reinterpret_cast<void*>(this), + INFINITE, + WT_EXECUTEDEFAULT)) { + stopping_ = false; + result = true; + } + } + } + + // If we're not good to go we don't need to hold onto the event. + if (!result && wait_event_) { + CloseHandle(wait_event_); + wait_event_ = NULL; + } + + return result; +} + +void RegistryWatcher::StopWatching() { + stopping_ = true; + if (wait_handle_) { + // Unregister the wait and block until any current handlers have returned. + UnregisterWaitEx(wait_handle_, INVALID_HANDLE_VALUE); + wait_handle_ = NULL; + } + if (wait_event_) { + CloseHandle(wait_event_); + wait_event_ = NULL; + } +} + +void CALLBACK RegistryWatcher::WaitCallback(void* param, BOOLEAN wait_fired) { + RegistryWatcher* watcher = reinterpret_cast<RegistryWatcher*>(param); + if (watcher->stopping_) + return; + + if (watcher->callback_) { + watcher->callback_(); + } +} |