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"
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(const std::vector
<storage::DirectoryEntry
>& entries
,
101 directory_callback_
.Run(entries
, has_more
);
104 void DidOpenFileSystem(const std::string
& name
,
106 filesystem_callback_
.Run(name
, root
);
109 void DidResolveURL(const storage::FileSystemInfo
& info
,
110 const base::FilePath
& file_path
,
112 resolve_callback_
.Run(info
, file_path
, is_directory
);
115 void DidWrite(int64 bytes
, bool complete
) {
116 write_callback_
.Run(bytes
, complete
);
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();
145 dispatcher
->DidFail(base::File::FILE_ERROR_ABORT
);
146 dispatchers_
.Remove(request_id
);
150 bool FileSystemDispatcher::OnMessageReceived(const IPC::Message
& msg
) {
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()
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(
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(
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(
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(
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(
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(
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(
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
));
282 *request_id_out
= request_id
;
285 void FileSystemDispatcher::Write(
287 const std::string
& blob_id
,
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
));
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(
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
,
334 DCHECK(root
.is_valid());
335 CallbackDispatcher
* dispatcher
= dispatchers_
.Lookup(request_id
);
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
,
345 DCHECK(info
.root_url
.is_valid());
346 CallbackDispatcher
* dispatcher
= dispatchers_
.Lookup(request_id
);
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
);
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
);
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
);
372 dispatcher
->DidCreateSnapshotFile(file_info
, platform_path
, request_id
);
373 dispatchers_
.Remove(request_id
);
376 void FileSystemDispatcher::OnDidReadDirectory(
378 const std::vector
<storage::DirectoryEntry
>& entries
,
380 CallbackDispatcher
* dispatcher
= dispatchers_
.Lookup(request_id
);
382 dispatcher
->DidReadDirectory(entries
, 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
);
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
);
399 dispatcher
->DidWrite(bytes
, complete
);
401 dispatchers_
.Remove(request_id
);
404 } // namespace content