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

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

Issue 11876025: Eliminate FilePathWatcher::Delegate. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 11 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 | « base/files/file_path_watcher_kqueue.cc ('k') | base/files/file_path_watcher_stub.cc » ('j') | 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) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 <errno.h> 7 #include <errno.h>
8 #include <string.h> 8 #include <string.h>
9 #include <sys/inotify.h> 9 #include <sys/inotify.h>
10 #include <sys/ioctl.h> 10 #include <sys/ioctl.h>
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
94 // the currently watched path for |fired_watch|. The flag |created| is true if 94 // the currently watched path for |fired_watch|. The flag |created| is true if
95 // the object appears. 95 // the object appears.
96 void OnFilePathChanged(InotifyReader::Watch fired_watch, 96 void OnFilePathChanged(InotifyReader::Watch fired_watch,
97 const FilePath::StringType& child, 97 const FilePath::StringType& child,
98 bool created); 98 bool created);
99 99
100 // Start watching |path| for changes and notify |delegate| on each change. 100 // Start watching |path| for changes and notify |delegate| on each change.
101 // Returns true if watch for |path| has been added successfully. 101 // Returns true if watch for |path| has been added successfully.
102 virtual bool Watch(const FilePath& path, 102 virtual bool Watch(const FilePath& path,
103 bool recursive, 103 bool recursive,
104 FilePathWatcher::Delegate* delegate) OVERRIDE; 104 const FilePathWatcher::Callback& callback) OVERRIDE;
105 105
106 // Cancel the watch. This unregisters the instance with InotifyReader. 106 // Cancel the watch. This unregisters the instance with InotifyReader.
107 virtual void Cancel() OVERRIDE; 107 virtual void Cancel() OVERRIDE;
108 108
109 // Deletion of the FilePathWatcher will call Cancel() to dispose of this 109 // Deletion of the FilePathWatcher will call Cancel() to dispose of this
110 // object in the right thread. This also observes destruction of the required 110 // object in the right thread. This also observes destruction of the required
111 // cleanup thread, in case it quits before Cancel() is called. 111 // cleanup thread, in case it quits before Cancel() is called.
112 virtual void WillDestroyCurrentMessageLoop() OVERRIDE; 112 virtual void WillDestroyCurrentMessageLoop() OVERRIDE;
113 113
114 protected: 114 protected:
(...skipping 15 matching lines...) Expand all
130 InotifyReader::Watch watch_; 130 InotifyReader::Watch watch_;
131 FilePath::StringType subdir_; 131 FilePath::StringType subdir_;
132 FilePath::StringType linkname_; 132 FilePath::StringType linkname_;
133 }; 133 };
134 typedef std::vector<WatchEntry> WatchVector; 134 typedef std::vector<WatchEntry> WatchVector;
135 135
136 // Reconfigure to watch for the most specific parent directory of |target_| 136 // Reconfigure to watch for the most specific parent directory of |target_|
137 // that exists. Updates |watched_path_|. Returns true on success. 137 // that exists. Updates |watched_path_|. Returns true on success.
138 bool UpdateWatches() WARN_UNUSED_RESULT; 138 bool UpdateWatches() WARN_UNUSED_RESULT;
139 139
140 // Delegate to notify upon changes. 140 // Callback to notify upon changes.
141 scoped_refptr<FilePathWatcher::Delegate> delegate_; 141 FilePathWatcher::Callback callback_;
142 142
143 // The file or directory we're supposed to watch. 143 // The file or directory we're supposed to watch.
144 FilePath target_; 144 FilePath target_;
145 145
146 // The vector of watches and next component names for all path components, 146 // The vector of watches and next component names for all path components,
147 // starting at the root directory. The last entry corresponds to the watch for 147 // starting at the root directory. The last entry corresponds to the watch for
148 // |target_| and always stores an empty next component name in |subdir_|. 148 // |target_| and always stores an empty next component name in |subdir_|.
149 WatchVector watches_; 149 WatchVector watches_;
150 150
151 DISALLOW_COPY_AND_ASSIGN(FilePathWatcherImpl); 151 DISALLOW_COPY_AND_ASSIGN(FilePathWatcherImpl);
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
288 288
289 for (WatcherSet::iterator watcher = watchers_[event->wd].begin(); 289 for (WatcherSet::iterator watcher = watchers_[event->wd].begin();
290 watcher != watchers_[event->wd].end(); 290 watcher != watchers_[event->wd].end();
291 ++watcher) { 291 ++watcher) {
292 (*watcher)->OnFilePathChanged(event->wd, 292 (*watcher)->OnFilePathChanged(event->wd,
293 child, 293 child,
294 event->mask & (IN_CREATE | IN_MOVED_TO)); 294 event->mask & (IN_CREATE | IN_MOVED_TO));
295 } 295 }
296 } 296 }
297 297
298 FilePathWatcherImpl::FilePathWatcherImpl() 298 FilePathWatcherImpl::FilePathWatcherImpl() {
299 : delegate_(NULL) {
300 } 299 }
301 300
302 void FilePathWatcherImpl::OnFilePathChanged(InotifyReader::Watch fired_watch, 301 void FilePathWatcherImpl::OnFilePathChanged(InotifyReader::Watch fired_watch,
303 const FilePath::StringType& child, 302 const FilePath::StringType& child,
304 bool created) { 303 bool created) {
305 if (!message_loop()->BelongsToCurrentThread()) { 304 if (!message_loop()->BelongsToCurrentThread()) {
306 // Switch to message_loop_ to access watches_ safely. 305 // Switch to message_loop_ to access watches_ safely.
307 message_loop()->PostTask(FROM_HERE, 306 message_loop()->PostTask(FROM_HERE,
308 base::Bind(&FilePathWatcherImpl::OnFilePathChanged, 307 base::Bind(&FilePathWatcherImpl::OnFilePathChanged,
309 this, 308 this,
(...skipping 22 matching lines...) Expand all
332 (watch_entry->subdir_.empty() && watch_entry->linkname_.empty()) || 331 (watch_entry->subdir_.empty() && watch_entry->linkname_.empty()) ||
333 (watch_entry->subdir_ == child && (watch_entry + 1)->subdir_.empty()); 332 (watch_entry->subdir_ == child && (watch_entry + 1)->subdir_.empty());
334 333
335 // Update watches if a directory component of the |target_| path 334 // Update watches if a directory component of the |target_| path
336 // (dis)appears. Note that we don't add the additional restriction 335 // (dis)appears. Note that we don't add the additional restriction
337 // of checking the event mask to see if it is for a directory here 336 // of checking the event mask to see if it is for a directory here
338 // as changes to symlinks on the target path will not have 337 // as changes to symlinks on the target path will not have
339 // IN_ISDIR set in the event masks. As a result we may sometimes 338 // IN_ISDIR set in the event masks. As a result we may sometimes
340 // call UpdateWatches() unnecessarily. 339 // call UpdateWatches() unnecessarily.
341 if (change_on_target_path && !UpdateWatches()) { 340 if (change_on_target_path && !UpdateWatches()) {
342 delegate_->OnFilePathError(target_); 341 callback_.Run(target_, true /* error */);
343 return; 342 return;
344 } 343 }
345 344
346 // Report the following events: 345 // Report the following events:
347 // - The target or a direct child of the target got changed (in case the 346 // - The target or a direct child of the target got changed (in case the
348 // watched path refers to a directory). 347 // watched path refers to a directory).
349 // - One of the parent directories got moved or deleted, since the target 348 // - One of the parent directories got moved or deleted, since the target
350 // disappears in this case. 349 // disappears in this case.
351 // - One of the parent directories appears. The event corresponding to 350 // - One of the parent directories appears. The event corresponding to
352 // the target appearing might have been missed in this case, so 351 // the target appearing might have been missed in this case, so
353 // recheck. 352 // recheck.
354 if (target_changed || 353 if (target_changed ||
355 (change_on_target_path && !created) || 354 (change_on_target_path && !created) ||
356 (change_on_target_path && file_util::PathExists(target_))) { 355 (change_on_target_path && file_util::PathExists(target_))) {
357 delegate_->OnFilePathChanged(target_); 356 callback_.Run(target_, false);
358 return; 357 return;
359 } 358 }
360 } 359 }
361 } 360 }
362 } 361 }
363 362
364 bool FilePathWatcherImpl::Watch(const FilePath& path, 363 bool FilePathWatcherImpl::Watch(const FilePath& path,
365 bool recursive, 364 bool recursive,
366 FilePathWatcher::Delegate* delegate) { 365 const FilePathWatcher::Callback& callback) {
367 DCHECK(target_.empty()); 366 DCHECK(target_.empty());
368 DCHECK(MessageLoopForIO::current()); 367 DCHECK(MessageLoopForIO::current());
369 if (recursive) { 368 if (recursive) {
370 // Recursive watch is not supported on this platform. 369 // Recursive watch is not supported on this platform.
371 NOTIMPLEMENTED(); 370 NOTIMPLEMENTED();
372 return false; 371 return false;
373 } 372 }
374 373
375 set_message_loop(base::MessageLoopProxy::current()); 374 set_message_loop(base::MessageLoopProxy::current());
376 delegate_ = delegate; 375 callback_ = callback;
377 target_ = path; 376 target_ = path;
378 MessageLoop::current()->AddDestructionObserver(this); 377 MessageLoop::current()->AddDestructionObserver(this);
379 378
380 std::vector<FilePath::StringType> comps; 379 std::vector<FilePath::StringType> comps;
381 target_.GetComponents(&comps); 380 target_.GetComponents(&comps);
382 DCHECK(!comps.empty()); 381 DCHECK(!comps.empty());
383 std::vector<FilePath::StringType>::const_iterator comp = comps.begin(); 382 std::vector<FilePath::StringType>::const_iterator comp = comps.begin();
384 for (++comp; comp != comps.end(); ++comp) 383 for (++comp; comp != comps.end(); ++comp)
385 watches_.push_back(WatchEntry(InotifyReader::kInvalidWatch, *comp)); 384 watches_.push_back(WatchEntry(InotifyReader::kInvalidWatch, *comp));
386 385
387 watches_.push_back(WatchEntry(InotifyReader::kInvalidWatch, 386 watches_.push_back(WatchEntry(InotifyReader::kInvalidWatch,
388 FilePath::StringType())); 387 FilePath::StringType()));
389 return UpdateWatches(); 388 return UpdateWatches();
390 } 389 }
391 390
392 void FilePathWatcherImpl::Cancel() { 391 void FilePathWatcherImpl::Cancel() {
393 if (!delegate_) { 392 if (callback_.is_null()) {
394 // Watch was never called, or the |message_loop_| thread is already gone. 393 // Watch was never called, or the |message_loop_| thread is already gone.
395 set_cancelled(); 394 set_cancelled();
396 return; 395 return;
397 } 396 }
398 397
399 // Switch to the message_loop_ if necessary so we can access |watches_|. 398 // Switch to the message_loop_ if necessary so we can access |watches_|.
400 if (!message_loop()->BelongsToCurrentThread()) { 399 if (!message_loop()->BelongsToCurrentThread()) {
401 message_loop()->PostTask(FROM_HERE, 400 message_loop()->PostTask(FROM_HERE,
402 base::Bind(&FilePathWatcher::CancelWatch, 401 base::Bind(&FilePathWatcher::CancelWatch,
403 make_scoped_refptr(this))); 402 make_scoped_refptr(this)));
404 } else { 403 } else {
405 CancelOnMessageLoopThread(); 404 CancelOnMessageLoopThread();
406 } 405 }
407 } 406 }
408 407
409 void FilePathWatcherImpl::CancelOnMessageLoopThread() { 408 void FilePathWatcherImpl::CancelOnMessageLoopThread() {
410 if (!is_cancelled()) 409 if (!is_cancelled())
411 set_cancelled(); 410 set_cancelled();
412 411
413 if (delegate_) { 412 if (!callback_.is_null()) {
414 MessageLoop::current()->RemoveDestructionObserver(this); 413 MessageLoop::current()->RemoveDestructionObserver(this);
415 delegate_ = NULL; 414 callback_.Reset();
416 } 415 }
417 416
418 for (WatchVector::iterator watch_entry(watches_.begin()); 417 for (WatchVector::iterator watch_entry(watches_.begin());
419 watch_entry != watches_.end(); ++watch_entry) { 418 watch_entry != watches_.end(); ++watch_entry) {
420 if (watch_entry->watch_ != InotifyReader::kInvalidWatch) 419 if (watch_entry->watch_ != InotifyReader::kInvalidWatch)
421 g_inotify_reader.Get().RemoveWatch(watch_entry->watch_, this); 420 g_inotify_reader.Get().RemoveWatch(watch_entry->watch_, this);
422 } 421 }
423 watches_.clear(); 422 watches_.clear();
424 target_.clear(); 423 target_.clear();
425 } 424 }
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
481 } 480 }
482 481
483 } // namespace 482 } // namespace
484 483
485 FilePathWatcher::FilePathWatcher() { 484 FilePathWatcher::FilePathWatcher() {
486 impl_ = new FilePathWatcherImpl(); 485 impl_ = new FilePathWatcherImpl();
487 } 486 }
488 487
489 } // namespace files 488 } // namespace files
490 } // namespace base 489 } // namespace base
OLDNEW
« no previous file with comments | « base/files/file_path_watcher_kqueue.cc ('k') | base/files/file_path_watcher_stub.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698