| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/common/file_path_watcher/file_path_watcher.h" | 5 #include "base/files/file_path_watcher.h" |
| 6 | 6 |
| 7 #include <errno.h> | 7 #include <errno.h> |
| 8 #include <string.h> | 8 #include <string.h> |
| 9 #include <sys/inotify.h> | 9 #include <sys/inotify.h> |
| 10 #include <sys/ioctl.h> | 10 #include <sys/ioctl.h> |
| 11 #include <sys/select.h> | 11 #include <sys/select.h> |
| 12 #include <unistd.h> | 12 #include <unistd.h> |
| 13 | 13 |
| 14 #include <algorithm> | 14 #include <algorithm> |
| 15 #include <set> | 15 #include <set> |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 73 | 73 |
| 74 // Use self-pipe trick to unblock select during shutdown. | 74 // Use self-pipe trick to unblock select during shutdown. |
| 75 int shutdown_pipe_[2]; | 75 int shutdown_pipe_[2]; |
| 76 | 76 |
| 77 // Flag set to true when startup was successful. | 77 // Flag set to true when startup was successful. |
| 78 bool valid_; | 78 bool valid_; |
| 79 | 79 |
| 80 DISALLOW_COPY_AND_ASSIGN(InotifyReader); | 80 DISALLOW_COPY_AND_ASSIGN(InotifyReader); |
| 81 }; | 81 }; |
| 82 | 82 |
| 83 class FilePathWatcherImpl : public FilePathWatcher::PlatformDelegate, | 83 class FilePathWatcherImpl |
| 84 public MessageLoop::DestructionObserver { | 84 : public base::files::FilePathWatcher::PlatformDelegate, |
| 85 public MessageLoop::DestructionObserver { |
| 85 public: | 86 public: |
| 86 FilePathWatcherImpl(); | 87 FilePathWatcherImpl(); |
| 87 | 88 |
| 88 // Called for each event coming from the watch. |fired_watch| identifies the | 89 // Called for each event coming from the watch. |fired_watch| identifies the |
| 89 // watch that fired, |child| indicates what has changed, and is relative to | 90 // watch that fired, |child| indicates what has changed, and is relative to |
| 90 // the currently watched path for |fired_watch|. The flag |created| is true if | 91 // the currently watched path for |fired_watch|. The flag |created| is true if |
| 91 // the object appears, and |is_directory| is set when the event refers to a | 92 // the object appears, and |is_directory| is set when the event refers to a |
| 92 // directory. | 93 // directory. |
| 93 void OnFilePathChanged(InotifyReader::Watch fired_watch, | 94 void OnFilePathChanged(InotifyReader::Watch fired_watch, |
| 94 const FilePath::StringType& child, | 95 const FilePath::StringType& child, |
| 95 bool created, | 96 bool created, |
| 96 bool is_directory); | 97 bool is_directory); |
| 97 | 98 |
| 98 // Start watching |path| for changes and notify |delegate| on each change. | 99 // Start watching |path| for changes and notify |delegate| on each change. |
| 99 // Returns true if watch for |path| has been added successfully. | 100 // Returns true if watch for |path| has been added successfully. |
| 100 virtual bool Watch(const FilePath& path, | 101 virtual bool Watch(const FilePath& path, |
| 101 FilePathWatcher::Delegate* delegate) OVERRIDE; | 102 base::files::FilePathWatcher::Delegate* delegate) OVERRIDE; |
| 102 | 103 |
| 103 // Cancel the watch. This unregisters the instance with InotifyReader. | 104 // Cancel the watch. This unregisters the instance with InotifyReader. |
| 104 virtual void Cancel() OVERRIDE; | 105 virtual void Cancel() OVERRIDE; |
| 105 | 106 |
| 106 // Deletion of the FilePathWatcher will call Cancel() to dispose of this | 107 // Deletion of the FilePathWatcher will call Cancel() to dispose of this |
| 107 // object in the right thread. This also observes destruction of the required | 108 // object in the right thread. This also observes destruction of the required |
| 108 // cleanup thread, in case it quits before Cancel() is called. | 109 // cleanup thread, in case it quits before Cancel() is called. |
| 109 virtual void WillDestroyCurrentMessageLoop() OVERRIDE; | 110 virtual void WillDestroyCurrentMessageLoop() OVERRIDE; |
| 110 | 111 |
| 111 private: | 112 private: |
| (...skipping 13 matching lines...) Expand all Loading... |
| 125 InotifyReader::Watch watch_; | 126 InotifyReader::Watch watch_; |
| 126 FilePath::StringType subdir_; | 127 FilePath::StringType subdir_; |
| 127 }; | 128 }; |
| 128 typedef std::vector<WatchEntry> WatchVector; | 129 typedef std::vector<WatchEntry> WatchVector; |
| 129 | 130 |
| 130 // Reconfigure to watch for the most specific parent directory of |target_| | 131 // Reconfigure to watch for the most specific parent directory of |target_| |
| 131 // that exists. Updates |watched_path_|. Returns true on success. | 132 // that exists. Updates |watched_path_|. Returns true on success. |
| 132 bool UpdateWatches() WARN_UNUSED_RESULT; | 133 bool UpdateWatches() WARN_UNUSED_RESULT; |
| 133 | 134 |
| 134 // Delegate to notify upon changes. | 135 // Delegate to notify upon changes. |
| 135 scoped_refptr<FilePathWatcher::Delegate> delegate_; | 136 scoped_refptr<base::files::FilePathWatcher::Delegate> delegate_; |
| 136 | 137 |
| 137 // The file or directory we're supposed to watch. | 138 // The file or directory we're supposed to watch. |
| 138 FilePath target_; | 139 FilePath target_; |
| 139 | 140 |
| 140 // The vector of watches and next component names for all path components, | 141 // The vector of watches and next component names for all path components, |
| 141 // starting at the root directory. The last entry corresponds to the watch for | 142 // starting at the root directory. The last entry corresponds to the watch for |
| 142 // |target_| and always stores an empty next component name in |subdir_|. | 143 // |target_| and always stores an empty next component name in |subdir_|. |
| 143 WatchVector watches_; | 144 WatchVector watches_; |
| 144 | 145 |
| 145 DISALLOW_COPY_AND_ASSIGN(FilePathWatcherImpl); | 146 DISALLOW_COPY_AND_ASSIGN(FilePathWatcherImpl); |
| (...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 355 // disappears in this case. | 356 // disappears in this case. |
| 356 // - One of the parent directories appears. The event corresponding to the | 357 // - One of the parent directories appears. The event corresponding to the |
| 357 // target appearing might have been missed in this case, so recheck. | 358 // target appearing might have been missed in this case, so recheck. |
| 358 if (target_changed || | 359 if (target_changed || |
| 359 (change_on_target_path && !created) || | 360 (change_on_target_path && !created) || |
| 360 (change_on_target_path && file_util::PathExists(target_))) { | 361 (change_on_target_path && file_util::PathExists(target_))) { |
| 361 delegate_->OnFilePathChanged(target_); | 362 delegate_->OnFilePathChanged(target_); |
| 362 } | 363 } |
| 363 } | 364 } |
| 364 | 365 |
| 365 bool FilePathWatcherImpl::Watch(const FilePath& path, | 366 bool FilePathWatcherImpl::Watch( |
| 366 FilePathWatcher::Delegate* delegate) { | 367 const FilePath& path, |
| 368 base::files::FilePathWatcher::Delegate* delegate) { |
| 367 DCHECK(target_.empty()); | 369 DCHECK(target_.empty()); |
| 368 DCHECK(MessageLoopForIO::current()); | 370 DCHECK(MessageLoopForIO::current()); |
| 369 | 371 |
| 370 set_message_loop(base::MessageLoopProxy::CreateForCurrentThread()); | 372 set_message_loop(base::MessageLoopProxy::CreateForCurrentThread()); |
| 371 delegate_ = delegate; | 373 delegate_ = delegate; |
| 372 target_ = path; | 374 target_ = path; |
| 373 MessageLoop::current()->AddDestructionObserver(this); | 375 MessageLoop::current()->AddDestructionObserver(this); |
| 374 | 376 |
| 375 std::vector<FilePath::StringType> comps; | 377 std::vector<FilePath::StringType> comps; |
| 376 target_.GetComponents(&comps); | 378 target_.GetComponents(&comps); |
| 377 DCHECK(!comps.empty()); | 379 DCHECK(!comps.empty()); |
| 378 for (std::vector<FilePath::StringType>::const_iterator comp(++comps.begin()); | 380 for (std::vector<FilePath::StringType>::const_iterator comp(++comps.begin()); |
| 379 comp != comps.end(); ++comp) { | 381 comp != comps.end(); ++comp) { |
| 380 watches_.push_back(WatchEntry(InotifyReader::kInvalidWatch, *comp)); | 382 watches_.push_back(WatchEntry(InotifyReader::kInvalidWatch, *comp)); |
| 381 } | 383 } |
| 382 watches_.push_back(WatchEntry(InotifyReader::kInvalidWatch, | 384 watches_.push_back(WatchEntry(InotifyReader::kInvalidWatch, |
| 383 FilePath::StringType())); | 385 FilePath::StringType())); |
| 384 return UpdateWatches(); | 386 return UpdateWatches(); |
| 385 } | 387 } |
| 386 | 388 |
| 387 void FilePathWatcherImpl::Cancel() { | 389 void FilePathWatcherImpl::Cancel() { |
| 388 if (!delegate_) { | 390 if (!delegate_) { |
| 389 // Watch was never called, or the |message_loop_| thread is already gone. | 391 // Watch was never called, or the |message_loop_| thread is already gone. |
| 390 set_cancelled(); | 392 set_cancelled(); |
| 391 return; | 393 return; |
| 392 } | 394 } |
| 393 | 395 |
| 394 // Switch to the message_loop_ if necessary so we can access |watches_|. | 396 // Switch to the message_loop_ if necessary so we can access |watches_|. |
| 395 if (!message_loop()->BelongsToCurrentThread()) { | 397 if (!message_loop()->BelongsToCurrentThread()) { |
| 396 message_loop()->PostTask(FROM_HERE, | 398 message_loop()->PostTask( |
| 397 new FilePathWatcher::CancelTask(this)); | 399 FROM_HERE, |
| 400 new base::files::FilePathWatcher::CancelTask(this)); |
| 398 } else { | 401 } else { |
| 399 CancelOnMessageLoopThread(); | 402 CancelOnMessageLoopThread(); |
| 400 } | 403 } |
| 401 } | 404 } |
| 402 | 405 |
| 403 void FilePathWatcherImpl::CancelOnMessageLoopThread() { | 406 void FilePathWatcherImpl::CancelOnMessageLoopThread() { |
| 404 if (!is_cancelled()) { | 407 if (!is_cancelled()) { |
| 405 set_cancelled(); | 408 set_cancelled(); |
| 406 MessageLoop::current()->RemoveDestructionObserver(this); | 409 MessageLoop::current()->RemoveDestructionObserver(this); |
| 407 | 410 |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 444 g_inotify_reader.Get().RemoveWatch(old_watch, this); | 447 g_inotify_reader.Get().RemoveWatch(old_watch, this); |
| 445 } | 448 } |
| 446 path = path.Append(watch_entry->subdir_); | 449 path = path.Append(watch_entry->subdir_); |
| 447 } | 450 } |
| 448 | 451 |
| 449 return true; | 452 return true; |
| 450 } | 453 } |
| 451 | 454 |
| 452 } // namespace | 455 } // namespace |
| 453 | 456 |
| 454 FilePathWatcher::FilePathWatcher() { | 457 base::files::FilePathWatcher::FilePathWatcher() { |
| 455 impl_ = new FilePathWatcherImpl(); | 458 impl_ = new FilePathWatcherImpl(); |
| 456 } | 459 } |
| OLD | NEW |