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

Side by Side Diff: base/files/file_path_watcher_win.cc

Issue 273843004: Fix file path notification filtering on Windows. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 7 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | 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
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/files/file_path_watcher.h" 5 #include "base/files/file_path_watcher.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/file_util.h" 8 #include "base/file_util.h"
9 #include "base/files/file.h" 9 #include "base/files/file.h"
10 #include "base/files/file_path.h" 10 #include "base/files/file_path.h"
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
90 bool recursive, 90 bool recursive,
91 const FilePathWatcher::Callback& callback) { 91 const FilePathWatcher::Callback& callback) {
92 DCHECK(target_.value().empty()); // Can only watch one path. 92 DCHECK(target_.value().empty()); // Can only watch one path.
93 93
94 set_message_loop(MessageLoopProxy::current()); 94 set_message_loop(MessageLoopProxy::current());
95 callback_ = callback; 95 callback_ = callback;
96 target_ = path; 96 target_ = path;
97 recursive_watch_ = recursive; 97 recursive_watch_ = recursive;
98 MessageLoop::current()->AddDestructionObserver(this); 98 MessageLoop::current()->AddDestructionObserver(this);
99 99
100 File::Info file_info;
101 if (GetFileInfo(target_, &file_info)) {
102 last_modified_ = file_info.last_modified;
103 first_notification_ = Time::Now();
104 }
105
100 if (!UpdateWatch()) 106 if (!UpdateWatch())
101 return false; 107 return false;
102 108
103 watcher_.StartWatching(handle_, this); 109 watcher_.StartWatching(handle_, this);
104 110
105 return true; 111 return true;
106 } 112 }
107 113
108 void FilePathWatcherImpl::Cancel() { 114 void FilePathWatcherImpl::Cancel() {
109 if (callback_.is_null()) { 115 if (callback_.is_null()) {
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
144 scoped_refptr<FilePathWatcherImpl> keep_alive(this); 150 scoped_refptr<FilePathWatcherImpl> keep_alive(this);
145 151
146 if (!UpdateWatch()) { 152 if (!UpdateWatch()) {
147 callback_.Run(target_, true /* error */); 153 callback_.Run(target_, true /* error */);
148 return; 154 return;
149 } 155 }
150 156
151 // Check whether the event applies to |target_| and notify the callback. 157 // Check whether the event applies to |target_| and notify the callback.
152 File::Info file_info; 158 File::Info file_info;
153 bool file_exists = GetFileInfo(target_, &file_info); 159 bool file_exists = GetFileInfo(target_, &file_info);
154 if (file_exists && (last_modified_.is_null() || 160 if (recursive_watch_) {
161 // Only the mtime of |target_| is tracked but in a recursive watch,
162 // some other file or directory may have changed so all notifications
163 // are passed through. It is possible to figure out which file changed
164 // using ReadDirectoryChangesW() instead of FindFirstChangeNotification(),
165 // but that function is quite complicated:
166 // http://qualapps.blogspot.com/2010/05/understanding-readdirectorychangesw. html
167 callback_.Run(target_, false);
168 } else if (file_exists && (last_modified_.is_null() ||
155 last_modified_ != file_info.last_modified)) { 169 last_modified_ != file_info.last_modified)) {
Mattias Nissler (ping if slow) 2014/05/14 10:27:52 nit: align at ( for readability
vandebo (ex-Chrome) 2014/05/14 16:55:41 Oops, fixed.
156 last_modified_ = file_info.last_modified; 170 last_modified_ = file_info.last_modified;
157 first_notification_ = Time::Now(); 171 first_notification_ = Time::Now();
158 callback_.Run(target_, false); 172 callback_.Run(target_, false);
159 } else if (file_exists && !first_notification_.is_null()) { 173 } else if (file_exists && last_modified_ == file_info.last_modified &&
174 !first_notification_.is_null()) {
160 // The target's last modification time is equal to what's on record. This 175 // The target's last modification time is equal to what's on record. This
161 // means that either an unrelated event occurred, or the target changed 176 // means that either an unrelated event occurred, or the target changed
162 // again (file modification times only have a resolution of 1s). Comparing 177 // again (file modification times only have a resolution of 1s). Comparing
163 // file modification times against the wall clock is not reliable to find 178 // file modification times against the wall clock is not reliable to find
164 // out whether the change is recent, since this code might just run too 179 // out whether the change is recent, since this code might just run too
165 // late. Moreover, there's no guarantee that file modification time and wall 180 // late. Moreover, there's no guarantee that file modification time and wall
166 // clock times come from the same source. 181 // clock times come from the same source.
167 // 182 //
168 // Instead, the time at which the first notification carrying the current 183 // Instead, the time at which the first notification carrying the current
169 // |last_notified_| time stamp is recorded. Later notifications that find 184 // |last_notified_| time stamp is recorded. Later notifications that find
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
223 return false; 238 return false;
224 } 239 }
225 240
226 return true; 241 return true;
227 } 242 }
228 243
229 bool FilePathWatcherImpl::UpdateWatch() { 244 bool FilePathWatcherImpl::UpdateWatch() {
230 if (handle_ != INVALID_HANDLE_VALUE) 245 if (handle_ != INVALID_HANDLE_VALUE)
231 DestroyWatch(); 246 DestroyWatch();
232 247
233 File::Info file_info;
234 if (GetFileInfo(target_, &file_info)) {
235 last_modified_ = file_info.last_modified;
236 first_notification_ = Time::Now();
237 }
238
239 // Start at the target and walk up the directory chain until we succesfully 248 // Start at the target and walk up the directory chain until we succesfully
240 // create a watch handle in |handle_|. |child_dirs| keeps a stack of child 249 // create a watch handle in |handle_|. |child_dirs| keeps a stack of child
241 // directories stripped from target, in reverse order. 250 // directories stripped from target, in reverse order.
242 std::vector<FilePath> child_dirs; 251 std::vector<FilePath> child_dirs;
243 FilePath watched_path(target_); 252 FilePath watched_path(target_);
244 while (true) { 253 while (true) {
245 if (!SetupWatchHandle(watched_path, recursive_watch_, &handle_)) 254 if (!SetupWatchHandle(watched_path, recursive_watch_, &handle_))
246 return false; 255 return false;
247 256
248 // Break if a valid handle is returned. Try the parent directory otherwise. 257 // Break if a valid handle is returned. Try the parent directory otherwise.
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
283 handle_ = INVALID_HANDLE_VALUE; 292 handle_ = INVALID_HANDLE_VALUE;
284 } 293 }
285 294
286 } // namespace 295 } // namespace
287 296
288 FilePathWatcher::FilePathWatcher() { 297 FilePathWatcher::FilePathWatcher() {
289 impl_ = new FilePathWatcherImpl(); 298 impl_ = new FilePathWatcherImpl();
290 } 299 }
291 300
292 } // namespace base 301 } // namespace base
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698