blob: e318d4b7acd6ecdc101bc58215ee0a79fbcb2b3e (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
|
// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/directory_watcher.h"
#include "base/file_path.h"
#include "base/logging.h"
#include "base/object_watcher.h"
#include "base/ref_counted.h"
namespace {
class DirectoryWatcherImpl : public DirectoryWatcher::PlatformDelegate,
public base::ObjectWatcher::Delegate {
public:
DirectoryWatcherImpl() : delegate_(NULL), handle_(INVALID_HANDLE_VALUE) {}
virtual bool Watch(const FilePath& path, DirectoryWatcher::Delegate* delegate,
MessageLoop* backend_loop, bool recursive);
// Callback from MessageLoopForIO.
virtual void OnObjectSignaled(HANDLE object);
private:
virtual ~DirectoryWatcherImpl();
// Delegate to notify upon changes.
DirectoryWatcher::Delegate* delegate_;
// Path we're watching (passed to delegate).
FilePath path_;
// Handle for FindFirstChangeNotification.
HANDLE handle_;
// ObjectWatcher to watch handle_ for events.
base::ObjectWatcher watcher_;
DISALLOW_COPY_AND_ASSIGN(DirectoryWatcherImpl);
};
DirectoryWatcherImpl::~DirectoryWatcherImpl() {
if (handle_ != INVALID_HANDLE_VALUE) {
watcher_.StopWatching();
FindCloseChangeNotification(handle_);
}
}
bool DirectoryWatcherImpl::Watch(const FilePath& path,
DirectoryWatcher::Delegate* delegate,
MessageLoop* backend_loop, bool recursive) {
DCHECK(path_.value().empty()); // Can only watch one path.
handle_ = FindFirstChangeNotification(
path.value().c_str(),
recursive,
FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_SIZE |
FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_DIR_NAME);
if (handle_ == INVALID_HANDLE_VALUE)
return false;
delegate_ = delegate;
path_ = path;
watcher_.StartWatching(handle_, this);
return true;
}
void DirectoryWatcherImpl::OnObjectSignaled(HANDLE object) {
DCHECK(object == handle_);
// Make sure we stay alive through the body of this function.
scoped_refptr<DirectoryWatcherImpl> keep_alive(this);
delegate_->OnDirectoryChanged(path_);
// Register for more notifications on file change.
BOOL ok = FindNextChangeNotification(object);
DCHECK(ok);
watcher_.StartWatching(object, this);
}
} // namespace
DirectoryWatcher::DirectoryWatcher() {
impl_ = new DirectoryWatcherImpl();
}
|