15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This module provides a way to monitor a file or directory for changes.
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef BASE_FILES_FILE_PATH_WATCHER_H_
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define BASE_FILES_FILE_PATH_WATCHER_H_
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/base_export.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/callback.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/ref_counted.h"
15868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/message_loop/message_loop_proxy.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace base {
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This class lets you register interest in changes on a FilePath.
20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// The callback will get called whenever the file or directory referenced by the
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// FilePath is changed, including created or deleted. Due to limitations in the
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// underlying OS APIs, FilePathWatcher has slightly different semantics on OS X
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// than on Windows or Linux. FilePathWatcher on Linux and Windows will detect
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// modifications to files in a watched directory. FilePathWatcher on Mac will
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// detect the creation and deletion of files in a watched directory, but will
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// not detect modifications to those files. See file_path_watcher_kqueue.cc for
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// details.
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class BASE_EXPORT FilePathWatcher {
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Callback type for Watch(). |path| points to the file that was updated,
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and |error| is true if the platform specific code detected an error. In
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // that case, the callback won't be invoked again.
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef base::Callback<void(const FilePath& path, bool error)> Callback;
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Used internally to encapsulate different members on different platforms.
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  class PlatformDelegate : public base::RefCountedThreadSafe<PlatformDelegate> {
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   public:
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PlatformDelegate();
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Start watching for the given |path| and notify |delegate| about changes.
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    virtual bool Watch(const FilePath& path,
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       bool recursive,
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       const Callback& callback) WARN_UNUSED_RESULT = 0;
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Stop watching. This is called from FilePathWatcher's dtor in order to
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // allow to shut down properly while the object is still alive.
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // It can be called from any thread.
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    virtual void Cancel() = 0;
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   protected:
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    friend class base::RefCountedThreadSafe<PlatformDelegate>;
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    friend class FilePathWatcher;
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    virtual ~PlatformDelegate();
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Stop watching. This is only called on the thread of the appropriate
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // message loop. Since it can also be called more than once, it should
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // check |is_cancelled()| to avoid duplicate work.
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    virtual void CancelOnMessageLoopThread() = 0;
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<base::MessageLoopProxy> message_loop() const {
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return message_loop_;
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void set_message_loop(base::MessageLoopProxy* loop) {
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      message_loop_ = loop;
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Must be called before the PlatformDelegate is deleted.
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void set_cancelled() {
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cancelled_ = true;
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool is_cancelled() const {
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return cancelled_;
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   private:
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<base::MessageLoopProxy> message_loop_;
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool cancelled_;
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FilePathWatcher();
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~FilePathWatcher();
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // A callback that always cleans up the PlatformDelegate, either when executed
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // or when deleted without having been executed at all, as can happen during
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // shutdown.
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void CancelWatch(const scoped_refptr<PlatformDelegate>& delegate);
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
91f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Returns true if the platform and OS version support recursive watches.
92f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  static bool RecursiveWatchAvailable();
93f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Invokes |callback| whenever updates to |path| are detected. This should be
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // called at most once, and from a MessageLoop of TYPE_IO. Set |recursive| to
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // true, to watch |path| and its children. The callback will be invoked on
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // the same loop. Returns true on success.
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //
99f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Recursive watch is not supported on all platforms and file systems.
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Watch() will return false in the case of failure.
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool Watch(const FilePath& path, bool recursive, const Callback& callback);
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<PlatformDelegate> impl_;
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(FilePathWatcher);
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace base
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // BASE_FILES_FILE_PATH_WATCHER_H_
112