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

Side by Side Diff: chrome/browser/extensions/api/file_system/entry_watcher_service.cc

Issue 452043003: [ew] Add basic classes. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Added missing files. Created 6 years, 4 months 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright 2014 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/extensions/api/file_system/entry_watcher_service.h"
6
7 #include "base/thread_task_runner_handle.h"
8 #include "chrome/browser/extensions/extension_util.h"
9 #include "chrome/browser/profiles/profile.h"
10 #include "chrome/common/extensions/api/file_system.h"
11 #include "components/keyed_service/content/browser_context_dependency_manager.h"
12 #include "content/public/browser/browser_context.h"
13 #include "content/public/browser/browser_thread.h"
14 #include "content/public/browser/storage_partition.h"
15 #include "extensions/browser/event_router.h"
16 #include "webkit/browser/fileapi/file_system_context.h"
17
18 namespace extensions {
19 namespace {
20
21 // Default implementation for dispatching an event. Can be replaced for unit
22 // tests by EntryWatcherService::SetDispatchEventImplForTesting().
23 void DispatchEventImpl(EventRouter* event_router,
24 const std::string& extension_id,
25 scoped_ptr<Event> event) {
26 event_router->DispatchEventToExtension(extension_id, event.Pass());
27 }
28
29 // Default implementation for acquiring a file system context for a specific
30 // |extension_id| and |context|.
31 storage::FileSystemContext* GetFileSystemContextImpl(
32 const std::string& extension_id,
33 content::BrowserContext* context) {
34 const GURL site = util::GetSiteForExtensionId(extension_id, context);
35 return content::BrowserContext::GetStoragePartitionForSite(context, site)
36 ->GetFileSystemContext();
37 }
38
39 } // namespace
40
41 EntryWatcherService::EntryWatcherService(content::BrowserContext* context)
42 : context_(context),
43 dispatch_event_impl_(
44 base::Bind(&DispatchEventImpl, EventRouter::Get(context))),
45 get_file_system_context_impl_(base::Bind(&GetFileSystemContextImpl)),
46 observing_(this),
47 weak_ptr_factory_(this) {
48 // TODO(mtomasz): Restore persistent watchers.
49 }
50
51 EntryWatcherService::~EntryWatcherService() {
52 }
53
54 void EntryWatcherService::SetDispatchEventImplForTesting(
55 const DispatchEventImplCallback& callback) {
56 dispatch_event_impl_ = callback;
57 }
58
59 void EntryWatcherService::SetGetFileSystemContextImplForTesting(
60 const GetFileSystemContextImplCallback& callback) {
61 get_file_system_context_impl_ = callback;
62 }
63
64 void EntryWatcherService::WatchDirectory(
65 const std::string& extension_id,
66 const storage::FileSystemURL& url,
67 bool recursive,
68 const storage::WatcherManager::StatusCallback& callback) {
69 // TODO(mtomasz): Add support for recursive watchers.
70 if (recursive) {
71 base::ThreadTaskRunnerHandle::Get()->PostTask(
72 FROM_HERE,
73 base::Bind(callback, base::File::FILE_ERROR_INVALID_OPERATION));
74 return;
75 }
76
77 storage::FileSystemContext* const context =
78 get_file_system_context_impl_.Run(extension_id, context_);
79 DCHECK(context);
80
81 storage::WatcherManager* const watcher_manager =
82 context->GetWatcherManager(url.type());
83 if (!watcher_manager) {
84 // Post a task instead of calling the callback directly, since the caller
85 // may expect the callback to be called asynchronously.
86 base::ThreadTaskRunnerHandle::Get()->PostTask(
87 FROM_HERE,
88 base::Bind(callback, base::File::FILE_ERROR_INVALID_OPERATION));
89 return;
90 }
91
92 // Passing a pointer to WatcherManager is safe, since the pointer is required
93 // to be valid until shutdown.
94 context->default_file_task_runner()->PostNonNestableTask(
95 FROM_HERE,
96 base::Bind(&storage::WatcherManager::WatchDirectory,
97 base::Unretained(watcher_manager), // Outlives the service.
98 url,
99 recursive,
100 base::Bind(&EntryWatcherService::OnWatchDirectoryCompleted,
101 weak_ptr_factory_.GetWeakPtr(),
102 watcher_manager, // Outlives the service.
103 extension_id,
104 url,
105 recursive,
106 callback)));
107 }
108
109 void EntryWatcherService::UnwatchEntry(
110 const std::string& extension_id,
111 const storage::FileSystemURL& url,
112 const storage::WatcherManager::StatusCallback& callback) {
113 storage::FileSystemContext* const context =
114 get_file_system_context_impl_.Run(extension_id, context_);
115 DCHECK(context);
116
117 storage::WatcherManager* const watcher_manager =
118 context->GetWatcherManager(url.type());
119 if (!watcher_manager) {
120 base::ThreadTaskRunnerHandle::Get()->PostTask(
121 FROM_HERE,
122 base::Bind(callback, base::File::FILE_ERROR_INVALID_OPERATION));
123 return;
124 }
125
126 // Passing a pointer to WatcherManager is safe, since the pointer is required
127 // to be valid until shutdown.
128 context->default_file_task_runner()->PostNonNestableTask(
129 FROM_HERE,
130 base::Bind(&storage::WatcherManager::UnwatchEntry,
131 base::Unretained(watcher_manager), // Outlives the service.
132 url,
133 base::Bind(&EntryWatcherService::OnUnwatchEntryCompleted,
134 weak_ptr_factory_.GetWeakPtr(),
135 extension_id,
136 url,
137 callback)));
138 }
139
140 std::vector<storage::FileSystemURL> EntryWatcherService::GetWatchedEntries(
141 const std::string& extension_id) {
142 std::vector<storage::FileSystemURL> result;
143 for (WatcherMap::const_iterator it = watchers_.begin(); it != watchers_.end();
144 ++it) {
145 const std::map<std::string, EntryWatcher>::const_iterator watcher_it =
146 it->second.find(extension_id);
147 if (watcher_it != it->second.end())
148 result.push_back(watcher_it->second.url);
149 }
150
151 return result;
152 }
153
154 void EntryWatcherService::OnEntryChanged(const storage::FileSystemURL& url) {
155 const WatcherMap::const_iterator it = watchers_.find(url);
156 DCHECK(it != watchers_.end());
157 for (std::map<std::string, EntryWatcher>::const_iterator watcher_it =
158 it->second.begin();
159 watcher_it != it->second.end();
160 ++watcher_it) {
161 const std::string& extension_id = watcher_it->first;
162 api::file_system::EntryChangedEvent event;
163 dispatch_event_impl_.Run(
164 extension_id,
165 make_scoped_ptr(
166 new Event(api::file_system::OnEntryChanged::kEventName,
167 api::file_system::OnEntryChanged::Create(event))));
168 }
169 }
170
171 void EntryWatcherService::OnEntryRemoved(const storage::FileSystemURL& url) {
172 WatcherMap::const_iterator it = watchers_.find(url);
173 DCHECK(it != watchers_.end());
174 for (std::map<std::string, EntryWatcher>::const_iterator watcher_it =
175 it->second.begin();
176 watcher_it != it->second.end();
177 ++watcher_it) {
178 const std::string& extension_id = watcher_it->first;
179 api::file_system::EntryRemovedEvent event;
180 dispatch_event_impl_.Run(
181 extension_id,
182 make_scoped_ptr(
183 new Event(api::file_system::OnEntryRemoved::kEventName,
184 api::file_system::OnEntryRemoved::Create(event))));
185 }
186 }
187
188 void EntryWatcherService::OnWatchDirectoryCompleted(
189 storage::WatcherManager* watcher_manager,
190 const std::string& extension_id,
191 const storage::FileSystemURL& url,
192 bool recursive,
193 const storage::WatcherManager::StatusCallback& callback,
194 base::File::Error result) {
195 if (result != base::File::FILE_OK) {
196 callback.Run(result);
197 return;
198 }
199
200 storage::FileSystemContext* const context =
201 get_file_system_context_impl_.Run(extension_id, context_);
202 DCHECK(context);
203
204 // Observe the manager if not observed yet.
205 if (!observing_.IsObserving(watcher_manager))
206 observing_.Add(watcher_manager);
207
208 watchers_[url][extension_id] =
209 EntryWatcher(url, true /* directory */, recursive);
210
211 // TODO(mtomasz): Save in preferences.
212
213 callback.Run(base::File::FILE_OK);
214 }
215
216 void EntryWatcherService::OnUnwatchEntryCompleted(
217 const std::string& extension_id,
218 const storage::FileSystemURL& url,
219 const storage::WatcherManager::StatusCallback& callback,
220 base::File::Error result) {
221 if (result != base::File::FILE_OK) {
222 callback.Run(result);
223 return;
224 }
225
226 if (watchers_[url].erase(extension_id) == 0) {
227 callback.Run(base::File::FILE_ERROR_NOT_FOUND);
228 return;
229 }
230
231 if (watchers_[url].empty())
232 watchers_.erase(url);
233
234 // TODO(mtomasz): Save in preferences.
235
236 callback.Run(base::File::FILE_OK);
237 }
238
239 EntryWatcherService::EntryWatcher::EntryWatcher()
240 : directory(false), recursive(false) {
241 }
242
243 EntryWatcherService::EntryWatcher::EntryWatcher(
244 const storage::FileSystemURL& url,
245 bool directory,
246 bool recursive)
247 : url(url), directory(directory), recursive(recursive) {
248 }
249
250 EntryWatcherService::EntryWatcher::~EntryWatcher() {
251 }
252
253 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698