blob: f9782779ba4fbdb01bdf997f6123baa76a3cd686 [file] [log] [blame]
[email protected]9e8d4f92008-10-17 02:45:561// Copyright (c) 2006-2008 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#include "base/directory_watcher.h"
6
7#include "base/file_path.h"
8#include "base/object_watcher.h"
9
10// Private implementation class implementing the behavior of DirectoryWatcher.
11class DirectoryWatcher::Impl : public base::RefCounted<DirectoryWatcher::Impl>,
12 public base::ObjectWatcher::Delegate {
13 public:
14 Impl(DirectoryWatcher::Delegate* delegate)
15 : delegate_(delegate), handle_(INVALID_HANDLE_VALUE) {}
16 ~Impl();
17
18 // Register interest in any changes in |path|.
19 // Returns false on error.
20 bool Watch(const FilePath& path);
21
22 // Callback from MessageLoopForIO.
23 virtual void OnObjectSignaled(HANDLE object);
24
25 private:
26 // Delegate to notify upon changes.
27 DirectoryWatcher::Delegate* delegate_;
28 // Path we're watching (passed to delegate).
29 FilePath path_;
30 // Handle for FindFirstChangeNotification.
31 HANDLE handle_;
32 // ObjectWatcher to watch handle_ for events.
33 base::ObjectWatcher watcher_;
34};
35
36DirectoryWatcher::Impl::~Impl() {
37 if (handle_ != INVALID_HANDLE_VALUE) {
38 watcher_.StopWatching();
39 FindCloseChangeNotification(handle_);
40 }
41}
42
43bool DirectoryWatcher::Impl::Watch(const FilePath& path) {
44 DCHECK(path_.value().empty()); // Can only watch one path.
[email protected]9e8d4f92008-10-17 02:45:5645
[email protected]bdbc87c2009-01-25 05:08:5446 // NOTE: If you want to change this code to *not* watch subdirectories, have a
47 // look at http://code.google.com/p/chromium/issues/detail?id=5072 first.
[email protected]9e8d4f92008-10-17 02:45:5648 handle_ = FindFirstChangeNotification(
49 path.value().c_str(),
[email protected]bdbc87c2009-01-25 05:08:5450 TRUE, // Watch subtree.
[email protected]9e8d4f92008-10-17 02:45:5651 FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_SIZE |
52 FILE_NOTIFY_CHANGE_LAST_WRITE);
[email protected]cfa428e2009-01-07 22:19:5053 if (handle_ == INVALID_HANDLE_VALUE)
[email protected]9e8d4f92008-10-17 02:45:5654 return false;
[email protected]9e8d4f92008-10-17 02:45:5655
56 path_ = path;
57 watcher_.StartWatching(handle_, this);
58
59 return true;
60}
61
62void DirectoryWatcher::Impl::OnObjectSignaled(HANDLE object) {
63 DCHECK(object == handle_);
64 // Make sure we stay alive through the body of this function.
65 scoped_refptr<DirectoryWatcher::Impl> keep_alive(this);
66
67 delegate_->OnDirectoryChanged(path_);
68
69 // Register for more notifications on file change.
70 BOOL ok = FindNextChangeNotification(object);
71 DCHECK(ok);
72 watcher_.StartWatching(object, this);
73}
74
75DirectoryWatcher::DirectoryWatcher() {
76}
77
78DirectoryWatcher::~DirectoryWatcher() {
79 // Declared in .cc file for access to ~DirectoryWatcher::Impl.
80}
81
82bool DirectoryWatcher::Watch(const FilePath& path,
83 Delegate* delegate) {
84 impl_ = new DirectoryWatcher::Impl(delegate);
85 return impl_->Watch(path);
86}