diff options
Diffstat (limited to 'base/directory_watcher_win.cc')
-rw-r--r-- | base/directory_watcher_win.cc | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/base/directory_watcher_win.cc b/base/directory_watcher_win.cc new file mode 100644 index 0000000..cdaec39 --- /dev/null +++ b/base/directory_watcher_win.cc @@ -0,0 +1,86 @@ +// Copyright (c) 2006-2008 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 "base/directory_watcher.h" + +#include "base/file_path.h" +#include "base/object_watcher.h" + +// Private implementation class implementing the behavior of DirectoryWatcher. +class DirectoryWatcher::Impl : public base::RefCounted<DirectoryWatcher::Impl>, + public base::ObjectWatcher::Delegate { + public: + Impl(DirectoryWatcher::Delegate* delegate) + : delegate_(delegate), handle_(INVALID_HANDLE_VALUE) {} + ~Impl(); + + // Register interest in any changes in |path|. + // Returns false on error. + bool Watch(const FilePath& path); + + // Callback from MessageLoopForIO. + virtual void OnObjectSignaled(HANDLE object); + + private: + // Delegate to notify upon changes. + DirectoryWatcher::Delegate* delegate_; + // Path we're watching (passed to delegate). + FilePath path_; + // Handle for FindFirstChangeNotification. + HANDLE handle_; + // ObjectWatcher to watch handle_ for events. + base::ObjectWatcher watcher_; +}; + +DirectoryWatcher::Impl::~Impl() { + if (handle_ != INVALID_HANDLE_VALUE) { + watcher_.StopWatching(); + FindCloseChangeNotification(handle_); + } +} + +bool DirectoryWatcher::Impl::Watch(const FilePath& path) { + DCHECK(path_.value().empty()); // Can only watch one path. + + handle_ = FindFirstChangeNotification( + path.value().c_str(), + FALSE, // Don't watch subtree. + FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_SIZE | + FILE_NOTIFY_CHANGE_LAST_WRITE); + if (handle_ == INVALID_HANDLE_VALUE) { + NOTREACHED(); + return false; + } + + path_ = path; + watcher_.StartWatching(handle_, this); + + return true; +} + +void DirectoryWatcher::Impl::OnObjectSignaled(HANDLE object) { + DCHECK(object == handle_); + // Make sure we stay alive through the body of this function. + scoped_refptr<DirectoryWatcher::Impl> keep_alive(this); + + delegate_->OnDirectoryChanged(path_); + + // Register for more notifications on file change. + BOOL ok = FindNextChangeNotification(object); + DCHECK(ok); + watcher_.StartWatching(object, this); +} + +DirectoryWatcher::DirectoryWatcher() { +} + +DirectoryWatcher::~DirectoryWatcher() { + // Declared in .cc file for access to ~DirectoryWatcher::Impl. +} + +bool DirectoryWatcher::Watch(const FilePath& path, + Delegate* delegate) { + impl_ = new DirectoryWatcher::Impl(delegate); + return impl_->Watch(path); +} |