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

Unified Diff: chrome/browser/file_path_watcher_mac.cc

Issue 5606002: Move:... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 10 years 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 | « chrome/browser/file_path_watcher_inotify.cc ('k') | chrome/browser/file_path_watcher_stub.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/file_path_watcher_mac.cc
===================================================================
--- chrome/browser/file_path_watcher_mac.cc (revision 68044)
+++ chrome/browser/file_path_watcher_mac.cc (working copy)
@@ -1,232 +0,0 @@
-// 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 "chrome/browser/file_path_watcher.h"
-
-#include <CoreServices/CoreServices.h>
-#include <set>
-
-#include "base/file_path.h"
-#include "base/file_util.h"
-#include "base/logging.h"
-#include "base/mac/scoped_cftyperef.h"
-#include "base/singleton.h"
-#include "base/time.h"
-
-namespace {
-
-// The latency parameter passed to FSEventsStreamCreate().
-const CFAbsoluteTime kEventLatencySeconds = 0.3;
-
-// Mac-specific file watcher implementation based on the FSEvents API.
-class FilePathWatcherImpl : public FilePathWatcher::PlatformDelegate {
- public:
- FilePathWatcherImpl();
- virtual ~FilePathWatcherImpl() {}
-
- // Called from the FSEvents callback whenever there is a change to the paths
- void OnFilePathChanged();
-
- // (Re-)Initialize the event stream to start reporting events from
- // |start_event|.
- void UpdateEventStream(FSEventStreamEventId start_event);
-
- // FilePathWatcher::PlatformDelegate overrides.
- virtual bool Watch(const FilePath& path, FilePathWatcher::Delegate* delegate);
- virtual void Cancel();
-
- private:
- // Destroy the event stream.
- void DestroyEventStream();
-
- // Delegate to notify upon changes.
- scoped_refptr<FilePathWatcher::Delegate> delegate_;
-
- // Target path to watch (passed to delegate).
- FilePath target_;
-
- // Keep track of the last modified time of the file. We use nulltime
- // to represent the file not existing.
- base::Time last_modified_;
-
- // The time at which we processed the first notification with the
- // |last_modified_| time stamp.
- base::Time first_notification_;
-
- // Backend stream we receive event callbacks from (strong reference).
- FSEventStreamRef fsevent_stream_;
-
- // Used to detect early cancellation.
- bool canceled_;
-
- DISALLOW_COPY_AND_ASSIGN(FilePathWatcherImpl);
-};
-
-// The callback passed to FSEventStreamCreate().
-void FSEventsCallback(ConstFSEventStreamRef stream,
- void* event_watcher, size_t num_events,
- void* event_paths, const FSEventStreamEventFlags flags[],
- const FSEventStreamEventId event_ids[]) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
- FilePathWatcherImpl* watcher =
- reinterpret_cast<FilePathWatcherImpl*>(event_watcher);
- bool root_changed = false;
- FSEventStreamEventId root_change_at = FSEventStreamGetLatestEventId(stream);
- for (size_t i = 0; i < num_events; i++) {
- if (flags[i] & kFSEventStreamEventFlagRootChanged)
- root_changed = true;
- if (event_ids[i])
- root_change_at = std::min(root_change_at, event_ids[i]);
- }
-
- // Reinitialize the event stream if we find changes to the root. This is
- // necessary since FSEvents doesn't report any events for the subtree after
- // the directory to be watched gets created.
- if (root_changed) {
- // Resetting the event stream from within the callback fails (FSEvents spews
- // bad file descriptor errors), so post a task to do the reset.
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- NewRunnableMethod(watcher, &FilePathWatcherImpl::UpdateEventStream,
- root_change_at));
- }
-
- BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
- NewRunnableMethod(watcher, &FilePathWatcherImpl::OnFilePathChanged));
-}
-
-// FilePathWatcherImpl implementation:
-
-FilePathWatcherImpl::FilePathWatcherImpl()
- : fsevent_stream_(NULL),
- canceled_(false) {
-}
-
-void FilePathWatcherImpl::OnFilePathChanged() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
- DCHECK(!target_.empty());
-
- base::PlatformFileInfo file_info;
- bool file_exists = file_util::GetFileInfo(target_, &file_info);
- if (file_exists && (last_modified_.is_null() ||
- last_modified_ != file_info.last_modified)) {
- last_modified_ = file_info.last_modified;
- first_notification_ = base::Time::Now();
- delegate_->OnFilePathChanged(target_);
- } else if (file_exists && !first_notification_.is_null()) {
- // The target's last modification time is equal to what's on record. This
- // means that either an unrelated event occurred, or the target changed
- // again (file modification times only have a resolution of 1s). Comparing
- // file modification times against the wall clock is not reliable to find
- // out whether the change is recent, since this code might just run too
- // late. Moreover, there's no guarantee that file modification time and wall
- // clock times come from the same source.
- //
- // Instead, the time at which the first notification carrying the current
- // |last_notified_| time stamp is recorded. Later notifications that find
- // the same file modification time only need to be forwarded until wall
- // clock has advanced one second from the initial notification. After that
- // interval, client code is guaranteed to having seen the current revision
- // of the file.
- if (base::Time::Now() - first_notification_ >
- base::TimeDelta::FromSeconds(1)) {
- // Stop further notifications for this |last_modification_| time stamp.
- first_notification_ = base::Time();
- }
- delegate_->OnFilePathChanged(target_);
- } else if (!file_exists && !last_modified_.is_null()) {
- last_modified_ = base::Time();
- delegate_->OnFilePathChanged(target_);
- }
-}
-
-bool FilePathWatcherImpl::Watch(const FilePath& path,
- FilePathWatcher::Delegate* delegate) {
- DCHECK(target_.value().empty());
-
- target_ = path;
- delegate_ = delegate;
-
- FSEventStreamEventId start_event = FSEventsGetCurrentEventId();
-
- base::PlatformFileInfo file_info;
- if (file_util::GetFileInfo(target_, &file_info)) {
- last_modified_ = file_info.last_modified;
- first_notification_ = base::Time::Now();
- }
-
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- NewRunnableMethod(this, &FilePathWatcherImpl::UpdateEventStream,
- start_event));
-
- return true;
-}
-
-void FilePathWatcherImpl::Cancel() {
- // Switch to the UI thread if necessary, so we can tear down the event stream.
- if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- NewRunnableMethod(this, &FilePathWatcherImpl::Cancel));
- return;
- }
-
- canceled_ = true;
- if (fsevent_stream_)
- DestroyEventStream();
-}
-
-void FilePathWatcherImpl::UpdateEventStream(FSEventStreamEventId start_event) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
- // It can happen that the watcher gets canceled while tasks that call this
- // function are still in flight, so abort if this situation is detected.
- if (canceled_)
- return;
-
- if (fsevent_stream_)
- DestroyEventStream();
-
- base::mac::ScopedCFTypeRef<CFStringRef> cf_path(CFStringCreateWithCString(
- NULL, target_.value().c_str(), kCFStringEncodingMacHFS));
- base::mac::ScopedCFTypeRef<CFStringRef> cf_dir_path(CFStringCreateWithCString(
- NULL, target_.DirName().value().c_str(), kCFStringEncodingMacHFS));
- CFStringRef paths_array[] = { cf_path.get(), cf_dir_path.get() };
- base::mac::ScopedCFTypeRef<CFArrayRef> watched_paths(CFArrayCreate(
- NULL, reinterpret_cast<const void**>(paths_array), arraysize(paths_array),
- &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,
- start_event,
- kEventLatencySeconds,
- kFSEventStreamCreateFlagWatchRoot);
- FSEventStreamScheduleWithRunLoop(fsevent_stream_, CFRunLoopGetCurrent(),
- kCFRunLoopDefaultMode);
- if (!FSEventStreamStart(fsevent_stream_)) {
- BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
- NewRunnableMethod(delegate_.get(),
- &FilePathWatcher::Delegate::OnError));
- }
-}
-
-void FilePathWatcherImpl::DestroyEventStream() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- FSEventStreamStop(fsevent_stream_);
- FSEventStreamInvalidate(fsevent_stream_);
- FSEventStreamRelease(fsevent_stream_);
- fsevent_stream_ = NULL;
-}
-
-} // namespace
-
-FilePathWatcher::FilePathWatcher() {
- impl_ = new FilePathWatcherImpl();
-}
« no previous file with comments | « chrome/browser/file_path_watcher_inotify.cc ('k') | chrome/browser/file_path_watcher_stub.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698