OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "base/file_watcher.h" |
| 6 |
| 7 #include "base/file_path.h" |
| 8 #include "base/file_util.h" |
| 9 #include "base/logging.h" |
| 10 #include "base/object_watcher.h" |
| 11 #include "base/ref_counted.h" |
| 12 #include "base/time.h" |
| 13 |
| 14 namespace { |
| 15 |
| 16 class FileWatcherImpl : public FileWatcher::PlatformDelegate, |
| 17 public base::ObjectWatcher::Delegate { |
| 18 public: |
| 19 FileWatcherImpl() : delegate_(NULL), handle_(INVALID_HANDLE_VALUE) {} |
| 20 |
| 21 virtual bool Watch(const FilePath& path, FileWatcher::Delegate* delegate, |
| 22 MessageLoop* backend_loop); |
| 23 |
| 24 // Callback from MessageLoopForIO. |
| 25 virtual void OnObjectSignaled(HANDLE object); |
| 26 |
| 27 private: |
| 28 virtual ~FileWatcherImpl(); |
| 29 |
| 30 // Delegate to notify upon changes. |
| 31 FileWatcher::Delegate* delegate_; |
| 32 |
| 33 // Path we're watching (passed to delegate). |
| 34 FilePath path_; |
| 35 |
| 36 // Handle for FindFirstChangeNotification. |
| 37 HANDLE handle_; |
| 38 |
| 39 // ObjectWatcher to watch handle_ for events. |
| 40 base::ObjectWatcher watcher_; |
| 41 |
| 42 // Keep track of the last modified time of the file. We use nulltime |
| 43 // to represent the file not existing. |
| 44 base::Time last_modified_; |
| 45 |
| 46 DISALLOW_COPY_AND_ASSIGN(FileWatcherImpl); |
| 47 }; |
| 48 |
| 49 FileWatcherImpl::~FileWatcherImpl() { |
| 50 if (handle_ != INVALID_HANDLE_VALUE) { |
| 51 watcher_.StopWatching(); |
| 52 FindCloseChangeNotification(handle_); |
| 53 } |
| 54 } |
| 55 |
| 56 bool FileWatcherImpl::Watch(const FilePath& path, |
| 57 FileWatcher::Delegate* delegate, |
| 58 MessageLoop* backend_loop) { |
| 59 DCHECK(path_.value().empty()); // Can only watch one path. |
| 60 file_util::FileInfo file_info; |
| 61 if (file_util::GetFileInfo(path, &file_info)) |
| 62 last_modified_ = file_info.last_modified; |
| 63 |
| 64 // FindFirstChangeNotification watches directories, so use the parent path. |
| 65 handle_ = FindFirstChangeNotification( |
| 66 path.DirName().value().c_str(), |
| 67 false, // Don't watch subtrees |
| 68 FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_SIZE | |
| 69 FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_DIR_NAME); |
| 70 if (handle_ == INVALID_HANDLE_VALUE) |
| 71 return false; |
| 72 |
| 73 delegate_ = delegate; |
| 74 path_ = path; |
| 75 watcher_.StartWatching(handle_, this); |
| 76 |
| 77 return true; |
| 78 } |
| 79 |
| 80 void FileWatcherImpl::OnObjectSignaled(HANDLE object) { |
| 81 DCHECK(object == handle_); |
| 82 // Make sure we stay alive through the body of this function. |
| 83 scoped_refptr<FileWatcherImpl> keep_alive(this); |
| 84 |
| 85 file_util::FileInfo file_info; |
| 86 bool file_exists = file_util::GetFileInfo(path_, &file_info); |
| 87 if (file_exists && (last_modified_.is_null() || |
| 88 last_modified_ != file_info.last_modified)) { |
| 89 last_modified_ = file_info.last_modified; |
| 90 delegate_->OnFileChanged(path_); |
| 91 } else if (file_exists && (base::Time::Now() - last_modified_ < |
| 92 base::TimeDelta::FromSeconds(2))) { |
| 93 // Since we only have a resolution of 1s, if we get a callback within |
| 94 // 2s of the file having changed, go ahead and notify our observer. This |
| 95 // might be from a different file change, but it's better to notify too |
| 96 // much rather than miss a notification. |
| 97 delegate_->OnFileChanged(path_); |
| 98 } else if (!file_exists && !last_modified_.is_null()) { |
| 99 last_modified_ = base::Time(); |
| 100 delegate_->OnFileChanged(path_); |
| 101 } |
| 102 |
| 103 // Register for more notifications on file change. |
| 104 BOOL ok = FindNextChangeNotification(object); |
| 105 DCHECK(ok); |
| 106 watcher_.StartWatching(object, this); |
| 107 } |
| 108 |
| 109 } // namespace |
| 110 |
| 111 FileWatcher::FileWatcher() { |
| 112 impl_ = new FileWatcherImpl(); |
| 113 } |
OLD | NEW |