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

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

Powered by Google App Engine
This is Rietveld 408576698