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/process/process.h"
10 #include "content/child/child_thread_impl.h"
11 #include "content/common/fileapi/file_system_messages.h"
12 #include "storage/common/fileapi/file_system_info.h"
16 class FileSystemDispatcher::CallbackDispatcher
{
18 typedef CallbackDispatcher self
;
19 typedef FileSystemDispatcher::StatusCallback StatusCallback
;
20 typedef FileSystemDispatcher::MetadataCallback MetadataCallback
;
21 typedef FileSystemDispatcher::ReadDirectoryCallback ReadDirectoryCallback
;
22 typedef FileSystemDispatcher::OpenFileSystemCallback OpenFileSystemCallback
;
23 typedef FileSystemDispatcher::ResolveURLCallback ResolveURLCallback
;
24 typedef FileSystemDispatcher::WriteCallback WriteCallback
;
25 typedef FileSystemDispatcher::OpenFileCallback OpenFileCallback
;
27 static CallbackDispatcher
* Create(const StatusCallback
& callback
) {
28 CallbackDispatcher
* dispatcher
= new CallbackDispatcher
;
29 dispatcher
->status_callback_
= callback
;
30 dispatcher
->error_callback_
= callback
;
33 static CallbackDispatcher
* Create(const MetadataCallback
& callback
,
34 const StatusCallback
& error_callback
) {
35 CallbackDispatcher
* dispatcher
= new CallbackDispatcher
;
36 dispatcher
->metadata_callback_
= callback
;
37 dispatcher
->error_callback_
= error_callback
;
40 static CallbackDispatcher
* Create(const CreateSnapshotFileCallback
& callback
,
41 const StatusCallback
& error_callback
) {
42 CallbackDispatcher
* dispatcher
= new CallbackDispatcher
;
43 dispatcher
->snapshot_callback_
= callback
;
44 dispatcher
->error_callback_
= error_callback
;
47 static CallbackDispatcher
* Create(const ReadDirectoryCallback
& callback
,
48 const StatusCallback
& error_callback
) {
49 CallbackDispatcher
* dispatcher
= new CallbackDispatcher
;
50 dispatcher
->directory_callback_
= callback
;
51 dispatcher
->error_callback_
= error_callback
;
54 static CallbackDispatcher
* Create(const OpenFileSystemCallback
& callback
,
55 const StatusCallback
& error_callback
) {
56 CallbackDispatcher
* dispatcher
= new CallbackDispatcher
;
57 dispatcher
->filesystem_callback_
= callback
;
58 dispatcher
->error_callback_
= error_callback
;
61 static CallbackDispatcher
* Create(const ResolveURLCallback
& callback
,
62 const StatusCallback
& error_callback
) {
63 CallbackDispatcher
* dispatcher
= new CallbackDispatcher
;
64 dispatcher
->resolve_callback_
= callback
;
65 dispatcher
->error_callback_
= error_callback
;
68 static CallbackDispatcher
* Create(const WriteCallback
& callback
,
69 const StatusCallback
& error_callback
) {
70 CallbackDispatcher
* dispatcher
= new CallbackDispatcher
;
71 dispatcher
->write_callback_
= callback
;
72 dispatcher
->error_callback_
= error_callback
;
76 ~CallbackDispatcher() {}
79 status_callback_
.Run(base::File::FILE_OK
);
82 void DidFail(base::File::Error error_code
) {
83 error_callback_
.Run(error_code
);
87 const base::File::Info
& file_info
) {
88 metadata_callback_
.Run(file_info
);
91 void DidCreateSnapshotFile(
92 const base::File::Info
& file_info
,
93 const base::FilePath
& platform_path
,
95 snapshot_callback_
.Run(file_info
, platform_path
, request_id
);
98 void DidReadDirectory(const std::vector
<storage::DirectoryEntry
>& entries
,
100 directory_callback_
.Run(entries
, has_more
);
103 void DidOpenFileSystem(const std::string
& name
,
105 filesystem_callback_
.Run(name
, root
);
108 void DidResolveURL(const storage::FileSystemInfo
& info
,
109 const base::FilePath
& file_path
,
111 resolve_callback_
.Run(info
, file_path
, is_directory
);
114 void DidWrite(int64 bytes
, bool complete
) {
115 write_callback_
.Run(bytes
, complete
);
119 CallbackDispatcher() {}
121 StatusCallback status_callback_
;
122 MetadataCallback metadata_callback_
;
123 CreateSnapshotFileCallback snapshot_callback_
;
124 ReadDirectoryCallback directory_callback_
;
125 OpenFileSystemCallback filesystem_callback_
;
126 ResolveURLCallback resolve_callback_
;
127 WriteCallback write_callback_
;
129 StatusCallback error_callback_
;
131 DISALLOW_COPY_AND_ASSIGN(CallbackDispatcher
);
134 FileSystemDispatcher::FileSystemDispatcher() {
137 FileSystemDispatcher::~FileSystemDispatcher() {
138 // Make sure we fire all the remaining callbacks.
139 for (IDMap
<CallbackDispatcher
, IDMapOwnPointer
>::iterator
140 iter(&dispatchers_
); !iter
.IsAtEnd(); iter
.Advance()) {
141 int request_id
= iter
.GetCurrentKey();
142 CallbackDispatcher
* dispatcher
= iter
.GetCurrentValue();
144 dispatcher
->DidFail(base::File::FILE_ERROR_ABORT
);
145 dispatchers_
.Remove(request_id
);
149 bool FileSystemDispatcher::OnMessageReceived(const IPC::Message
& msg
) {
151 IPC_BEGIN_MESSAGE_MAP(FileSystemDispatcher
, msg
)
152 IPC_MESSAGE_HANDLER(FileSystemMsg_DidOpenFileSystem
, OnDidOpenFileSystem
)
153 IPC_MESSAGE_HANDLER(FileSystemMsg_DidResolveURL
, OnDidResolveURL
)
154 IPC_MESSAGE_HANDLER(FileSystemMsg_DidSucceed
, OnDidSucceed
)
155 IPC_MESSAGE_HANDLER(FileSystemMsg_DidReadDirectory
, OnDidReadDirectory
)
156 IPC_MESSAGE_HANDLER(FileSystemMsg_DidReadMetadata
, OnDidReadMetadata
)
157 IPC_MESSAGE_HANDLER(FileSystemMsg_DidCreateSnapshotFile
,
158 OnDidCreateSnapshotFile
)
159 IPC_MESSAGE_HANDLER(FileSystemMsg_DidFail
, OnDidFail
)
160 IPC_MESSAGE_HANDLER(FileSystemMsg_DidWrite
, OnDidWrite
)
161 IPC_MESSAGE_UNHANDLED(handled
= false)
162 IPC_END_MESSAGE_MAP()
166 void FileSystemDispatcher::OpenFileSystem(
167 const GURL
& origin_url
,
168 storage::FileSystemType type
,
169 const OpenFileSystemCallback
& success_callback
,
170 const StatusCallback
& error_callback
) {
171 int request_id
= dispatchers_
.Add(
172 CallbackDispatcher::Create(success_callback
, error_callback
));
173 ChildThreadImpl::current()->Send(new FileSystemHostMsg_OpenFileSystem(
174 request_id
, origin_url
, type
));
177 void FileSystemDispatcher::ResolveURL(
178 const GURL
& filesystem_url
,
179 const ResolveURLCallback
& success_callback
,
180 const StatusCallback
& error_callback
) {
181 int request_id
= dispatchers_
.Add(
182 CallbackDispatcher::Create(success_callback
, error_callback
));
183 ChildThreadImpl::current()->Send(new FileSystemHostMsg_ResolveURL(
184 request_id
, filesystem_url
));
187 void FileSystemDispatcher::DeleteFileSystem(const GURL
& origin_url
,
188 storage::FileSystemType type
,
189 const StatusCallback
& callback
) {
190 int request_id
= dispatchers_
.Add(CallbackDispatcher::Create(callback
));
191 ChildThreadImpl::current()->Send(new FileSystemHostMsg_DeleteFileSystem(
192 request_id
, origin_url
, type
));
195 void FileSystemDispatcher::Move(
196 const GURL
& src_path
,
197 const GURL
& dest_path
,
198 const StatusCallback
& callback
) {
199 int request_id
= dispatchers_
.Add(CallbackDispatcher::Create(callback
));
200 ChildThreadImpl::current()->Send(new FileSystemHostMsg_Move(
201 request_id
, src_path
, dest_path
));
204 void FileSystemDispatcher::Copy(
205 const GURL
& src_path
,
206 const GURL
& dest_path
,
207 const StatusCallback
& callback
) {
208 int request_id
= dispatchers_
.Add(CallbackDispatcher::Create(callback
));
209 ChildThreadImpl::current()->Send(new FileSystemHostMsg_Copy(
210 request_id
, src_path
, dest_path
));
213 void FileSystemDispatcher::Remove(
216 const StatusCallback
& callback
) {
217 int request_id
= dispatchers_
.Add(CallbackDispatcher::Create(callback
));
218 ChildThreadImpl::current()->Send(
219 new FileSystemHostMsg_Remove(request_id
, path
, recursive
));
222 void FileSystemDispatcher::ReadMetadata(
224 const MetadataCallback
& success_callback
,
225 const StatusCallback
& error_callback
) {
226 int request_id
= dispatchers_
.Add(
227 CallbackDispatcher::Create(success_callback
, error_callback
));
228 ChildThreadImpl::current()->Send(
229 new FileSystemHostMsg_ReadMetadata(request_id
, path
));
232 void FileSystemDispatcher::CreateFile(
235 const StatusCallback
& callback
) {
236 int request_id
= dispatchers_
.Add(CallbackDispatcher::Create(callback
));
237 ChildThreadImpl::current()->Send(new FileSystemHostMsg_Create(
238 request_id
, path
, exclusive
,
239 false /* is_directory */, false /* recursive */));
242 void FileSystemDispatcher::CreateDirectory(
246 const StatusCallback
& callback
) {
247 int request_id
= dispatchers_
.Add(CallbackDispatcher::Create(callback
));
248 ChildThreadImpl::current()->Send(new FileSystemHostMsg_Create(
249 request_id
, path
, exclusive
, true /* is_directory */, recursive
));
252 void FileSystemDispatcher::Exists(
255 const StatusCallback
& callback
) {
256 int request_id
= dispatchers_
.Add(CallbackDispatcher::Create(callback
));
257 ChildThreadImpl::current()->Send(
258 new FileSystemHostMsg_Exists(request_id
, path
, is_directory
));
261 void FileSystemDispatcher::ReadDirectory(
263 const ReadDirectoryCallback
& success_callback
,
264 const StatusCallback
& error_callback
) {
265 int request_id
= dispatchers_
.Add(
266 CallbackDispatcher::Create(success_callback
, error_callback
));
267 ChildThreadImpl::current()->Send(
268 new FileSystemHostMsg_ReadDirectory(request_id
, path
));
271 void FileSystemDispatcher::Truncate(
275 const StatusCallback
& callback
) {
276 int request_id
= dispatchers_
.Add(CallbackDispatcher::Create(callback
));
277 ChildThreadImpl::current()->Send(
278 new FileSystemHostMsg_Truncate(request_id
, path
, offset
));
281 *request_id_out
= request_id
;
284 void FileSystemDispatcher::Write(
286 const std::string
& blob_id
,
289 const WriteCallback
& success_callback
,
290 const StatusCallback
& error_callback
) {
291 int request_id
= dispatchers_
.Add(
292 CallbackDispatcher::Create(success_callback
, error_callback
));
293 ChildThreadImpl::current()->Send(
294 new FileSystemHostMsg_Write(request_id
, path
, blob_id
, offset
));
297 *request_id_out
= request_id
;
300 void FileSystemDispatcher::Cancel(
301 int request_id_to_cancel
,
302 const StatusCallback
& callback
) {
303 int request_id
= dispatchers_
.Add(CallbackDispatcher::Create(callback
));
304 ChildThreadImpl::current()->Send(new FileSystemHostMsg_CancelWrite(
305 request_id
, request_id_to_cancel
));
308 void FileSystemDispatcher::TouchFile(
310 const base::Time
& last_access_time
,
311 const base::Time
& last_modified_time
,
312 const StatusCallback
& callback
) {
313 int request_id
= dispatchers_
.Add(CallbackDispatcher::Create(callback
));
314 ChildThreadImpl::current()->Send(
315 new FileSystemHostMsg_TouchFile(
316 request_id
, path
, last_access_time
, last_modified_time
));
319 void FileSystemDispatcher::CreateSnapshotFile(
320 const GURL
& file_path
,
321 const CreateSnapshotFileCallback
& success_callback
,
322 const StatusCallback
& error_callback
) {
323 int request_id
= dispatchers_
.Add(
324 CallbackDispatcher::Create(success_callback
, error_callback
));
325 ChildThreadImpl::current()->Send(
326 new FileSystemHostMsg_CreateSnapshotFile(
327 request_id
, file_path
));
330 void FileSystemDispatcher::OnDidOpenFileSystem(int request_id
,
331 const std::string
& name
,
333 DCHECK(root
.is_valid());
334 CallbackDispatcher
* dispatcher
= dispatchers_
.Lookup(request_id
);
336 dispatcher
->DidOpenFileSystem(name
, root
);
337 dispatchers_
.Remove(request_id
);
340 void FileSystemDispatcher::OnDidResolveURL(int request_id
,
341 const storage::FileSystemInfo
& info
,
342 const base::FilePath
& file_path
,
344 DCHECK(info
.root_url
.is_valid());
345 CallbackDispatcher
* dispatcher
= dispatchers_
.Lookup(request_id
);
347 dispatcher
->DidResolveURL(info
, file_path
, is_directory
);
348 dispatchers_
.Remove(request_id
);
351 void FileSystemDispatcher::OnDidSucceed(int request_id
) {
352 CallbackDispatcher
* dispatcher
= dispatchers_
.Lookup(request_id
);
354 dispatcher
->DidSucceed();
355 dispatchers_
.Remove(request_id
);
358 void FileSystemDispatcher::OnDidReadMetadata(
359 int request_id
, const base::File::Info
& file_info
) {
360 CallbackDispatcher
* dispatcher
= dispatchers_
.Lookup(request_id
);
362 dispatcher
->DidReadMetadata(file_info
);
363 dispatchers_
.Remove(request_id
);
366 void FileSystemDispatcher::OnDidCreateSnapshotFile(
367 int request_id
, const base::File::Info
& file_info
,
368 const base::FilePath
& platform_path
) {
369 CallbackDispatcher
* dispatcher
= dispatchers_
.Lookup(request_id
);
371 dispatcher
->DidCreateSnapshotFile(file_info
, platform_path
, request_id
);
372 dispatchers_
.Remove(request_id
);
375 void FileSystemDispatcher::OnDidReadDirectory(
377 const std::vector
<storage::DirectoryEntry
>& entries
,
379 CallbackDispatcher
* dispatcher
= dispatchers_
.Lookup(request_id
);
381 dispatcher
->DidReadDirectory(entries
, has_more
);
383 dispatchers_
.Remove(request_id
);
386 void FileSystemDispatcher::OnDidFail(
387 int request_id
, base::File::Error error_code
) {
388 CallbackDispatcher
* dispatcher
= dispatchers_
.Lookup(request_id
);
390 dispatcher
->DidFail(error_code
);
391 dispatchers_
.Remove(request_id
);
394 void FileSystemDispatcher::OnDidWrite(
395 int request_id
, int64 bytes
, bool complete
) {
396 CallbackDispatcher
* dispatcher
= dispatchers_
.Lookup(request_id
);
398 dispatcher
->DidWrite(bytes
, complete
);
400 dispatchers_
.Remove(request_id
);
403 } // namespace content