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

Unified Diff: base/files/file_path_watcher_win.cc

Issue 1446363003: Deleted OS_WIN and all Windows specific files from base. (Closed) Base URL: https://github.com/domokit/mojo.git@base_tests
Patch Set: Created 5 years, 1 month 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/files/file_path_watcher_unittest.cc ('k') | base/files/file_proxy_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: base/files/file_path_watcher_win.cc
diff --git a/base/files/file_path_watcher_win.cc b/base/files/file_path_watcher_win.cc
deleted file mode 100644
index 081698f8df12daed09679dfa880445cd370c9ea5..0000000000000000000000000000000000000000
--- a/base/files/file_path_watcher_win.cc
+++ /dev/null
@@ -1,300 +0,0 @@
-// Copyright (c) 2011 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/files/file_path_watcher.h"
-
-#include "base/bind.h"
-#include "base/files/file.h"
-#include "base/files/file_path.h"
-#include "base/files/file_util.h"
-#include "base/logging.h"
-#include "base/memory/ref_counted.h"
-#include "base/thread_task_runner_handle.h"
-#include "base/time/time.h"
-#include "base/win/object_watcher.h"
-
-namespace base {
-
-namespace {
-
-class FilePathWatcherImpl : public FilePathWatcher::PlatformDelegate,
- public base::win::ObjectWatcher::Delegate,
- public MessageLoop::DestructionObserver {
- public:
- FilePathWatcherImpl()
- : handle_(INVALID_HANDLE_VALUE),
- recursive_watch_(false) {}
-
- // FilePathWatcher::PlatformDelegate overrides.
- bool Watch(const FilePath& path,
- bool recursive,
- const FilePathWatcher::Callback& callback) override;
- void Cancel() override;
-
- // Deletion of the FilePathWatcher will call Cancel() to dispose of this
- // object in the right thread. This also observes destruction of the required
- // cleanup thread, in case it quits before Cancel() is called.
- void WillDestroyCurrentMessageLoop() override;
-
- // Callback from MessageLoopForIO.
- void OnObjectSignaled(HANDLE object) override;
-
- private:
- ~FilePathWatcherImpl() override {}
-
- // Setup a watch handle for directory |dir|. Set |recursive| to true to watch
- // the directory sub trees. Returns true if no fatal error occurs. |handle|
- // will receive the handle value if |dir| is watchable, otherwise
- // INVALID_HANDLE_VALUE.
- static bool SetupWatchHandle(const FilePath& dir,
- bool recursive,
- HANDLE* handle) WARN_UNUSED_RESULT;
-
- // (Re-)Initialize the watch handle.
- bool UpdateWatch() WARN_UNUSED_RESULT;
-
- // Destroy the watch handle.
- void DestroyWatch();
-
- // Cleans up and stops observing the |task_runner_| thread.
- void CancelOnMessageLoopThread() override;
-
- // Callback to notify upon changes.
- FilePathWatcher::Callback callback_;
-
- // Path we're supposed to watch (passed to callback).
- FilePath target_;
-
- // Handle for FindFirstChangeNotification.
- HANDLE handle_;
-
- // ObjectWatcher to watch handle_ for events.
- base::win::ObjectWatcher watcher_;
-
- // Set to true to watch the sub trees of the specified directory file path.
- bool recursive_watch_;
-
- // Keep track of the last modified time of the file. We use nulltime
- // to represent the file not existing.
- Time last_modified_;
-
- // The time at which we processed the first notification with the
- // |last_modified_| time stamp.
- Time first_notification_;
-
- DISALLOW_COPY_AND_ASSIGN(FilePathWatcherImpl);
-};
-
-bool FilePathWatcherImpl::Watch(const FilePath& path,
- bool recursive,
- const FilePathWatcher::Callback& callback) {
- DCHECK(target_.value().empty()); // Can only watch one path.
-
- set_task_runner(ThreadTaskRunnerHandle::Get());
- callback_ = callback;
- target_ = path;
- recursive_watch_ = recursive;
- MessageLoop::current()->AddDestructionObserver(this);
-
- File::Info file_info;
- if (GetFileInfo(target_, &file_info)) {
- last_modified_ = file_info.last_modified;
- first_notification_ = Time::Now();
- }
-
- if (!UpdateWatch())
- return false;
-
- watcher_.StartWatching(handle_, this);
-
- return true;
-}
-
-void FilePathWatcherImpl::Cancel() {
- if (callback_.is_null()) {
- // Watch was never called, or the |task_runner_| has already quit.
- set_cancelled();
- return;
- }
-
- // Switch to the file thread if necessary so we can stop |watcher_|.
- if (!task_runner()->BelongsToCurrentThread()) {
- task_runner()->PostTask(FROM_HERE, Bind(&FilePathWatcher::CancelWatch,
- make_scoped_refptr(this)));
- } else {
- CancelOnMessageLoopThread();
- }
-}
-
-void FilePathWatcherImpl::CancelOnMessageLoopThread() {
- DCHECK(task_runner()->BelongsToCurrentThread());
- set_cancelled();
-
- if (handle_ != INVALID_HANDLE_VALUE)
- DestroyWatch();
-
- if (!callback_.is_null()) {
- MessageLoop::current()->RemoveDestructionObserver(this);
- callback_.Reset();
- }
-}
-
-void FilePathWatcherImpl::WillDestroyCurrentMessageLoop() {
- CancelOnMessageLoopThread();
-}
-
-void FilePathWatcherImpl::OnObjectSignaled(HANDLE object) {
- DCHECK(object == handle_);
- // Make sure we stay alive through the body of this function.
- scoped_refptr<FilePathWatcherImpl> keep_alive(this);
-
- if (!UpdateWatch()) {
- callback_.Run(target_, true /* error */);
- return;
- }
-
- // Check whether the event applies to |target_| and notify the callback.
- File::Info file_info;
- bool file_exists = GetFileInfo(target_, &file_info);
- if (recursive_watch_) {
- // Only the mtime of |target_| is tracked but in a recursive watch,
- // some other file or directory may have changed so all notifications
- // are passed through. It is possible to figure out which file changed
- // using ReadDirectoryChangesW() instead of FindFirstChangeNotification(),
- // but that function is quite complicated:
- // http://qualapps.blogspot.com/2010/05/understanding-readdirectorychangesw.html
- callback_.Run(target_, false);
- } else if (file_exists && (last_modified_.is_null() ||
- last_modified_ != file_info.last_modified)) {
- last_modified_ = file_info.last_modified;
- first_notification_ = Time::Now();
- callback_.Run(target_, false);
- } else if (file_exists && last_modified_ == file_info.last_modified &&
- !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 (Time::Now() - first_notification_ > TimeDelta::FromSeconds(1)) {
- // Stop further notifications for this |last_modification_| time stamp.
- first_notification_ = Time();
- }
- callback_.Run(target_, false);
- } else if (!file_exists && !last_modified_.is_null()) {
- last_modified_ = Time();
- callback_.Run(target_, false);
- }
-
- // The watch may have been cancelled by the callback.
- if (handle_ != INVALID_HANDLE_VALUE)
- watcher_.StartWatching(handle_, this);
-}
-
-// static
-bool FilePathWatcherImpl::SetupWatchHandle(const FilePath& dir,
- bool recursive,
- HANDLE* handle) {
- *handle = FindFirstChangeNotification(
- dir.value().c_str(),
- recursive,
- FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_SIZE |
- FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_DIR_NAME |
- FILE_NOTIFY_CHANGE_ATTRIBUTES | FILE_NOTIFY_CHANGE_SECURITY);
- if (*handle != INVALID_HANDLE_VALUE) {
- // Make sure the handle we got points to an existing directory. It seems
- // that windows sometimes hands out watches to directories that are
- // about to go away, but doesn't sent notifications if that happens.
- if (!DirectoryExists(dir)) {
- FindCloseChangeNotification(*handle);
- *handle = INVALID_HANDLE_VALUE;
- }
- return true;
- }
-
- // If FindFirstChangeNotification failed because the target directory
- // doesn't exist, access is denied (happens if the file is already gone but
- // there are still handles open), or the target is not a directory, try the
- // immediate parent directory instead.
- DWORD error_code = GetLastError();
- if (error_code != ERROR_FILE_NOT_FOUND &&
- error_code != ERROR_PATH_NOT_FOUND &&
- error_code != ERROR_ACCESS_DENIED &&
- error_code != ERROR_SHARING_VIOLATION &&
- error_code != ERROR_DIRECTORY) {
- DPLOG(ERROR) << "FindFirstChangeNotification failed for "
- << dir.value();
- return false;
- }
-
- return true;
-}
-
-bool FilePathWatcherImpl::UpdateWatch() {
- if (handle_ != INVALID_HANDLE_VALUE)
- DestroyWatch();
-
- // Start at the target and walk up the directory chain until we succesfully
- // create a watch handle in |handle_|. |child_dirs| keeps a stack of child
- // directories stripped from target, in reverse order.
- std::vector<FilePath> child_dirs;
- FilePath watched_path(target_);
- while (true) {
- if (!SetupWatchHandle(watched_path, recursive_watch_, &handle_))
- return false;
-
- // Break if a valid handle is returned. Try the parent directory otherwise.
- if (handle_ != INVALID_HANDLE_VALUE)
- break;
-
- // Abort if we hit the root directory.
- child_dirs.push_back(watched_path.BaseName());
- FilePath parent(watched_path.DirName());
- if (parent == watched_path) {
- DLOG(ERROR) << "Reached the root directory";
- return false;
- }
- watched_path = parent;
- }
-
- // At this point, handle_ is valid. However, the bottom-up search that the
- // above code performs races against directory creation. So try to walk back
- // down and see whether any children appeared in the mean time.
- while (!child_dirs.empty()) {
- watched_path = watched_path.Append(child_dirs.back());
- child_dirs.pop_back();
- HANDLE temp_handle = INVALID_HANDLE_VALUE;
- if (!SetupWatchHandle(watched_path, recursive_watch_, &temp_handle))
- return false;
- if (temp_handle == INVALID_HANDLE_VALUE)
- break;
- FindCloseChangeNotification(handle_);
- handle_ = temp_handle;
- }
-
- return true;
-}
-
-void FilePathWatcherImpl::DestroyWatch() {
- watcher_.StopWatching();
- FindCloseChangeNotification(handle_);
- handle_ = INVALID_HANDLE_VALUE;
-}
-
-} // namespace
-
-FilePathWatcher::FilePathWatcher() {
- impl_ = new FilePathWatcherImpl();
-}
-
-} // namespace base
« no previous file with comments | « base/files/file_path_watcher_unittest.cc ('k') | base/files/file_proxy_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698