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