OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #include "content/common/fileapi/file_system_dispatcher.h" | |
6 | |
7 #include "base/callback.h" | |
8 #include "base/file_util.h" | |
9 #include "base/process.h" | |
10 #include "content/common/child_thread.h" | |
11 #include "content/common/fileapi/file_system_messages.h" | |
12 | |
13 namespace content { | |
14 | |
15 class FileSystemDispatcher::CallbackDispatcher { | |
16 public: | |
17 typedef CallbackDispatcher self; | |
18 typedef FileSystemDispatcher::StatusCallback StatusCallback; | |
19 typedef FileSystemDispatcher::MetadataCallback MetadataCallback; | |
20 typedef FileSystemDispatcher::ReadDirectoryCallback ReadDirectoryCallback; | |
21 typedef FileSystemDispatcher::OpenFileSystemCallback OpenFileSystemCallback; | |
22 typedef FileSystemDispatcher::WriteCallback WriteCallback; | |
23 typedef FileSystemDispatcher::OpenFileCallback OpenFileCallback; | |
24 | |
25 static CallbackDispatcher* Create(const StatusCallback& callback) { | |
26 CallbackDispatcher* dispatcher = new CallbackDispatcher; | |
27 dispatcher->status_callback_ = callback; | |
28 dispatcher->error_callback_ = callback; | |
29 return dispatcher; | |
30 } | |
31 static CallbackDispatcher* Create(const MetadataCallback& callback, | |
32 const StatusCallback& error_callback) { | |
33 CallbackDispatcher* dispatcher = new CallbackDispatcher; | |
34 dispatcher->metadata_callback_ = callback; | |
35 dispatcher->error_callback_ = error_callback; | |
36 return dispatcher; | |
37 } | |
38 static CallbackDispatcher* Create(const ReadDirectoryCallback& callback, | |
39 const StatusCallback& error_callback) { | |
40 CallbackDispatcher* dispatcher = new CallbackDispatcher; | |
41 dispatcher->directory_callback_ = callback; | |
42 dispatcher->error_callback_ = error_callback; | |
43 return dispatcher; | |
44 } | |
45 static CallbackDispatcher* Create(const OpenFileSystemCallback& callback, | |
46 const StatusCallback& error_callback) { | |
47 CallbackDispatcher* dispatcher = new CallbackDispatcher; | |
48 dispatcher->filesystem_callback_ = callback; | |
49 dispatcher->error_callback_ = error_callback; | |
50 return dispatcher; | |
51 } | |
52 static CallbackDispatcher* Create(const WriteCallback& callback, | |
53 const StatusCallback& error_callback) { | |
54 CallbackDispatcher* dispatcher = new CallbackDispatcher; | |
55 dispatcher->write_callback_ = callback; | |
56 dispatcher->error_callback_ = error_callback; | |
57 return dispatcher; | |
58 } | |
59 static CallbackDispatcher* Create(const OpenFileCallback& callback, | |
60 const StatusCallback& error_callback) { | |
61 CallbackDispatcher* dispatcher = new CallbackDispatcher; | |
62 dispatcher->open_callback_ = callback; | |
63 dispatcher->error_callback_ = error_callback; | |
64 return dispatcher; | |
65 } | |
66 | |
67 ~CallbackDispatcher() {} | |
68 | |
69 void DidSucceed() { | |
70 status_callback_.Run(base::PLATFORM_FILE_OK); | |
71 } | |
72 | |
73 void DidFail(base::PlatformFileError error_code) { | |
74 error_callback_.Run(error_code); | |
75 } | |
76 | |
77 void DidReadMetadata( | |
78 const base::PlatformFileInfo& file_info, | |
79 const base::FilePath& platform_path) { | |
80 metadata_callback_.Run(file_info, platform_path); | |
81 } | |
82 | |
83 void DidCreateSnapshotFile( | |
84 const base::PlatformFileInfo& file_info, | |
85 const base::FilePath& platform_path) { | |
86 metadata_callback_.Run(file_info, platform_path); | |
87 } | |
88 | |
89 void DidReadDirectory( | |
90 const std::vector<fileapi::DirectoryEntry>& entries, | |
91 bool has_more) { | |
92 directory_callback_.Run(entries, has_more); | |
93 } | |
94 | |
95 void DidOpenFileSystem(const std::string& name, | |
96 const GURL& root) { | |
97 filesystem_callback_.Run(name, root); | |
98 } | |
99 | |
100 void DidWrite(int64 bytes, bool complete) { | |
101 write_callback_.Run(bytes, complete); | |
102 } | |
103 | |
104 void DidOpenFile(base::PlatformFile file, | |
105 int file_open_id, | |
106 quota::QuotaLimitType quota_policy) { | |
107 open_callback_.Run(file, file_open_id, quota_policy); | |
108 } | |
109 | |
110 private: | |
111 CallbackDispatcher() {} | |
112 | |
113 StatusCallback status_callback_; | |
114 MetadataCallback metadata_callback_; | |
115 ReadDirectoryCallback directory_callback_; | |
116 OpenFileSystemCallback filesystem_callback_; | |
117 WriteCallback write_callback_; | |
118 OpenFileCallback open_callback_; | |
119 | |
120 StatusCallback error_callback_; | |
121 | |
122 DISALLOW_COPY_AND_ASSIGN(CallbackDispatcher); | |
123 }; | |
124 | |
125 FileSystemDispatcher::FileSystemDispatcher() { | |
126 } | |
127 | |
128 FileSystemDispatcher::~FileSystemDispatcher() { | |
129 // Make sure we fire all the remaining callbacks. | |
130 for (IDMap<CallbackDispatcher, IDMapOwnPointer>::iterator | |
131 iter(&dispatchers_); !iter.IsAtEnd(); iter.Advance()) { | |
132 int request_id = iter.GetCurrentKey(); | |
133 CallbackDispatcher* dispatcher = iter.GetCurrentValue(); | |
134 DCHECK(dispatcher); | |
135 dispatcher->DidFail(base::PLATFORM_FILE_ERROR_ABORT); | |
136 dispatchers_.Remove(request_id); | |
137 } | |
138 } | |
139 | |
140 bool FileSystemDispatcher::OnMessageReceived(const IPC::Message& msg) { | |
141 bool handled = true; | |
142 IPC_BEGIN_MESSAGE_MAP(FileSystemDispatcher, msg) | |
143 IPC_MESSAGE_HANDLER(FileSystemMsg_DidOpenFileSystem, OnDidOpenFileSystem) | |
144 IPC_MESSAGE_HANDLER(FileSystemMsg_DidSucceed, OnDidSucceed) | |
145 IPC_MESSAGE_HANDLER(FileSystemMsg_DidReadDirectory, OnDidReadDirectory) | |
146 IPC_MESSAGE_HANDLER(FileSystemMsg_DidReadMetadata, OnDidReadMetadata) | |
147 IPC_MESSAGE_HANDLER(FileSystemMsg_DidCreateSnapshotFile, | |
148 OnDidCreateSnapshotFile) | |
149 IPC_MESSAGE_HANDLER(FileSystemMsg_DidFail, OnDidFail) | |
150 IPC_MESSAGE_HANDLER(FileSystemMsg_DidWrite, OnDidWrite) | |
151 IPC_MESSAGE_HANDLER(FileSystemMsg_DidOpenFile, OnDidOpenFile) | |
152 IPC_MESSAGE_UNHANDLED(handled = false) | |
153 IPC_END_MESSAGE_MAP() | |
154 return handled; | |
155 } | |
156 | |
157 bool FileSystemDispatcher::OpenFileSystem( | |
158 const GURL& origin_url, fileapi::FileSystemType type, | |
159 long long size, bool create, | |
160 const OpenFileSystemCallback& success_callback, | |
161 const StatusCallback& error_callback) { | |
162 int request_id = dispatchers_.Add( | |
163 CallbackDispatcher::Create(success_callback, error_callback)); | |
164 if (!ChildThread::current()->Send(new FileSystemHostMsg_Open( | |
165 request_id, origin_url, type, size, create))) { | |
166 dispatchers_.Remove(request_id); // destroys |dispatcher| | |
167 return false; | |
168 } | |
169 | |
170 return true; | |
171 } | |
172 | |
173 bool FileSystemDispatcher::DeleteFileSystem( | |
174 const GURL& origin_url, | |
175 fileapi::FileSystemType type, | |
176 const StatusCallback& callback) { | |
177 int request_id = dispatchers_.Add(CallbackDispatcher::Create(callback)); | |
178 if (!ChildThread::current()->Send(new FileSystemHostMsg_DeleteFileSystem( | |
179 request_id, origin_url, type))) { | |
180 dispatchers_.Remove(request_id); | |
181 return false; | |
182 } | |
183 return true; | |
184 } | |
185 | |
186 bool FileSystemDispatcher::Move( | |
187 const GURL& src_path, | |
188 const GURL& dest_path, | |
189 const StatusCallback& callback) { | |
190 int request_id = dispatchers_.Add(CallbackDispatcher::Create(callback)); | |
191 if (!ChildThread::current()->Send(new FileSystemHostMsg_Move( | |
192 request_id, src_path, dest_path))) { | |
193 dispatchers_.Remove(request_id); // destroys |dispatcher| | |
194 return false; | |
195 } | |
196 | |
197 return true; | |
198 } | |
199 | |
200 bool FileSystemDispatcher::Copy( | |
201 const GURL& src_path, | |
202 const GURL& dest_path, | |
203 const StatusCallback& callback) { | |
204 int request_id = dispatchers_.Add(CallbackDispatcher::Create(callback)); | |
205 if (!ChildThread::current()->Send(new FileSystemHostMsg_Copy( | |
206 request_id, src_path, dest_path))) { | |
207 dispatchers_.Remove(request_id); // destroys |dispatcher| | |
208 return false; | |
209 } | |
210 | |
211 return true; | |
212 } | |
213 | |
214 bool FileSystemDispatcher::Remove( | |
215 const GURL& path, | |
216 bool recursive, | |
217 const StatusCallback& callback) { | |
218 int request_id = dispatchers_.Add(CallbackDispatcher::Create(callback)); | |
219 if (!ChildThread::current()->Send( | |
220 new FileSystemMsg_Remove(request_id, path, recursive))) { | |
221 dispatchers_.Remove(request_id); // destroys |dispatcher| | |
222 return false; | |
223 } | |
224 | |
225 return true; | |
226 } | |
227 | |
228 bool FileSystemDispatcher::ReadMetadata( | |
229 const GURL& path, | |
230 const MetadataCallback& success_callback, | |
231 const StatusCallback& error_callback) { | |
232 int request_id = dispatchers_.Add( | |
233 CallbackDispatcher::Create(success_callback, error_callback)); | |
234 if (!ChildThread::current()->Send( | |
235 new FileSystemHostMsg_ReadMetadata(request_id, path))) { | |
236 dispatchers_.Remove(request_id); // destroys |dispatcher| | |
237 return false; | |
238 } | |
239 | |
240 return true; | |
241 } | |
242 | |
243 bool FileSystemDispatcher::Create( | |
244 const GURL& path, | |
245 bool exclusive, | |
246 bool is_directory, | |
247 bool recursive, | |
248 const StatusCallback& callback) { | |
249 int request_id = dispatchers_.Add(CallbackDispatcher::Create(callback)); | |
250 if (!ChildThread::current()->Send(new FileSystemHostMsg_Create( | |
251 request_id, path, exclusive, is_directory, recursive))) { | |
252 dispatchers_.Remove(request_id); // destroys |dispatcher| | |
253 return false; | |
254 } | |
255 | |
256 return true; | |
257 } | |
258 | |
259 bool FileSystemDispatcher::Exists( | |
260 const GURL& path, | |
261 bool is_directory, | |
262 const StatusCallback& callback) { | |
263 int request_id = dispatchers_.Add(CallbackDispatcher::Create(callback)); | |
264 if (!ChildThread::current()->Send( | |
265 new FileSystemHostMsg_Exists(request_id, path, is_directory))) { | |
266 dispatchers_.Remove(request_id); // destroys |dispatcher| | |
267 return false; | |
268 } | |
269 | |
270 return true; | |
271 } | |
272 | |
273 bool FileSystemDispatcher::ReadDirectory( | |
274 const GURL& path, | |
275 const ReadDirectoryCallback& success_callback, | |
276 const StatusCallback& error_callback) { | |
277 int request_id = dispatchers_.Add( | |
278 CallbackDispatcher::Create(success_callback, error_callback)); | |
279 if (!ChildThread::current()->Send( | |
280 new FileSystemHostMsg_ReadDirectory(request_id, path))) { | |
281 dispatchers_.Remove(request_id); // destroys |dispatcher| | |
282 return false; | |
283 } | |
284 | |
285 return true; | |
286 } | |
287 | |
288 bool FileSystemDispatcher::Truncate( | |
289 const GURL& path, | |
290 int64 offset, | |
291 int* request_id_out, | |
292 const StatusCallback& callback) { | |
293 int request_id = dispatchers_.Add(CallbackDispatcher::Create(callback)); | |
294 if (!ChildThread::current()->Send( | |
295 new FileSystemHostMsg_Truncate(request_id, path, offset))) { | |
296 dispatchers_.Remove(request_id); // destroys |dispatcher| | |
297 return false; | |
298 } | |
299 | |
300 if (request_id_out) | |
301 *request_id_out = request_id; | |
302 return true; | |
303 } | |
304 | |
305 bool FileSystemDispatcher::Write( | |
306 const GURL& path, | |
307 const GURL& blob_url, | |
308 int64 offset, | |
309 int* request_id_out, | |
310 const WriteCallback& success_callback, | |
311 const StatusCallback& error_callback) { | |
312 int request_id = dispatchers_.Add( | |
313 CallbackDispatcher::Create(success_callback, error_callback)); | |
314 if (!ChildThread::current()->Send( | |
315 new FileSystemHostMsg_Write(request_id, path, blob_url, offset))) { | |
316 dispatchers_.Remove(request_id); // destroys |dispatcher| | |
317 return false; | |
318 } | |
319 | |
320 if (request_id_out) | |
321 *request_id_out = request_id; | |
322 return true; | |
323 } | |
324 | |
325 bool FileSystemDispatcher::Cancel( | |
326 int request_id_to_cancel, | |
327 const StatusCallback& callback) { | |
328 int request_id = dispatchers_.Add(CallbackDispatcher::Create(callback)); | |
329 if (!ChildThread::current()->Send(new FileSystemHostMsg_CancelWrite( | |
330 request_id, request_id_to_cancel))) { | |
331 dispatchers_.Remove(request_id); // destroys |dispatcher| | |
332 return false; | |
333 } | |
334 | |
335 return true; | |
336 } | |
337 | |
338 bool FileSystemDispatcher::TouchFile( | |
339 const GURL& path, | |
340 const base::Time& last_access_time, | |
341 const base::Time& last_modified_time, | |
342 const StatusCallback& callback) { | |
343 int request_id = dispatchers_.Add(CallbackDispatcher::Create(callback)); | |
344 if (!ChildThread::current()->Send( | |
345 new FileSystemHostMsg_TouchFile( | |
346 request_id, path, last_access_time, last_modified_time))) { | |
347 dispatchers_.Remove(request_id); // destroys |dispatcher| | |
348 return false; | |
349 } | |
350 | |
351 return true; | |
352 } | |
353 | |
354 bool FileSystemDispatcher::OpenFile( | |
355 const GURL& file_path, | |
356 int file_flags, | |
357 const OpenFileCallback& success_callback, | |
358 const StatusCallback& error_callback) { | |
359 int request_id = dispatchers_.Add( | |
360 CallbackDispatcher::Create(success_callback, error_callback)); | |
361 if (!ChildThread::current()->Send( | |
362 new FileSystemHostMsg_OpenFile( | |
363 request_id, file_path, file_flags))) { | |
364 dispatchers_.Remove(request_id); // destroys |dispatcher| | |
365 return false; | |
366 } | |
367 | |
368 return true; | |
369 } | |
370 | |
371 bool FileSystemDispatcher::NotifyCloseFile(int file_open_id) { | |
372 return ChildThread::current()->Send( | |
373 new FileSystemHostMsg_NotifyCloseFile(file_open_id)); | |
374 } | |
375 | |
376 bool FileSystemDispatcher::CreateSnapshotFile( | |
377 const GURL& file_path, | |
378 const CreateSnapshotFileCallback& success_callback, | |
379 const StatusCallback& error_callback) { | |
380 int request_id = dispatchers_.Add( | |
381 CallbackDispatcher::Create(success_callback, error_callback)); | |
382 if (!ChildThread::current()->Send( | |
383 new FileSystemHostMsg_CreateSnapshotFile( | |
384 request_id, file_path))) { | |
385 dispatchers_.Remove(request_id); // destroys |dispatcher| | |
386 return false; | |
387 } | |
388 return true; | |
389 } | |
390 | |
391 void FileSystemDispatcher::OnDidOpenFileSystem(int request_id, | |
392 const std::string& name, | |
393 const GURL& root) { | |
394 DCHECK(root.is_valid()); | |
395 CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id); | |
396 DCHECK(dispatcher); | |
397 dispatcher->DidOpenFileSystem(name, root); | |
398 dispatchers_.Remove(request_id); | |
399 } | |
400 | |
401 void FileSystemDispatcher::OnDidSucceed(int request_id) { | |
402 CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id); | |
403 DCHECK(dispatcher); | |
404 dispatcher->DidSucceed(); | |
405 dispatchers_.Remove(request_id); | |
406 } | |
407 | |
408 void FileSystemDispatcher::OnDidReadMetadata( | |
409 int request_id, const base::PlatformFileInfo& file_info, | |
410 const base::FilePath& platform_path) { | |
411 CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id); | |
412 DCHECK(dispatcher); | |
413 dispatcher->DidReadMetadata(file_info, platform_path); | |
414 dispatchers_.Remove(request_id); | |
415 } | |
416 | |
417 void FileSystemDispatcher::OnDidCreateSnapshotFile( | |
418 int request_id, const base::PlatformFileInfo& file_info, | |
419 const base::FilePath& platform_path) { | |
420 CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id); | |
421 DCHECK(dispatcher); | |
422 dispatcher->DidCreateSnapshotFile(file_info, platform_path); | |
423 dispatchers_.Remove(request_id); | |
424 ChildThread::current()->Send( | |
425 new FileSystemHostMsg_DidReceiveSnapshotFile(request_id)); | |
426 } | |
427 | |
428 void FileSystemDispatcher::OnDidReadDirectory( | |
429 int request_id, | |
430 const std::vector<fileapi::DirectoryEntry>& entries, | |
431 bool has_more) { | |
432 CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id); | |
433 DCHECK(dispatcher); | |
434 dispatcher->DidReadDirectory(entries, has_more); | |
435 dispatchers_.Remove(request_id); | |
436 } | |
437 | |
438 void FileSystemDispatcher::OnDidFail( | |
439 int request_id, base::PlatformFileError error_code) { | |
440 CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id); | |
441 DCHECK(dispatcher); | |
442 dispatcher->DidFail(error_code); | |
443 dispatchers_.Remove(request_id); | |
444 } | |
445 | |
446 void FileSystemDispatcher::OnDidWrite( | |
447 int request_id, int64 bytes, bool complete) { | |
448 CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id); | |
449 DCHECK(dispatcher); | |
450 dispatcher->DidWrite(bytes, complete); | |
451 if (complete) | |
452 dispatchers_.Remove(request_id); | |
453 } | |
454 | |
455 void FileSystemDispatcher::OnDidOpenFile( | |
456 int request_id, | |
457 IPC::PlatformFileForTransit file, | |
458 int file_open_id, | |
459 quota::QuotaLimitType quota_policy) { | |
460 CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id); | |
461 DCHECK(dispatcher); | |
462 dispatcher->DidOpenFile(IPC::PlatformFileForTransitToPlatformFile(file), | |
463 file_open_id, | |
464 quota_policy); | |
465 dispatchers_.Remove(request_id); | |
466 } | |
467 | |
468 } // namespace content | |
OLD | NEW |