Home | History | Annotate | Download | only in files
      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 
     58     scoped_refptr<SequencedTaskRunner> task_runner() const {
     59       return task_runner_;
     60     }
     61 
     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.
     67     void set_cancelled() {
     68       cancelled_ = true;
     69     }
     70 
     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