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 "base/base_export.h"
     11 #include "base/basictypes.h"
     12 #include "base/callback.h"
     13 #include "base/files/file_path.h"
     14 #include "base/memory/ref_counted.h"
     15 #include "base/message_loop/message_loop_proxy.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 
     61     scoped_refptr<base::MessageLoopProxy> message_loop() const {
     62       return message_loop_;
     63     }
     64 
     65     void set_message_loop(const scoped_refptr<base::MessageLoopProxy>& loop) {
     66       message_loop_ = loop;
     67     }
     68 
     69     // Must be called before the PlatformDelegate is deleted.
     70     void set_cancelled() {
     71       cancelled_ = true;
     72     }
     73 
     74     bool is_cancelled() const {
     75       return cancelled_;
     76     }
     77 
     78    private:
     79     scoped_refptr<base::MessageLoopProxy> message_loop_;
     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