This source file includes following definitions.
- set_delay
- weak_ptr_factory_
- Destroy
- StartWatch
- DestroyOnFileThread
- StartWatchOnFileThread
- OnWriteEvent
- InvokeCallback
- StartWatch
- DisableDelayForTesting
#include "chrome/browser/chromeos/drive/file_write_watcher.h"
#include <map>
#include <vector>
#include "base/bind.h"
#include "base/callback.h"
#include "base/files/file_path_watcher.h"
#include "base/stl_util.h"
#include "base/timer/timer.h"
#include "content/public/browser/browser_thread.h"
#include "google_apis/drive/task_util.h"
using content::BrowserThread;
namespace drive {
namespace internal {
namespace {
const int64 kWriteEventDelayInSeconds = 5;
}
class FileWriteWatcher::FileWriteWatcherImpl {
public:
FileWriteWatcherImpl();
void Destroy();
void StartWatch(const base::FilePath& path,
const StartWatchCallback& on_start_callback,
const base::Closure& on_write_callback);
void set_delay(base::TimeDelta delay) { delay_ = delay; }
private:
~FileWriteWatcherImpl();
void DestroyOnFileThread();
void StartWatchOnFileThread(const base::FilePath& path,
const StartWatchCallback& on_start_callback,
const base::Closure& on_write_callback);
void OnWriteEvent(const base::FilePath& path, bool error);
void InvokeCallback(const base::FilePath& path);
struct PathWatchInfo {
std::vector<base::Closure> on_write_callbacks;
base::FilePathWatcher watcher;
base::Timer timer;
explicit PathWatchInfo(const base::Closure& on_write_callback)
: on_write_callbacks(1, on_write_callback),
timer(false , false ) {
}
};
base::TimeDelta delay_;
std::map<base::FilePath, PathWatchInfo*> watchers_;
base::WeakPtrFactory<FileWriteWatcherImpl> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(FileWriteWatcherImpl);
};
FileWriteWatcher::FileWriteWatcherImpl::FileWriteWatcherImpl()
: delay_(base::TimeDelta::FromSeconds(kWriteEventDelayInSeconds)),
weak_ptr_factory_(this) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
}
void FileWriteWatcher::FileWriteWatcherImpl::Destroy() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE)->PostTask(
FROM_HERE,
base::Bind(&FileWriteWatcherImpl::DestroyOnFileThread,
base::Unretained(this)));
}
void FileWriteWatcher::FileWriteWatcherImpl::StartWatch(
const base::FilePath& path,
const StartWatchCallback& on_start_callback,
const base::Closure& on_write_callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE)->PostTask(
FROM_HERE,
base::Bind(&FileWriteWatcherImpl::StartWatchOnFileThread,
base::Unretained(this),
path,
google_apis::CreateRelayCallback(on_start_callback),
google_apis::CreateRelayCallback(on_write_callback)));
}
FileWriteWatcher::FileWriteWatcherImpl::~FileWriteWatcherImpl() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
STLDeleteContainerPairSecondPointers(watchers_.begin(), watchers_.end());
}
void FileWriteWatcher::FileWriteWatcherImpl::DestroyOnFileThread() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
delete this;
}
void FileWriteWatcher::FileWriteWatcherImpl::StartWatchOnFileThread(
const base::FilePath& path,
const StartWatchCallback& on_start_callback,
const base::Closure& on_write_callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
std::map<base::FilePath, PathWatchInfo*>::iterator it = watchers_.find(path);
if (it != watchers_.end()) {
on_start_callback.Run(true);
it->second->on_write_callbacks.push_back(on_write_callback);
return;
}
scoped_ptr<PathWatchInfo> info(new PathWatchInfo(on_write_callback));
bool ok = info->watcher.Watch(
path,
false,
base::Bind(&FileWriteWatcherImpl::OnWriteEvent,
weak_ptr_factory_.GetWeakPtr()));
watchers_[path] = info.release();
on_start_callback.Run(ok);
}
void FileWriteWatcher::FileWriteWatcherImpl::OnWriteEvent(
const base::FilePath& path,
bool error) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
if (error)
return;
std::map<base::FilePath, PathWatchInfo*>::iterator it = watchers_.find(path);
DCHECK(it != watchers_.end());
it->second->timer.Start(FROM_HERE,
delay_,
base::Bind(&FileWriteWatcherImpl::InvokeCallback,
weak_ptr_factory_.GetWeakPtr(),
path));
}
void FileWriteWatcher::FileWriteWatcherImpl::InvokeCallback(
const base::FilePath& path) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
std::map<base::FilePath, PathWatchInfo*>::iterator it = watchers_.find(path);
DCHECK(it != watchers_.end());
std::vector<base::Closure> callbacks;
callbacks.swap(it->second->on_write_callbacks);
delete it->second;
watchers_.erase(it);
for (size_t i = 0; i < callbacks.size(); ++i)
callbacks[i].Run();
}
FileWriteWatcher::FileWriteWatcher()
: watcher_impl_(new FileWriteWatcherImpl) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
}
FileWriteWatcher::~FileWriteWatcher() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
}
void FileWriteWatcher::StartWatch(const base::FilePath& file_path,
const StartWatchCallback& on_start_callback,
const base::Closure& on_write_callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
watcher_impl_->StartWatch(file_path, on_start_callback, on_write_callback);
}
void FileWriteWatcher::DisableDelayForTesting() {
watcher_impl_->set_delay(base::TimeDelta());
}
}
}