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/file_util.h"
9 #include "base/message_loop/message_loop_proxy.h"
10 #include "base/process/process.h"
11 #include "content/child/child_thread.h"
12 #include "content/common/fileapi/file_system_messages.h"
13 #include "webkit/common/fileapi/file_system_info.h"
17 class FileSystemDispatcher::CallbackDispatcher
{
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
;
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
;
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
;
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
;
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
;
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
;
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
;
77 ~CallbackDispatcher() {}
80 status_callback_
.Run(base::File::FILE_OK
);
83 void DidFail(base::File::Error error_code
) {
84 error_callback_
.Run(error_code
);
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
,
96 snapshot_callback_
.Run(file_info
, platform_path
, request_id
);
99 void DidReadDirectory(
100 const std::vector
<fileapi::DirectoryEntry
>& entries
,
102 directory_callback_
.Run(entries
, has_more
);
105 void DidOpenFileSystem(const std::string
& name
,
107 filesystem_callback_
.Run(name
, root
);
110 void DidResolveURL(const fileapi::FileSystemInfo
& info
,
111 const base::FilePath
& file_path
,
113 resolve_callback_
.Run(info
, file_path
, is_directory
);
116 void DidWrite(int64 bytes
, bool complete
) {
117 write_callback_
.Run(bytes
, complete
);
120 void DidOpenFile(base::PlatformFile file
,
122 quota::QuotaLimitType quota_policy
) {
123 open_callback_
.Run(file
, file_open_id
, quota_policy
);
127 CallbackDispatcher() {}
129 StatusCallback status_callback_
;
130 MetadataCallback metadata_callback_
;
131 CreateSnapshotFileCallback snapshot_callback_
;
132 ReadDirectoryCallback directory_callback_
;
133 OpenFileSystemCallback filesystem_callback_
;
134 ResolveURLCallback resolve_callback_
;
135 WriteCallback write_callback_
;
136 OpenFileCallback open_callback_
;
138 StatusCallback error_callback_
;
140 DISALLOW_COPY_AND_ASSIGN(CallbackDispatcher
);
143 FileSystemDispatcher::FileSystemDispatcher() {
146 FileSystemDispatcher::~FileSystemDispatcher() {
147 // Make sure we fire all the remaining callbacks.
148 for (IDMap
<CallbackDispatcher
, IDMapOwnPointer
>::iterator
149 iter(&dispatchers_
); !iter
.IsAtEnd(); iter
.Advance()) {
150 int request_id
= iter
.GetCurrentKey();
151 CallbackDispatcher
* dispatcher
= iter
.GetCurrentValue();
153 dispatcher
->DidFail(base::File::FILE_ERROR_ABORT
);
154 dispatchers_
.Remove(request_id
);
158 bool FileSystemDispatcher::OnMessageReceived(const IPC::Message
& msg
) {
160 IPC_BEGIN_MESSAGE_MAP(FileSystemDispatcher
, msg
)
161 IPC_MESSAGE_HANDLER(FileSystemMsg_DidOpenFileSystem
, OnDidOpenFileSystem
)
162 IPC_MESSAGE_HANDLER(FileSystemMsg_DidResolveURL
, OnDidResolveURL
)
163 IPC_MESSAGE_HANDLER(FileSystemMsg_DidSucceed
, OnDidSucceed
)
164 IPC_MESSAGE_HANDLER(FileSystemMsg_DidReadDirectory
, OnDidReadDirectory
)
165 IPC_MESSAGE_HANDLER(FileSystemMsg_DidReadMetadata
, OnDidReadMetadata
)
166 IPC_MESSAGE_HANDLER(FileSystemMsg_DidCreateSnapshotFile
,
167 OnDidCreateSnapshotFile
)
168 IPC_MESSAGE_HANDLER(FileSystemMsg_DidFail
, OnDidFail
)
169 IPC_MESSAGE_HANDLER(FileSystemMsg_DidWrite
, OnDidWrite
)
170 IPC_MESSAGE_HANDLER(FileSystemMsg_DidOpenFile
, OnDidOpenFile
)
171 IPC_MESSAGE_UNHANDLED(handled
= false)
172 IPC_END_MESSAGE_MAP()
176 void FileSystemDispatcher::OpenFileSystem(
177 const GURL
& origin_url
,
178 fileapi::FileSystemType type
,
179 const OpenFileSystemCallback
& success_callback
,
180 const StatusCallback
& error_callback
) {
181 int request_id
= dispatchers_
.Add(
182 CallbackDispatcher::Create(success_callback
, error_callback
));
183 ChildThread::current()->Send(new FileSystemHostMsg_OpenFileSystem(
184 request_id
, origin_url
, type
));
187 void FileSystemDispatcher::ResolveURL(
188 const GURL
& filesystem_url
,
189 const ResolveURLCallback
& success_callback
,
190 const StatusCallback
& error_callback
) {
191 int request_id
= dispatchers_
.Add(
192 CallbackDispatcher::Create(success_callback
, error_callback
));
193 ChildThread::current()->Send(new FileSystemHostMsg_ResolveURL(
194 request_id
, filesystem_url
));
197 void FileSystemDispatcher::DeleteFileSystem(
198 const GURL
& origin_url
,
199 fileapi::FileSystemType type
,
200 const StatusCallback
& callback
) {
201 int request_id
= dispatchers_
.Add(CallbackDispatcher::Create(callback
));
202 ChildThread::current()->Send(new FileSystemHostMsg_DeleteFileSystem(
203 request_id
, origin_url
, type
));
206 void FileSystemDispatcher::Move(
207 const GURL
& src_path
,
208 const GURL
& dest_path
,
209 const StatusCallback
& callback
) {
210 int request_id
= dispatchers_
.Add(CallbackDispatcher::Create(callback
));
211 ChildThread::current()->Send(new FileSystemHostMsg_Move(
212 request_id
, src_path
, dest_path
));
215 void FileSystemDispatcher::Copy(
216 const GURL
& src_path
,
217 const GURL
& dest_path
,
218 const StatusCallback
& callback
) {
219 int request_id
= dispatchers_
.Add(CallbackDispatcher::Create(callback
));
220 ChildThread::current()->Send(new FileSystemHostMsg_Copy(
221 request_id
, src_path
, dest_path
));
224 void FileSystemDispatcher::Remove(
227 const StatusCallback
& callback
) {
228 int request_id
= dispatchers_
.Add(CallbackDispatcher::Create(callback
));
229 ChildThread::current()->Send(
230 new FileSystemHostMsg_Remove(request_id
, path
, recursive
));
233 void FileSystemDispatcher::ReadMetadata(
235 const MetadataCallback
& success_callback
,
236 const StatusCallback
& error_callback
) {
237 int request_id
= dispatchers_
.Add(
238 CallbackDispatcher::Create(success_callback
, error_callback
));
239 ChildThread::current()->Send(
240 new FileSystemHostMsg_ReadMetadata(request_id
, path
));
243 void FileSystemDispatcher::CreateFile(
246 const StatusCallback
& callback
) {
247 int request_id
= dispatchers_
.Add(CallbackDispatcher::Create(callback
));
248 ChildThread::current()->Send(new FileSystemHostMsg_Create(
249 request_id
, path
, exclusive
,
250 false /* is_directory */, false /* recursive */));
253 void FileSystemDispatcher::CreateDirectory(
257 const StatusCallback
& callback
) {
258 int request_id
= dispatchers_
.Add(CallbackDispatcher::Create(callback
));
259 ChildThread::current()->Send(new FileSystemHostMsg_Create(
260 request_id
, path
, exclusive
, true /* is_directory */, recursive
));
263 void FileSystemDispatcher::Exists(
266 const StatusCallback
& callback
) {
267 int request_id
= dispatchers_
.Add(CallbackDispatcher::Create(callback
));
268 ChildThread::current()->Send(
269 new FileSystemHostMsg_Exists(request_id
, path
, is_directory
));
272 void FileSystemDispatcher::ReadDirectory(
274 const ReadDirectoryCallback
& success_callback
,
275 const StatusCallback
& error_callback
) {
276 int request_id
= dispatchers_
.Add(
277 CallbackDispatcher::Create(success_callback
, error_callback
));
278 ChildThread::current()->Send(
279 new FileSystemHostMsg_ReadDirectory(request_id
, path
));
282 void FileSystemDispatcher::Truncate(
286 const StatusCallback
& callback
) {
287 int request_id
= dispatchers_
.Add(CallbackDispatcher::Create(callback
));
288 ChildThread::current()->Send(
289 new FileSystemHostMsg_Truncate(request_id
, path
, offset
));
292 *request_id_out
= request_id
;
295 void FileSystemDispatcher::Write(
297 const std::string
& blob_id
,
300 const WriteCallback
& success_callback
,
301 const StatusCallback
& error_callback
) {
302 int request_id
= dispatchers_
.Add(
303 CallbackDispatcher::Create(success_callback
, error_callback
));
304 ChildThread::current()->Send(
305 new FileSystemHostMsg_Write(request_id
, path
, blob_id
, offset
));
308 *request_id_out
= request_id
;
311 void FileSystemDispatcher::Cancel(
312 int request_id_to_cancel
,
313 const StatusCallback
& callback
) {
314 int request_id
= dispatchers_
.Add(CallbackDispatcher::Create(callback
));
315 ChildThread::current()->Send(new FileSystemHostMsg_CancelWrite(
316 request_id
, request_id_to_cancel
));
319 void FileSystemDispatcher::TouchFile(
321 const base::Time
& last_access_time
,
322 const base::Time
& last_modified_time
,
323 const StatusCallback
& callback
) {
324 int request_id
= dispatchers_
.Add(CallbackDispatcher::Create(callback
));
325 ChildThread::current()->Send(
326 new FileSystemHostMsg_TouchFile(
327 request_id
, path
, last_access_time
, last_modified_time
));
330 void FileSystemDispatcher::CreateSnapshotFile(
331 const GURL
& file_path
,
332 const CreateSnapshotFileCallback
& success_callback
,
333 const StatusCallback
& error_callback
) {
334 int request_id
= dispatchers_
.Add(
335 CallbackDispatcher::Create(success_callback
, error_callback
));
336 ChildThread::current()->Send(
337 new FileSystemHostMsg_CreateSnapshotFile(
338 request_id
, file_path
));
341 void FileSystemDispatcher::OnDidOpenFileSystem(int request_id
,
342 const std::string
& name
,
344 DCHECK(root
.is_valid());
345 CallbackDispatcher
* dispatcher
= dispatchers_
.Lookup(request_id
);
347 dispatcher
->DidOpenFileSystem(name
, root
);
348 dispatchers_
.Remove(request_id
);
351 void FileSystemDispatcher::OnDidResolveURL(int request_id
,
352 const fileapi::FileSystemInfo
& info
,
353 const base::FilePath
& file_path
,
355 DCHECK(info
.root_url
.is_valid());
356 CallbackDispatcher
* dispatcher
= dispatchers_
.Lookup(request_id
);
358 dispatcher
->DidResolveURL(info
, file_path
, is_directory
);
359 dispatchers_
.Remove(request_id
);
362 void FileSystemDispatcher::OnDidSucceed(int request_id
) {
363 CallbackDispatcher
* dispatcher
= dispatchers_
.Lookup(request_id
);
365 dispatcher
->DidSucceed();
366 dispatchers_
.Remove(request_id
);
369 void FileSystemDispatcher::OnDidReadMetadata(
370 int request_id
, const base::File::Info
& file_info
) {
371 CallbackDispatcher
* dispatcher
= dispatchers_
.Lookup(request_id
);
373 dispatcher
->DidReadMetadata(file_info
);
374 dispatchers_
.Remove(request_id
);
377 void FileSystemDispatcher::OnDidCreateSnapshotFile(
378 int request_id
, const base::File::Info
& file_info
,
379 const base::FilePath
& platform_path
) {
380 CallbackDispatcher
* dispatcher
= dispatchers_
.Lookup(request_id
);
382 dispatcher
->DidCreateSnapshotFile(file_info
, platform_path
, request_id
);
383 dispatchers_
.Remove(request_id
);
386 void FileSystemDispatcher::OnDidReadDirectory(
388 const std::vector
<fileapi::DirectoryEntry
>& entries
,
390 CallbackDispatcher
* dispatcher
= dispatchers_
.Lookup(request_id
);
392 dispatcher
->DidReadDirectory(entries
, has_more
);
394 dispatchers_
.Remove(request_id
);
397 void FileSystemDispatcher::OnDidFail(
398 int request_id
, base::File::Error error_code
) {
399 CallbackDispatcher
* dispatcher
= dispatchers_
.Lookup(request_id
);
401 dispatcher
->DidFail(error_code
);
402 dispatchers_
.Remove(request_id
);
405 void FileSystemDispatcher::OnDidWrite(
406 int request_id
, int64 bytes
, bool complete
) {
407 CallbackDispatcher
* dispatcher
= dispatchers_
.Lookup(request_id
);
409 dispatcher
->DidWrite(bytes
, complete
);
411 dispatchers_
.Remove(request_id
);
414 void FileSystemDispatcher::OnDidOpenFile(
416 IPC::PlatformFileForTransit file
,
418 quota::QuotaLimitType quota_policy
) {
419 CallbackDispatcher
* dispatcher
= dispatchers_
.Lookup(request_id
);
421 dispatcher
->DidOpenFile(IPC::PlatformFileForTransitToPlatformFile(file
),
424 dispatchers_
.Remove(request_id
);
427 } // namespace content