summaryrefslogtreecommitdiffstats
path: root/chrome/browser/file_watcher_win.cc
diff options
context:
space:
mode:
authormnissler@chromium.org <mnissler@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-08-17 15:04:42 +0000
committermnissler@chromium.org <mnissler@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-08-17 15:04:42 +0000
commitc369ffd33760e7b2f6aad22b3747dff321bf497a (patch)
tree18a08bfd012b1f17f24f22042e7af4dd2fe541e9 /chrome/browser/file_watcher_win.cc
parent9d03e7300b24129e53ac5f7894c003336c35f170 (diff)
downloadchromium_src-c369ffd33760e7b2f6aad22b3747dff321bf497a.zip
chromium_src-c369ffd33760e7b2f6aad22b3747dff321bf497a.tar.gz
chromium_src-c369ffd33760e7b2f6aad22b3747dff321bf497a.tar.bz2
Revert 56341 - Add support for watching directories to FileWatcher.
BUG=none TEST=Unit tests in file_watcher_unittest.cc. Review URL: http://codereview.chromium.org/3149004 TBR=mnissler@chromium.org Review URL: http://codereview.chromium.org/3165027 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@56349 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/file_watcher_win.cc')
-rw-r--r--chrome/browser/file_watcher_win.cc111
1 files changed, 111 insertions, 0 deletions
diff --git a/chrome/browser/file_watcher_win.cc b/chrome/browser/file_watcher_win.cc
new file mode 100644
index 0000000..d4ec0ed
--- /dev/null
+++ b/chrome/browser/file_watcher_win.cc
@@ -0,0 +1,111 @@
+// Copyright (c) 2009 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 "chrome/browser/file_watcher.h"
+
+#include "base/file_path.h"
+#include "base/file_util.h"
+#include "base/logging.h"
+#include "base/object_watcher.h"
+#include "base/ref_counted.h"
+#include "base/time.h"
+
+namespace {
+
+class FileWatcherImpl : public FileWatcher::PlatformDelegate,
+ public base::ObjectWatcher::Delegate {
+ public:
+ FileWatcherImpl() : delegate_(NULL), handle_(INVALID_HANDLE_VALUE) {}
+
+ virtual bool Watch(const FilePath& path, FileWatcher::Delegate* delegate);
+
+ // Callback from MessageLoopForIO.
+ virtual void OnObjectSignaled(HANDLE object);
+
+ private:
+ virtual ~FileWatcherImpl();
+
+ // Delegate to notify upon changes.
+ scoped_refptr<FileWatcher::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_;
+
+ // Keep track of the last modified time of the file. We use nulltime
+ // to represent the file not existing.
+ base::Time last_modified_;
+
+ DISALLOW_COPY_AND_ASSIGN(FileWatcherImpl);
+};
+
+FileWatcherImpl::~FileWatcherImpl() {
+ if (handle_ != INVALID_HANDLE_VALUE) {
+ watcher_.StopWatching();
+ FindCloseChangeNotification(handle_);
+ }
+}
+
+bool FileWatcherImpl::Watch(const FilePath& path,
+ FileWatcher::Delegate* delegate) {
+ DCHECK(path_.value().empty()); // Can only watch one path.
+ file_util::FileInfo file_info;
+ if (file_util::GetFileInfo(path, &file_info))
+ last_modified_ = file_info.last_modified;
+
+ // FindFirstChangeNotification watches directories, so use the parent path.
+ handle_ = FindFirstChangeNotification(
+ path.DirName().value().c_str(),
+ false, // Don't watch subtrees
+ FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_SIZE |
+ FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_DIR_NAME);
+ if (handle_ == INVALID_HANDLE_VALUE)
+ return false;
+
+ delegate_ = delegate;
+ path_ = path;
+ watcher_.StartWatching(handle_, this);
+
+ return true;
+}
+
+void FileWatcherImpl::OnObjectSignaled(HANDLE object) {
+ DCHECK(object == handle_);
+ // Make sure we stay alive through the body of this function.
+ scoped_refptr<FileWatcherImpl> keep_alive(this);
+
+ file_util::FileInfo file_info;
+ bool file_exists = file_util::GetFileInfo(path_, &file_info);
+ if (file_exists && (last_modified_.is_null() ||
+ last_modified_ != file_info.last_modified)) {
+ last_modified_ = file_info.last_modified;
+ delegate_->OnFileChanged(path_);
+ } else if (file_exists && (base::Time::Now() - last_modified_ <
+ base::TimeDelta::FromSeconds(2))) {
+ // Since we only have a resolution of 1s, if we get a callback within
+ // 2s of the file having changed, go ahead and notify our observer. This
+ // might be from a different file change, but it's better to notify too
+ // much rather than miss a notification.
+ delegate_->OnFileChanged(path_);
+ } else if (!file_exists && !last_modified_.is_null()) {
+ last_modified_ = base::Time();
+ delegate_->OnFileChanged(path_);
+ }
+
+ // Register for more notifications on file change.
+ BOOL ok = FindNextChangeNotification(object);
+ DCHECK(ok);
+ watcher_.StartWatching(object, this);
+}
+
+} // namespace
+
+FileWatcher::FileWatcher() {
+ impl_ = new FileWatcherImpl();
+}