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