Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(28)

Side by Side Diff: base/directory_watcher_mac.cc

Issue 99057: Add DirectoryWatcher implementation for Mac. (Closed)
Patch Set: scoped_cftyperef Created 11 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « base/base.gyp ('k') | base/directory_watcher_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2009 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 <CoreServices/CoreServices.h>
8
9 #include "base/file_path.h"
10 #include "base/file_util.h"
11 #include "base/logging.h"
12 #include "base/message_loop.h"
13 #include "base/scoped_cftyperef.h"
14
15 namespace {
16
17 const CFAbsoluteTime kEventLatencySeconds = 0.3;
18
19 class DirectoryWatcherImpl : public DirectoryWatcher::PlatformDelegate {
20 public:
21 DirectoryWatcherImpl() {}
22 ~DirectoryWatcherImpl() {
23 if (!path_.value().empty()) {
24 FSEventStreamStop(fsevent_stream_);
25 FSEventStreamInvalidate(fsevent_stream_);
26 FSEventStreamRelease(fsevent_stream_);
27 }
28 }
29
30 virtual bool Watch(const FilePath& path, DirectoryWatcher::Delegate* delegate,
31 bool recursive);
32
33 void OnFSEventsCallback(const FilePath& event_path) {
34 DCHECK(!path_.value().empty());
35 if (!recursive_) {
36 FilePath absolute_event_path = event_path;
37 if (!file_util::AbsolutePath(&absolute_event_path))
38 return;
39 if (absolute_event_path != path_)
40 return;
41 }
42 delegate_->OnDirectoryChanged(path_);
43 }
44
45 private:
46 // Delegate to notify upon changes.
47 DirectoryWatcher::Delegate* delegate_;
48
49 // Path we're watching (passed to delegate).
50 FilePath path_;
51
52 // Indicates recursive watch.
53 bool recursive_;
54
55 // Backend stream we receive event callbacks from (strong reference).
56 FSEventStreamRef fsevent_stream_;
57
58 DISALLOW_COPY_AND_ASSIGN(DirectoryWatcherImpl);
59 };
60
61 void FSEventsCallback(ConstFSEventStreamRef stream,
62 void* event_watcher, size_t num_events,
63 void* event_paths, const FSEventStreamEventFlags flags[],
64 const FSEventStreamEventId event_ids[]) {
65 char** paths = reinterpret_cast<char**>(event_paths);
66 DirectoryWatcherImpl* watcher =
67 reinterpret_cast<DirectoryWatcherImpl*> (event_watcher);
68 for (size_t i = 0; i < num_events; i++) {
69 watcher->OnFSEventsCallback(FilePath(paths[i]));
70 }
71 }
72
73 bool DirectoryWatcherImpl::Watch(const FilePath& path,
74 DirectoryWatcher::Delegate* delegate,
75 bool recursive) {
76 DCHECK(path_.value().empty()); // Can only watch one path.
77
78 DCHECK(MessageLoop::current()->type() == MessageLoop::TYPE_UI);
79
80 if (!file_util::PathExists(path))
81 return false;
82
83 path_ = path;
84 if (!file_util::AbsolutePath(&path_)) {
85 path_ = FilePath(); // Make sure we're marked as not-in-use.
86 return false;
87 }
88 delegate_ = delegate;
89 recursive_ = recursive;
90
91 scoped_cftyperef<CFStringRef> cf_path(CFStringCreateWithCString(
92 NULL, path.value().c_str(), kCFStringEncodingMacHFS));
93 CFStringRef path_for_array = cf_path.get();
94 scoped_cftyperef<CFArrayRef> watched_paths(CFArrayCreate(
95 NULL, reinterpret_cast<const void**>(&path_for_array), 1,
96 &kCFTypeArrayCallBacks));
97
98 FSEventStreamContext context;
99 context.version = 0;
100 context.info = this;
101 context.retain = NULL;
102 context.release = NULL;
103 context.copyDescription = NULL;
104
105 fsevent_stream_ = FSEventStreamCreate(NULL, &FSEventsCallback, &context,
106 watched_paths,
107 kFSEventStreamEventIdSinceNow,
108 kEventLatencySeconds,
109 kFSEventStreamCreateFlagNone);
110 FSEventStreamScheduleWithRunLoop(fsevent_stream_, CFRunLoopGetCurrent(),
111 kCFRunLoopDefaultMode);
112 FSEventStreamStart(fsevent_stream_);
113
114 return true;
115 }
116
117 } // namespace
118
119 DirectoryWatcher::DirectoryWatcher() {
120 impl_ = new DirectoryWatcherImpl();
121 }
OLDNEW
« no previous file with comments | « base/base.gyp ('k') | base/directory_watcher_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698