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

Unified Diff: base/directory_watcher_mac.cc

Issue 99057: Add DirectoryWatcher implementation for Mac. (Closed)
Patch Set: scoped_cftyperef Created 11 years, 8 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « base/base.gyp ('k') | base/directory_watcher_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: base/directory_watcher_mac.cc
diff --git a/base/directory_watcher_mac.cc b/base/directory_watcher_mac.cc
new file mode 100644
index 0000000000000000000000000000000000000000..d4b3082e994b67bb925d658c0567985573292722
--- /dev/null
+++ b/base/directory_watcher_mac.cc
@@ -0,0 +1,121 @@
+// 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 <CoreServices/CoreServices.h>
+
+#include "base/file_path.h"
+#include "base/file_util.h"
+#include "base/logging.h"
+#include "base/message_loop.h"
+#include "base/scoped_cftyperef.h"
+
+namespace {
+
+const CFAbsoluteTime kEventLatencySeconds = 0.3;
+
+class DirectoryWatcherImpl : public DirectoryWatcher::PlatformDelegate {
+ public:
+ DirectoryWatcherImpl() {}
+ ~DirectoryWatcherImpl() {
+ if (!path_.value().empty()) {
+ FSEventStreamStop(fsevent_stream_);
+ FSEventStreamInvalidate(fsevent_stream_);
+ FSEventStreamRelease(fsevent_stream_);
+ }
+ }
+
+ virtual bool Watch(const FilePath& path, DirectoryWatcher::Delegate* delegate,
+ bool recursive);
+
+ void OnFSEventsCallback(const FilePath& event_path) {
+ DCHECK(!path_.value().empty());
+ if (!recursive_) {
+ FilePath absolute_event_path = event_path;
+ if (!file_util::AbsolutePath(&absolute_event_path))
+ return;
+ if (absolute_event_path != path_)
+ return;
+ }
+ delegate_->OnDirectoryChanged(path_);
+ }
+
+ private:
+ // Delegate to notify upon changes.
+ DirectoryWatcher::Delegate* delegate_;
+
+ // Path we're watching (passed to delegate).
+ FilePath path_;
+
+ // Indicates recursive watch.
+ bool recursive_;
+
+ // Backend stream we receive event callbacks from (strong reference).
+ FSEventStreamRef fsevent_stream_;
+
+ DISALLOW_COPY_AND_ASSIGN(DirectoryWatcherImpl);
+};
+
+void FSEventsCallback(ConstFSEventStreamRef stream,
+ void* event_watcher, size_t num_events,
+ void* event_paths, const FSEventStreamEventFlags flags[],
+ const FSEventStreamEventId event_ids[]) {
+ char** paths = reinterpret_cast<char**>(event_paths);
+ DirectoryWatcherImpl* watcher =
+ reinterpret_cast<DirectoryWatcherImpl*> (event_watcher);
+ for (size_t i = 0; i < num_events; i++) {
+ watcher->OnFSEventsCallback(FilePath(paths[i]));
+ }
+}
+
+bool DirectoryWatcherImpl::Watch(const FilePath& path,
+ DirectoryWatcher::Delegate* delegate,
+ bool recursive) {
+ DCHECK(path_.value().empty()); // Can only watch one path.
+
+ DCHECK(MessageLoop::current()->type() == MessageLoop::TYPE_UI);
+
+ if (!file_util::PathExists(path))
+ return false;
+
+ path_ = path;
+ if (!file_util::AbsolutePath(&path_)) {
+ path_ = FilePath(); // Make sure we're marked as not-in-use.
+ return false;
+ }
+ delegate_ = delegate;
+ recursive_ = recursive;
+
+ scoped_cftyperef<CFStringRef> cf_path(CFStringCreateWithCString(
+ NULL, path.value().c_str(), kCFStringEncodingMacHFS));
+ CFStringRef path_for_array = cf_path.get();
+ scoped_cftyperef<CFArrayRef> watched_paths(CFArrayCreate(
+ NULL, reinterpret_cast<const void**>(&path_for_array), 1,
+ &kCFTypeArrayCallBacks));
+
+ FSEventStreamContext context;
+ context.version = 0;
+ context.info = this;
+ context.retain = NULL;
+ context.release = NULL;
+ context.copyDescription = NULL;
+
+ fsevent_stream_ = FSEventStreamCreate(NULL, &FSEventsCallback, &context,
+ watched_paths,
+ kFSEventStreamEventIdSinceNow,
+ kEventLatencySeconds,
+ kFSEventStreamCreateFlagNone);
+ FSEventStreamScheduleWithRunLoop(fsevent_stream_, CFRunLoopGetCurrent(),
+ kCFRunLoopDefaultMode);
+ FSEventStreamStart(fsevent_stream_);
+
+ return true;
+}
+
+} // namespace
+
+DirectoryWatcher::DirectoryWatcher() {
+ impl_ = new DirectoryWatcherImpl();
+}
« 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