Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(607)

Side by Side Diff: base/file_watcher_win.cc

Issue 661359: Add a FileWatcher to base/. (Closed)
Patch Set: 2s Created 10 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « base/file_watcher_unittest.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(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 }
OLDNEW
« no previous file with comments | « base/file_watcher_unittest.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698