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