From 9e8d4f92df67dd8d4c8d4097035aaf6279fe84ba Mon Sep 17 00:00:00 2001 From: "evanm@google.com" Date: Fri, 17 Oct 2008 02:45:56 +0000 Subject: Add a DirectoryWatcher class, allowing objects to be notified whenever a directory's contents change. Review URL: http://codereview.chromium.org/6377 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@3504 0039d316-1c4b-4281-b951-d872f2087c98 --- base/directory_watcher_win.cc | 86 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 base/directory_watcher_win.cc (limited to 'base/directory_watcher_win.cc') 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, + 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 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); +} -- cgit v1.1