1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/chromeos/file_manager/file_watcher.h"
6
7 #include "base/bind.h"
8 #include "content/public/browser/browser_thread.h"
9 #include "google_apis/drive/task_util.h"
10
11 using content::BrowserThread;
12
13 namespace file_manager {
14 namespace {
15
16 // Creates a base::FilePathWatcher and starts watching at |watch_path| with
17 // |callback|. Returns NULL on failure.
CreateAndStartFilePathWatcher(const base::FilePath & watch_path,const base::FilePathWatcher::Callback & callback)18 base::FilePathWatcher* CreateAndStartFilePathWatcher(
19 const base::FilePath& watch_path,
20 const base::FilePathWatcher::Callback& callback) {
21 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
22 DCHECK(!callback.is_null());
23
24 scoped_ptr<base::FilePathWatcher> watcher(new base::FilePathWatcher);
25 if (!watcher->Watch(watch_path, false /* recursive */, callback))
26 return NULL;
27
28 return watcher.release();
29 }
30
31 } // namespace
32
FileWatcher(const base::FilePath & virtual_path)33 FileWatcher::FileWatcher(const base::FilePath& virtual_path)
34 : local_file_watcher_(NULL),
35 virtual_path_(virtual_path),
36 weak_ptr_factory_(this) {
37 DCHECK_CURRENTLY_ON(BrowserThread::UI);
38 }
39
~FileWatcher()40 FileWatcher::~FileWatcher() {
41 DCHECK_CURRENTLY_ON(BrowserThread::UI);
42
43 BrowserThread::DeleteSoon(BrowserThread::FILE,
44 FROM_HERE,
45 local_file_watcher_);
46 }
47
AddExtension(const std::string & extension_id)48 void FileWatcher::AddExtension(const std::string& extension_id) {
49 DCHECK_CURRENTLY_ON(BrowserThread::UI);
50
51 extensions_[extension_id]++;
52 }
53
RemoveExtension(const std::string & extension_id)54 void FileWatcher::RemoveExtension(const std::string& extension_id) {
55 DCHECK_CURRENTLY_ON(BrowserThread::UI);
56
57 ExtensionCountMap::iterator it = extensions_.find(extension_id);
58 if (it == extensions_.end()) {
59 LOG(ERROR) << " Extension [" << extension_id
60 << "] tries to unsubscribe from folder ["
61 << virtual_path_.value()
62 << "] it isn't subscribed";
63 return;
64 }
65
66 // If entry found - decrease it's count and remove if necessary
67 --it->second;
68 if (it->second == 0)
69 extensions_.erase(it);
70 }
71
GetExtensionIds() const72 std::vector<std::string> FileWatcher::GetExtensionIds() const {
73 std::vector<std::string> extension_ids;
74 for (ExtensionCountMap::const_iterator iter = extensions_.begin();
75 iter != extensions_.end(); ++iter) {
76 extension_ids.push_back(iter->first);
77 }
78 return extension_ids;
79 }
80
WatchLocalFile(const base::FilePath & local_path,const base::FilePathWatcher::Callback & file_watcher_callback,const BoolCallback & callback)81 void FileWatcher::WatchLocalFile(
82 const base::FilePath& local_path,
83 const base::FilePathWatcher::Callback& file_watcher_callback,
84 const BoolCallback& callback) {
85 DCHECK_CURRENTLY_ON(BrowserThread::UI);
86 DCHECK(!callback.is_null());
87 DCHECK(!local_file_watcher_);
88
89 BrowserThread::PostTaskAndReplyWithResult(
90 BrowserThread::FILE,
91 FROM_HERE,
92 base::Bind(&CreateAndStartFilePathWatcher,
93 local_path,
94 google_apis::CreateRelayCallback(file_watcher_callback)),
95 base::Bind(&FileWatcher::OnWatcherStarted,
96 weak_ptr_factory_.GetWeakPtr(),
97 callback));
98 }
99
OnWatcherStarted(const BoolCallback & callback,base::FilePathWatcher * file_watcher)100 void FileWatcher::OnWatcherStarted(
101 const BoolCallback& callback,
102 base::FilePathWatcher* file_watcher) {
103 DCHECK_CURRENTLY_ON(BrowserThread::UI);
104 DCHECK(!callback.is_null());
105 DCHECK(!local_file_watcher_);
106
107 if (file_watcher) {
108 local_file_watcher_ = file_watcher;
109 callback.Run(true);
110 } else {
111 callback.Run(false);
112 }
113 }
114
115 } // namespace file_manager
116