ipc/chromium/src/base/directory_watcher_win.cc
author Smokey Ardisson <alqahira@ardisson.org>
Mon, 07 Jan 2013 23:52:45 -0500
branchCAMINO_2_1_SECBRANCH
changeset 35290 b66b287a2650de54f6b2a2b92f6bd456d1bcd76e
parent 33811 2e5197c227166b207b4263fb07850be79ecdb4de
permissions -rw-r--r--
Bug 825484 - Upgrade CAMINO_2_1_SECBRANCH to NSS_3_14_CKBI_1_93_RTM (implies NSPR_4_9_3_RTM). r=wtc/kaie/bsmith/kwilson on the original patches in their original bugs, a=me for CAMINO_2_1_SECBRANCH. CLOSED TREE

// Copyright (c) 2006-2008 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 "base/file_path.h"
#include "base/logging.h"
#include "base/object_watcher.h"
#include "base/ref_counted.h"

namespace {

class DirectoryWatcherImpl : public DirectoryWatcher::PlatformDelegate,
                             public base::ObjectWatcher::Delegate {
 public:
  DirectoryWatcherImpl() : handle_(INVALID_HANDLE_VALUE) {}
  virtual ~DirectoryWatcherImpl();

  virtual bool Watch(const FilePath& path, DirectoryWatcher::Delegate* delegate,
                     bool recursive);

  // Callback from MessageLoopForIO.
  virtual void OnObjectSignaled(HANDLE object);

 private:
  // Delegate to notify upon changes.
  DirectoryWatcher::Delegate* delegate_;
  // Path we're watching (passed to delegate).
  FilePath path_;
  // Handle for FindFirstChangeNotification.
  HANDLE handle_;
  // ObjectWatcher to watch handle_ for events.
  base::ObjectWatcher watcher_;

  DISALLOW_COPY_AND_ASSIGN(DirectoryWatcherImpl);
};

DirectoryWatcherImpl::~DirectoryWatcherImpl() {
  if (handle_ != INVALID_HANDLE_VALUE) {
    watcher_.StopWatching();
    FindCloseChangeNotification(handle_);
  }
}

bool DirectoryWatcherImpl::Watch(const FilePath& path,
    DirectoryWatcher::Delegate* delegate, bool recursive) {
  DCHECK(path_.value().empty());  // Can only watch one path.

  handle_ = FindFirstChangeNotification(
      path.value().c_str(),
      recursive,
      FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_SIZE |
      FILE_NOTIFY_CHANGE_LAST_WRITE);
  if (handle_ == INVALID_HANDLE_VALUE)
    return false;

  delegate_ = delegate;
  path_ = path;
  watcher_.StartWatching(handle_, this);

  return true;
}

void DirectoryWatcherImpl::OnObjectSignaled(HANDLE object) {
  DCHECK(object == handle_);
  // Make sure we stay alive through the body of this function.
  scoped_refptr<DirectoryWatcherImpl> keep_alive(this);

  delegate_->OnDirectoryChanged(path_);

  // Register for more notifications on file change.
  BOOL ok = FindNextChangeNotification(object);
  DCHECK(ok);
  watcher_.StartWatching(object, this);
}

}  // namespace

DirectoryWatcher::DirectoryWatcher() {
  impl_ = new DirectoryWatcherImpl();
}