Upstream version 10.39.225.0
[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/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.h"
12 #include "content/common/fileapi/file_system_messages.h"
13 #include "storage/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
77   ~CallbackDispatcher() {}
78
79   void DidSucceed() {
80     status_callback_.Run(base::File::FILE_OK);
81   }
82
83   void DidFail(base::File::Error error_code) {
84     error_callback_.Run(error_code);
85   }
86
87   void DidReadMetadata(
88       const base::File::Info& file_info) {
89     metadata_callback_.Run(file_info);
90   }
91
92   void DidCreateSnapshotFile(
93       const base::File::Info& file_info,
94       const base::FilePath& platform_path,
95       int request_id) {
96     snapshot_callback_.Run(file_info, platform_path, request_id);
97   }
98
99   void DidReadDirectory(const std::vector<storage::DirectoryEntry>& entries,
100                         bool has_more) {
101     directory_callback_.Run(entries, has_more);
102   }
103
104   void DidOpenFileSystem(const std::string& name,
105                          const GURL& root) {
106     filesystem_callback_.Run(name, root);
107   }
108
109   void DidResolveURL(const storage::FileSystemInfo& info,
110                      const base::FilePath& file_path,
111                      bool is_directory) {
112     resolve_callback_.Run(info, file_path, is_directory);
113   }
114
115   void DidWrite(int64 bytes, bool complete) {
116     write_callback_.Run(bytes, complete);
117   }
118
119  private:
120   CallbackDispatcher() {}
121
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_;
129
130   StatusCallback error_callback_;
131
132   DISALLOW_COPY_AND_ASSIGN(CallbackDispatcher);
133 };
134
135 FileSystemDispatcher::FileSystemDispatcher() {
136 }
137
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();
144     DCHECK(dispatcher);
145     dispatcher->DidFail(base::File::FILE_ERROR_ABORT);
146     dispatchers_.Remove(request_id);
147   }
148 }
149
150 bool FileSystemDispatcher::OnMessageReceived(const IPC::Message& msg) {
151   bool handled = true;
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()
164   return handled;
165 }
166
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   ChildThread::current()->Send(new FileSystemHostMsg_OpenFileSystem(
175       request_id, origin_url, type));
176 }
177
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   ChildThread::current()->Send(new FileSystemHostMsg_ResolveURL(
185           request_id, filesystem_url));
186 }
187
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   ChildThread::current()->Send(new FileSystemHostMsg_DeleteFileSystem(
193           request_id, origin_url, type));
194 }
195
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   ChildThread::current()->Send(new FileSystemHostMsg_Move(
202           request_id, src_path, dest_path));
203 }
204
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   ChildThread::current()->Send(new FileSystemHostMsg_Copy(
211       request_id, src_path, dest_path));
212 }
213
214 void FileSystemDispatcher::Remove(
215     const GURL& path,
216     bool recursive,
217     const StatusCallback& callback) {
218   int request_id = dispatchers_.Add(CallbackDispatcher::Create(callback));
219   ChildThread::current()->Send(
220       new FileSystemHostMsg_Remove(request_id, path, recursive));
221 }
222
223 void FileSystemDispatcher::ReadMetadata(
224     const GURL& path,
225     const MetadataCallback& success_callback,
226     const StatusCallback& error_callback) {
227   int request_id = dispatchers_.Add(
228       CallbackDispatcher::Create(success_callback, error_callback));
229   ChildThread::current()->Send(
230       new FileSystemHostMsg_ReadMetadata(request_id, path));
231 }
232
233 void FileSystemDispatcher::CreateFile(
234     const GURL& path,
235     bool exclusive,
236     const StatusCallback& callback) {
237   int request_id = dispatchers_.Add(CallbackDispatcher::Create(callback));
238   ChildThread::current()->Send(new FileSystemHostMsg_Create(
239       request_id, path, exclusive,
240       false /* is_directory */, false /* recursive */));
241 }
242
243 void FileSystemDispatcher::CreateDirectory(
244     const GURL& path,
245     bool exclusive,
246     bool recursive,
247     const StatusCallback& callback) {
248   int request_id = dispatchers_.Add(CallbackDispatcher::Create(callback));
249   ChildThread::current()->Send(new FileSystemHostMsg_Create(
250       request_id, path, exclusive, true /* is_directory */, recursive));
251 }
252
253 void FileSystemDispatcher::Exists(
254     const GURL& path,
255     bool is_directory,
256     const StatusCallback& callback) {
257   int request_id = dispatchers_.Add(CallbackDispatcher::Create(callback));
258   ChildThread::current()->Send(
259       new FileSystemHostMsg_Exists(request_id, path, is_directory));
260 }
261
262 void FileSystemDispatcher::ReadDirectory(
263     const GURL& path,
264     const ReadDirectoryCallback& success_callback,
265     const StatusCallback& error_callback) {
266   int request_id = dispatchers_.Add(
267       CallbackDispatcher::Create(success_callback, error_callback));
268   ChildThread::current()->Send(
269       new FileSystemHostMsg_ReadDirectory(request_id, path));
270 }
271
272 void FileSystemDispatcher::Truncate(
273     const GURL& path,
274     int64 offset,
275     int* request_id_out,
276     const StatusCallback& callback) {
277   int request_id = dispatchers_.Add(CallbackDispatcher::Create(callback));
278   ChildThread::current()->Send(
279       new FileSystemHostMsg_Truncate(request_id, path, offset));
280
281   if (request_id_out)
282     *request_id_out = request_id;
283 }
284
285 void FileSystemDispatcher::Write(
286     const GURL& path,
287     const std::string& blob_id,
288     int64 offset,
289     int* request_id_out,
290     const WriteCallback& success_callback,
291     const StatusCallback& error_callback) {
292   int request_id = dispatchers_.Add(
293       CallbackDispatcher::Create(success_callback, error_callback));
294   ChildThread::current()->Send(
295       new FileSystemHostMsg_Write(request_id, path, blob_id, offset));
296
297   if (request_id_out)
298     *request_id_out = request_id;
299 }
300
301 void FileSystemDispatcher::Cancel(
302     int request_id_to_cancel,
303     const StatusCallback& callback) {
304   int request_id = dispatchers_.Add(CallbackDispatcher::Create(callback));
305   ChildThread::current()->Send(new FileSystemHostMsg_CancelWrite(
306       request_id, request_id_to_cancel));
307 }
308
309 void FileSystemDispatcher::TouchFile(
310     const GURL& path,
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   ChildThread::current()->Send(
316       new FileSystemHostMsg_TouchFile(
317           request_id, path, last_access_time, last_modified_time));
318 }
319
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   ChildThread::current()->Send(
327       new FileSystemHostMsg_CreateSnapshotFile(
328           request_id, file_path));
329 }
330
331 void FileSystemDispatcher::OnDidOpenFileSystem(int request_id,
332                                                const std::string& name,
333                                                const GURL& root) {
334   DCHECK(root.is_valid());
335   CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id);
336   DCHECK(dispatcher);
337   dispatcher->DidOpenFileSystem(name, root);
338   dispatchers_.Remove(request_id);
339 }
340
341 void FileSystemDispatcher::OnDidResolveURL(int request_id,
342                                            const storage::FileSystemInfo& info,
343                                            const base::FilePath& file_path,
344                                            bool is_directory) {
345   DCHECK(info.root_url.is_valid());
346   CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id);
347   DCHECK(dispatcher);
348   dispatcher->DidResolveURL(info, file_path, is_directory);
349   dispatchers_.Remove(request_id);
350 }
351
352 void FileSystemDispatcher::OnDidSucceed(int request_id) {
353   CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id);
354   DCHECK(dispatcher);
355   dispatcher->DidSucceed();
356   dispatchers_.Remove(request_id);
357 }
358
359 void FileSystemDispatcher::OnDidReadMetadata(
360     int request_id, const base::File::Info& file_info) {
361   CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id);
362   DCHECK(dispatcher);
363   dispatcher->DidReadMetadata(file_info);
364   dispatchers_.Remove(request_id);
365 }
366
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);
371   DCHECK(dispatcher);
372   dispatcher->DidCreateSnapshotFile(file_info, platform_path, request_id);
373   dispatchers_.Remove(request_id);
374 }
375
376 void FileSystemDispatcher::OnDidReadDirectory(
377     int request_id,
378     const std::vector<storage::DirectoryEntry>& entries,
379     bool has_more) {
380   CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id);
381   DCHECK(dispatcher);
382   dispatcher->DidReadDirectory(entries, has_more);
383   if (!has_more)
384     dispatchers_.Remove(request_id);
385 }
386
387 void FileSystemDispatcher::OnDidFail(
388     int request_id, base::File::Error error_code) {
389   CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id);
390   DCHECK(dispatcher);
391   dispatcher->DidFail(error_code);
392   dispatchers_.Remove(request_id);
393 }
394
395 void FileSystemDispatcher::OnDidWrite(
396     int request_id, int64 bytes, bool complete) {
397   CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id);
398   DCHECK(dispatcher);
399   dispatcher->DidWrite(bytes, complete);
400   if (complete)
401     dispatchers_.Remove(request_id);
402 }
403
404 }  // namespace content