Re-subimission of https://codereview.chromium.org/1041213003/
[chromium-blink-merge.git] / content / child / fileapi / file_system_dispatcher.cc
blob1a742db263111a1d7405c3a1f9a75104dd188437
1 // Copyright (c) 2012 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.
5 #include "content/child/fileapi/file_system_dispatcher.h"
7 #include "base/callback.h"
8 #include "base/files/file_util.h"
9 #include "base/message_loop/message_loop_proxy.h"
10 #include "base/process/process.h"
11 #include "content/child/child_thread_impl.h"
12 #include "content/common/fileapi/file_system_messages.h"
13 #include "storage/common/fileapi/file_system_info.h"
15 namespace content {
17 class FileSystemDispatcher::CallbackDispatcher {
18 public:
19 typedef CallbackDispatcher self;
20 typedef FileSystemDispatcher::StatusCallback StatusCallback;
21 typedef FileSystemDispatcher::MetadataCallback MetadataCallback;
22 typedef FileSystemDispatcher::ReadDirectoryCallback ReadDirectoryCallback;
23 typedef FileSystemDispatcher::OpenFileSystemCallback OpenFileSystemCallback;
24 typedef FileSystemDispatcher::ResolveURLCallback ResolveURLCallback;
25 typedef FileSystemDispatcher::WriteCallback WriteCallback;
26 typedef FileSystemDispatcher::OpenFileCallback OpenFileCallback;
28 static CallbackDispatcher* Create(const StatusCallback& callback) {
29 CallbackDispatcher* dispatcher = new CallbackDispatcher;
30 dispatcher->status_callback_ = callback;
31 dispatcher->error_callback_ = callback;
32 return dispatcher;
34 static CallbackDispatcher* Create(const MetadataCallback& callback,
35 const StatusCallback& error_callback) {
36 CallbackDispatcher* dispatcher = new CallbackDispatcher;
37 dispatcher->metadata_callback_ = callback;
38 dispatcher->error_callback_ = error_callback;
39 return dispatcher;
41 static CallbackDispatcher* Create(const CreateSnapshotFileCallback& callback,
42 const StatusCallback& error_callback) {
43 CallbackDispatcher* dispatcher = new CallbackDispatcher;
44 dispatcher->snapshot_callback_ = callback;
45 dispatcher->error_callback_ = error_callback;
46 return dispatcher;
48 static CallbackDispatcher* Create(const ReadDirectoryCallback& callback,
49 const StatusCallback& error_callback) {
50 CallbackDispatcher* dispatcher = new CallbackDispatcher;
51 dispatcher->directory_callback_ = callback;
52 dispatcher->error_callback_ = error_callback;
53 return dispatcher;
55 static CallbackDispatcher* Create(const OpenFileSystemCallback& callback,
56 const StatusCallback& error_callback) {
57 CallbackDispatcher* dispatcher = new CallbackDispatcher;
58 dispatcher->filesystem_callback_ = callback;
59 dispatcher->error_callback_ = error_callback;
60 return dispatcher;
62 static CallbackDispatcher* Create(const ResolveURLCallback& callback,
63 const StatusCallback& error_callback) {
64 CallbackDispatcher* dispatcher = new CallbackDispatcher;
65 dispatcher->resolve_callback_ = callback;
66 dispatcher->error_callback_ = error_callback;
67 return dispatcher;
69 static CallbackDispatcher* Create(const WriteCallback& callback,
70 const StatusCallback& error_callback) {
71 CallbackDispatcher* dispatcher = new CallbackDispatcher;
72 dispatcher->write_callback_ = callback;
73 dispatcher->error_callback_ = error_callback;
74 return dispatcher;
77 ~CallbackDispatcher() {}
79 void DidSucceed() {
80 status_callback_.Run(base::File::FILE_OK);
83 void DidFail(base::File::Error error_code) {
84 error_callback_.Run(error_code);
87 void DidReadMetadata(
88 const base::File::Info& file_info) {
89 metadata_callback_.Run(file_info);
92 void DidCreateSnapshotFile(
93 const base::File::Info& file_info,
94 const base::FilePath& platform_path,
95 int request_id) {
96 snapshot_callback_.Run(file_info, platform_path, request_id);
99 void DidReadDirectory(const std::vector<storage::DirectoryEntry>& entries,
100 bool has_more) {
101 directory_callback_.Run(entries, has_more);
104 void DidOpenFileSystem(const std::string& name,
105 const GURL& root) {
106 filesystem_callback_.Run(name, root);
109 void DidResolveURL(const storage::FileSystemInfo& info,
110 const base::FilePath& file_path,
111 bool is_directory) {
112 resolve_callback_.Run(info, file_path, is_directory);
115 void DidWrite(int64 bytes, bool complete) {
116 write_callback_.Run(bytes, complete);
119 private:
120 CallbackDispatcher() {}
122 StatusCallback status_callback_;
123 MetadataCallback metadata_callback_;
124 CreateSnapshotFileCallback snapshot_callback_;
125 ReadDirectoryCallback directory_callback_;
126 OpenFileSystemCallback filesystem_callback_;
127 ResolveURLCallback resolve_callback_;
128 WriteCallback write_callback_;
130 StatusCallback error_callback_;
132 DISALLOW_COPY_AND_ASSIGN(CallbackDispatcher);
135 FileSystemDispatcher::FileSystemDispatcher() {
138 FileSystemDispatcher::~FileSystemDispatcher() {
139 // Make sure we fire all the remaining callbacks.
140 for (IDMap<CallbackDispatcher, IDMapOwnPointer>::iterator
141 iter(&dispatchers_); !iter.IsAtEnd(); iter.Advance()) {
142 int request_id = iter.GetCurrentKey();
143 CallbackDispatcher* dispatcher = iter.GetCurrentValue();
144 DCHECK(dispatcher);
145 dispatcher->DidFail(base::File::FILE_ERROR_ABORT);
146 dispatchers_.Remove(request_id);
150 bool FileSystemDispatcher::OnMessageReceived(const IPC::Message& msg) {
151 bool handled = true;
152 IPC_BEGIN_MESSAGE_MAP(FileSystemDispatcher, msg)
153 IPC_MESSAGE_HANDLER(FileSystemMsg_DidOpenFileSystem, OnDidOpenFileSystem)
154 IPC_MESSAGE_HANDLER(FileSystemMsg_DidResolveURL, OnDidResolveURL)
155 IPC_MESSAGE_HANDLER(FileSystemMsg_DidSucceed, OnDidSucceed)
156 IPC_MESSAGE_HANDLER(FileSystemMsg_DidReadDirectory, OnDidReadDirectory)
157 IPC_MESSAGE_HANDLER(FileSystemMsg_DidReadMetadata, OnDidReadMetadata)
158 IPC_MESSAGE_HANDLER(FileSystemMsg_DidCreateSnapshotFile,
159 OnDidCreateSnapshotFile)
160 IPC_MESSAGE_HANDLER(FileSystemMsg_DidFail, OnDidFail)
161 IPC_MESSAGE_HANDLER(FileSystemMsg_DidWrite, OnDidWrite)
162 IPC_MESSAGE_UNHANDLED(handled = false)
163 IPC_END_MESSAGE_MAP()
164 return handled;
167 void FileSystemDispatcher::OpenFileSystem(
168 const GURL& origin_url,
169 storage::FileSystemType type,
170 const OpenFileSystemCallback& success_callback,
171 const StatusCallback& error_callback) {
172 int request_id = dispatchers_.Add(
173 CallbackDispatcher::Create(success_callback, error_callback));
174 ChildThreadImpl::current()->Send(new FileSystemHostMsg_OpenFileSystem(
175 request_id, origin_url, type));
178 void FileSystemDispatcher::ResolveURL(
179 const GURL& filesystem_url,
180 const ResolveURLCallback& success_callback,
181 const StatusCallback& error_callback) {
182 int request_id = dispatchers_.Add(
183 CallbackDispatcher::Create(success_callback, error_callback));
184 ChildThreadImpl::current()->Send(new FileSystemHostMsg_ResolveURL(
185 request_id, filesystem_url));
188 void FileSystemDispatcher::DeleteFileSystem(const GURL& origin_url,
189 storage::FileSystemType type,
190 const StatusCallback& callback) {
191 int request_id = dispatchers_.Add(CallbackDispatcher::Create(callback));
192 ChildThreadImpl::current()->Send(new FileSystemHostMsg_DeleteFileSystem(
193 request_id, origin_url, type));
196 void FileSystemDispatcher::Move(
197 const GURL& src_path,
198 const GURL& dest_path,
199 const StatusCallback& callback) {
200 int request_id = dispatchers_.Add(CallbackDispatcher::Create(callback));
201 ChildThreadImpl::current()->Send(new FileSystemHostMsg_Move(
202 request_id, src_path, dest_path));
205 void FileSystemDispatcher::Copy(
206 const GURL& src_path,
207 const GURL& dest_path,
208 const StatusCallback& callback) {
209 int request_id = dispatchers_.Add(CallbackDispatcher::Create(callback));
210 ChildThreadImpl::current()->Send(new FileSystemHostMsg_Copy(
211 request_id, src_path, dest_path));
214 void FileSystemDispatcher::Remove(
215 const GURL& path,
216 bool recursive,
217 const StatusCallback& callback) {
218 int request_id = dispatchers_.Add(CallbackDispatcher::Create(callback));
219 ChildThreadImpl::current()->Send(
220 new FileSystemHostMsg_Remove(request_id, path, recursive));
223 void FileSystemDispatcher::ReadMetadata(
224 const GURL& path,
225 const MetadataCallback& success_callback,
226 const StatusCallback& error_callback) {
227 int request_id = dispatchers_.Add(
228 CallbackDispatcher::Create(success_callback, error_callback));
229 ChildThreadImpl::current()->Send(
230 new FileSystemHostMsg_ReadMetadata(request_id, path));
233 void FileSystemDispatcher::CreateFile(
234 const GURL& path,
235 bool exclusive,
236 const StatusCallback& callback) {
237 int request_id = dispatchers_.Add(CallbackDispatcher::Create(callback));
238 ChildThreadImpl::current()->Send(new FileSystemHostMsg_Create(
239 request_id, path, exclusive,
240 false /* is_directory */, false /* recursive */));
243 void FileSystemDispatcher::CreateDirectory(
244 const GURL& path,
245 bool exclusive,
246 bool recursive,
247 const StatusCallback& callback) {
248 int request_id = dispatchers_.Add(CallbackDispatcher::Create(callback));
249 ChildThreadImpl::current()->Send(new FileSystemHostMsg_Create(
250 request_id, path, exclusive, true /* is_directory */, recursive));
253 void FileSystemDispatcher::Exists(
254 const GURL& path,
255 bool is_directory,
256 const StatusCallback& callback) {
257 int request_id = dispatchers_.Add(CallbackDispatcher::Create(callback));
258 ChildThreadImpl::current()->Send(
259 new FileSystemHostMsg_Exists(request_id, path, is_directory));
262 void FileSystemDispatcher::ReadDirectory(
263 const GURL& path,
264 const ReadDirectoryCallback& success_callback,
265 const StatusCallback& error_callback) {
266 int request_id = dispatchers_.Add(
267 CallbackDispatcher::Create(success_callback, error_callback));
268 ChildThreadImpl::current()->Send(
269 new FileSystemHostMsg_ReadDirectory(request_id, path));
272 void FileSystemDispatcher::Truncate(
273 const GURL& path,
274 int64 offset,
275 int* request_id_out,
276 const StatusCallback& callback) {
277 int request_id = dispatchers_.Add(CallbackDispatcher::Create(callback));
278 ChildThreadImpl::current()->Send(
279 new FileSystemHostMsg_Truncate(request_id, path, offset));
281 if (request_id_out)
282 *request_id_out = request_id;
285 void FileSystemDispatcher::Write(
286 const GURL& path,
287 const std::string& blob_id,
288 int64 offset,
289 int* request_id_out,
290 const WriteCallback& success_callback,
291 const StatusCallback& error_callback) {
292 int request_id = dispatchers_.Add(
293 CallbackDispatcher::Create(success_callback, error_callback));
294 ChildThreadImpl::current()->Send(
295 new FileSystemHostMsg_Write(request_id, path, blob_id, offset));
297 if (request_id_out)
298 *request_id_out = request_id;
301 void FileSystemDispatcher::Cancel(
302 int request_id_to_cancel,
303 const StatusCallback& callback) {
304 int request_id = dispatchers_.Add(CallbackDispatcher::Create(callback));
305 ChildThreadImpl::current()->Send(new FileSystemHostMsg_CancelWrite(
306 request_id, request_id_to_cancel));
309 void FileSystemDispatcher::TouchFile(
310 const GURL& path,
311 const base::Time& last_access_time,
312 const base::Time& last_modified_time,
313 const StatusCallback& callback) {
314 int request_id = dispatchers_.Add(CallbackDispatcher::Create(callback));
315 ChildThreadImpl::current()->Send(
316 new FileSystemHostMsg_TouchFile(
317 request_id, path, last_access_time, last_modified_time));
320 void FileSystemDispatcher::CreateSnapshotFile(
321 const GURL& file_path,
322 const CreateSnapshotFileCallback& success_callback,
323 const StatusCallback& error_callback) {
324 int request_id = dispatchers_.Add(
325 CallbackDispatcher::Create(success_callback, error_callback));
326 ChildThreadImpl::current()->Send(
327 new FileSystemHostMsg_CreateSnapshotFile(
328 request_id, file_path));
331 void FileSystemDispatcher::OnDidOpenFileSystem(int request_id,
332 const std::string& name,
333 const GURL& root) {
334 DCHECK(root.is_valid());
335 CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id);
336 DCHECK(dispatcher);
337 dispatcher->DidOpenFileSystem(name, root);
338 dispatchers_.Remove(request_id);
341 void FileSystemDispatcher::OnDidResolveURL(int request_id,
342 const storage::FileSystemInfo& info,
343 const base::FilePath& file_path,
344 bool is_directory) {
345 DCHECK(info.root_url.is_valid());
346 CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id);
347 DCHECK(dispatcher);
348 dispatcher->DidResolveURL(info, file_path, is_directory);
349 dispatchers_.Remove(request_id);
352 void FileSystemDispatcher::OnDidSucceed(int request_id) {
353 CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id);
354 DCHECK(dispatcher);
355 dispatcher->DidSucceed();
356 dispatchers_.Remove(request_id);
359 void FileSystemDispatcher::OnDidReadMetadata(
360 int request_id, const base::File::Info& file_info) {
361 CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id);
362 DCHECK(dispatcher);
363 dispatcher->DidReadMetadata(file_info);
364 dispatchers_.Remove(request_id);
367 void FileSystemDispatcher::OnDidCreateSnapshotFile(
368 int request_id, const base::File::Info& file_info,
369 const base::FilePath& platform_path) {
370 CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id);
371 DCHECK(dispatcher);
372 dispatcher->DidCreateSnapshotFile(file_info, platform_path, request_id);
373 dispatchers_.Remove(request_id);
376 void FileSystemDispatcher::OnDidReadDirectory(
377 int request_id,
378 const std::vector<storage::DirectoryEntry>& entries,
379 bool has_more) {
380 CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id);
381 DCHECK(dispatcher);
382 dispatcher->DidReadDirectory(entries, has_more);
383 if (!has_more)
384 dispatchers_.Remove(request_id);
387 void FileSystemDispatcher::OnDidFail(
388 int request_id, base::File::Error error_code) {
389 CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id);
390 DCHECK(dispatcher);
391 dispatcher->DidFail(error_code);
392 dispatchers_.Remove(request_id);
395 void FileSystemDispatcher::OnDidWrite(
396 int request_id, int64 bytes, bool complete) {
397 CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id);
398 DCHECK(dispatcher);
399 dispatcher->DidWrite(bytes, complete);
400 if (complete)
401 dispatchers_.Remove(request_id);
404 } // namespace content