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 3 // found in the LICENSE file. 4 5 // This module provides a way to monitor a file or directory for changes. 6 7 #ifndef BASE_FILES_FILE_PATH_WATCHER_H_ 8 #define BASE_FILES_FILE_PATH_WATCHER_H_ 9 10 #include "base/base_export.h" 11 #include "base/callback.h" 12 #include "base/files/file_path.h" 13 #include "base/macros.h" 14 #include "base/memory/ref_counted.h" 15 #include "base/single_thread_task_runner.h" 16 17 namespace base { 18 19 // This class lets you register interest in changes on a FilePath. 20 // The callback will get called whenever the file or directory referenced by the 21 // FilePath is changed, including created or deleted. Due to limitations in the 22 // underlying OS APIs, FilePathWatcher has slightly different semantics on OS X 23 // than on Windows or Linux. FilePathWatcher on Linux and Windows will detect 24 // modifications to files in a watched directory. FilePathWatcher on Mac will 25 // detect the creation and deletion of files in a watched directory, but will 26 // not detect modifications to those files. See file_path_watcher_kqueue.cc for 27 // details. 28 class BASE_EXPORT FilePathWatcher { 29 public: 30 // Callback type for Watch(). |path| points to the file that was updated, 31 // and |error| is true if the platform specific code detected an error. In 32 // that case, the callback won't be invoked again. 33 typedef base::Callback<void(const FilePath& path, bool error)> Callback; 34 35 // Used internally to encapsulate different members on different platforms. 36 class PlatformDelegate : public base::RefCountedThreadSafe<PlatformDelegate> { 37 public: 38 PlatformDelegate(); 39 40 // Start watching for the given |path| and notify |delegate| about changes. 41 virtual bool Watch(const FilePath& path, 42 bool recursive, 43 const Callback& callback) WARN_UNUSED_RESULT = 0; 44 45 // Stop watching. This is called from FilePathWatcher's dtor in order to 46 // allow to shut down properly while the object is still alive. 47 // It can be called from any thread. 48 virtual void Cancel() = 0; 49 50 protected: 51 friend class base::RefCountedThreadSafe<PlatformDelegate>; 52 friend class FilePathWatcher; 53 54 virtual ~PlatformDelegate(); 55 56 // Stop watching. This is only called on the thread of the appropriate 57 // message loop. Since it can also be called more than once, it should 58 // check |is_cancelled()| to avoid duplicate work. 59 virtual void CancelOnMessageLoopThread() = 0; 60 task_runner()61 scoped_refptr<base::SingleThreadTaskRunner> task_runner() const { 62 return task_runner_; 63 } 64 set_task_runner(scoped_refptr<base::SingleThreadTaskRunner> runner)65 void set_task_runner(scoped_refptr<base::SingleThreadTaskRunner> runner) { 66 task_runner_ = std::move(runner); 67 } 68 69 // Must be called before the PlatformDelegate is deleted. set_cancelled()70 void set_cancelled() { 71 cancelled_ = true; 72 } 73 is_cancelled()74 bool is_cancelled() const { 75 return cancelled_; 76 } 77 78 private: 79 scoped_refptr<base::SingleThreadTaskRunner> task_runner_; 80 bool cancelled_; 81 }; 82 83 FilePathWatcher(); 84 virtual ~FilePathWatcher(); 85 86 // A callback that always cleans up the PlatformDelegate, either when executed 87 // or when deleted without having been executed at all, as can happen during 88 // shutdown. 89 static void CancelWatch(const scoped_refptr<PlatformDelegate>& delegate); 90 91 // Returns true if the platform and OS version support recursive watches. 92 static bool RecursiveWatchAvailable(); 93 94 // Invokes |callback| whenever updates to |path| are detected. This should be 95 // called at most once, and from a MessageLoop of TYPE_IO. Set |recursive| to 96 // true, to watch |path| and its children. The callback will be invoked on 97 // the same loop. Returns true on success. 98 // 99 // Recursive watch is not supported on all platforms and file systems. 100 // Watch() will return false in the case of failure. 101 bool Watch(const FilePath& path, bool recursive, const Callback& callback); 102 103 private: 104 scoped_refptr<PlatformDelegate> impl_; 105 106 DISALLOW_COPY_AND_ASSIGN(FilePathWatcher); 107 }; 108 109 } // namespace base 110 111 #endif // BASE_FILES_FILE_PATH_WATCHER_H_ 112