• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
Create(const StatusCallback & callback)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   }
Create(const MetadataCallback & callback,const StatusCallback & error_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;
39     return dispatcher;
40   }
Create(const CreateSnapshotFileCallback & callback,const StatusCallback & 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;
46     return dispatcher;
47   }
Create(const ReadDirectoryCallback & callback,const StatusCallback & 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;
53     return dispatcher;
54   }
Create(const OpenFileSystemCallback & callback,const StatusCallback & 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;
60     return dispatcher;
61   }
Create(const ResolveURLCallback & callback,const StatusCallback & 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;
67     return dispatcher;
68   }
Create(const WriteCallback & callback,const StatusCallback & 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;
74     return dispatcher;
75   }
76 
~CallbackDispatcher()77   ~CallbackDispatcher() {}
78 
DidSucceed()79   void DidSucceed() {
80     status_callback_.Run(base::File::FILE_OK);
81   }
82 
DidFail(base::File::Error error_code)83   void DidFail(base::File::Error error_code) {
84     error_callback_.Run(error_code);
85   }
86 
DidReadMetadata(const base::File::Info & file_info)87   void DidReadMetadata(
88       const base::File::Info& file_info) {
89     metadata_callback_.Run(file_info);
90   }
91 
DidCreateSnapshotFile(const base::File::Info & file_info,const base::FilePath & platform_path,int request_id)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 
DidReadDirectory(const std::vector<fileapi::DirectoryEntry> & entries,bool has_more)99   void DidReadDirectory(
100       const std::vector<fileapi::DirectoryEntry>& entries,
101       bool has_more) {
102     directory_callback_.Run(entries, has_more);
103   }
104 
DidOpenFileSystem(const std::string & name,const GURL & root)105   void DidOpenFileSystem(const std::string& name,
106                          const GURL& root) {
107     filesystem_callback_.Run(name, root);
108   }
109 
DidResolveURL(const fileapi::FileSystemInfo & info,const base::FilePath & file_path,bool is_directory)110   void DidResolveURL(const fileapi::FileSystemInfo& info,
111                      const base::FilePath& file_path,
112                      bool is_directory) {
113     resolve_callback_.Run(info, file_path, is_directory);
114   }
115 
DidWrite(int64 bytes,bool complete)116   void DidWrite(int64 bytes, bool complete) {
117     write_callback_.Run(bytes, complete);
118   }
119 
DidOpenFile(base::PlatformFile file,int file_open_id,quota::QuotaLimitType quota_policy)120   void DidOpenFile(base::PlatformFile file,
121                    int file_open_id,
122                    quota::QuotaLimitType quota_policy) {
123     open_callback_.Run(file, file_open_id, quota_policy);
124   }
125 
126  private:
CallbackDispatcher()127   CallbackDispatcher() {}
128 
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_;
137 
138   StatusCallback error_callback_;
139 
140   DISALLOW_COPY_AND_ASSIGN(CallbackDispatcher);
141 };
142 
FileSystemDispatcher()143 FileSystemDispatcher::FileSystemDispatcher() {
144 }
145 
~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();
152     DCHECK(dispatcher);
153     dispatcher->DidFail(base::File::FILE_ERROR_ABORT);
154     dispatchers_.Remove(request_id);
155   }
156 }
157 
OnMessageReceived(const IPC::Message & msg)158 bool FileSystemDispatcher::OnMessageReceived(const IPC::Message& msg) {
159   bool handled = true;
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()
173   return handled;
174 }
175 
OpenFileSystem(const GURL & origin_url,fileapi::FileSystemType type,const OpenFileSystemCallback & success_callback,const StatusCallback & error_callback)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));
185 }
186 
ResolveURL(const GURL & filesystem_url,const ResolveURLCallback & success_callback,const StatusCallback & error_callback)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));
195 }
196 
DeleteFileSystem(const GURL & origin_url,fileapi::FileSystemType type,const StatusCallback & callback)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));
204 }
205 
Move(const GURL & src_path,const GURL & dest_path,const StatusCallback & callback)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));
213 }
214 
Copy(const GURL & src_path,const GURL & dest_path,const StatusCallback & callback)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));
222 }
223 
Remove(const GURL & path,bool recursive,const StatusCallback & callback)224 void FileSystemDispatcher::Remove(
225     const GURL& path,
226     bool recursive,
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));
231 }
232 
ReadMetadata(const GURL & path,const MetadataCallback & success_callback,const StatusCallback & error_callback)233 void FileSystemDispatcher::ReadMetadata(
234     const GURL& path,
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));
241 }
242 
CreateFile(const GURL & path,bool exclusive,const StatusCallback & callback)243 void FileSystemDispatcher::CreateFile(
244     const GURL& path,
245     bool exclusive,
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 */));
251 }
252 
CreateDirectory(const GURL & path,bool exclusive,bool recursive,const StatusCallback & callback)253 void FileSystemDispatcher::CreateDirectory(
254     const GURL& path,
255     bool exclusive,
256     bool recursive,
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));
261 }
262 
Exists(const GURL & path,bool is_directory,const StatusCallback & callback)263 void FileSystemDispatcher::Exists(
264     const GURL& path,
265     bool is_directory,
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));
270 }
271 
ReadDirectory(const GURL & path,const ReadDirectoryCallback & success_callback,const StatusCallback & error_callback)272 void FileSystemDispatcher::ReadDirectory(
273     const GURL& path,
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));
280 }
281 
Truncate(const GURL & path,int64 offset,int * request_id_out,const StatusCallback & callback)282 void FileSystemDispatcher::Truncate(
283     const GURL& path,
284     int64 offset,
285     int* request_id_out,
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));
290 
291   if (request_id_out)
292     *request_id_out = request_id;
293 }
294 
Write(const GURL & path,const std::string & blob_id,int64 offset,int * request_id_out,const WriteCallback & success_callback,const StatusCallback & error_callback)295 void FileSystemDispatcher::Write(
296     const GURL& path,
297     const std::string& blob_id,
298     int64 offset,
299     int* request_id_out,
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));
306 
307   if (request_id_out)
308     *request_id_out = request_id;
309 }
310 
Cancel(int request_id_to_cancel,const StatusCallback & callback)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));
317 }
318 
TouchFile(const GURL & path,const base::Time & last_access_time,const base::Time & last_modified_time,const StatusCallback & callback)319 void FileSystemDispatcher::TouchFile(
320     const GURL& path,
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));
328 }
329 
CreateSnapshotFile(const GURL & file_path,const CreateSnapshotFileCallback & success_callback,const StatusCallback & error_callback)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));
339 }
340 
OnDidOpenFileSystem(int request_id,const std::string & name,const GURL & root)341 void FileSystemDispatcher::OnDidOpenFileSystem(int request_id,
342                                                const std::string& name,
343                                                const GURL& root) {
344   DCHECK(root.is_valid());
345   CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id);
346   DCHECK(dispatcher);
347   dispatcher->DidOpenFileSystem(name, root);
348   dispatchers_.Remove(request_id);
349 }
350 
OnDidResolveURL(int request_id,const fileapi::FileSystemInfo & info,const base::FilePath & file_path,bool is_directory)351 void FileSystemDispatcher::OnDidResolveURL(int request_id,
352                                            const fileapi::FileSystemInfo& info,
353                                            const base::FilePath& file_path,
354                                            bool is_directory) {
355   DCHECK(info.root_url.is_valid());
356   CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id);
357   DCHECK(dispatcher);
358   dispatcher->DidResolveURL(info, file_path, is_directory);
359   dispatchers_.Remove(request_id);
360 }
361 
OnDidSucceed(int request_id)362 void FileSystemDispatcher::OnDidSucceed(int request_id) {
363   CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id);
364   DCHECK(dispatcher);
365   dispatcher->DidSucceed();
366   dispatchers_.Remove(request_id);
367 }
368 
OnDidReadMetadata(int request_id,const base::File::Info & file_info)369 void FileSystemDispatcher::OnDidReadMetadata(
370     int request_id, const base::File::Info& file_info) {
371   CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id);
372   DCHECK(dispatcher);
373   dispatcher->DidReadMetadata(file_info);
374   dispatchers_.Remove(request_id);
375 }
376 
OnDidCreateSnapshotFile(int request_id,const base::File::Info & file_info,const base::FilePath & platform_path)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);
381   DCHECK(dispatcher);
382   dispatcher->DidCreateSnapshotFile(file_info, platform_path, request_id);
383   dispatchers_.Remove(request_id);
384 }
385 
OnDidReadDirectory(int request_id,const std::vector<fileapi::DirectoryEntry> & entries,bool has_more)386 void FileSystemDispatcher::OnDidReadDirectory(
387     int request_id,
388     const std::vector<fileapi::DirectoryEntry>& entries,
389     bool has_more) {
390   CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id);
391   DCHECK(dispatcher);
392   dispatcher->DidReadDirectory(entries, has_more);
393   if (!has_more)
394     dispatchers_.Remove(request_id);
395 }
396 
OnDidFail(int request_id,base::File::Error error_code)397 void FileSystemDispatcher::OnDidFail(
398     int request_id, base::File::Error error_code) {
399   CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id);
400   DCHECK(dispatcher);
401   dispatcher->DidFail(error_code);
402   dispatchers_.Remove(request_id);
403 }
404 
OnDidWrite(int request_id,int64 bytes,bool complete)405 void FileSystemDispatcher::OnDidWrite(
406     int request_id, int64 bytes, bool complete) {
407   CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id);
408   DCHECK(dispatcher);
409   dispatcher->DidWrite(bytes, complete);
410   if (complete)
411     dispatchers_.Remove(request_id);
412 }
413 
OnDidOpenFile(int request_id,IPC::PlatformFileForTransit file,int file_open_id,quota::QuotaLimitType quota_policy)414 void FileSystemDispatcher::OnDidOpenFile(
415     int request_id,
416     IPC::PlatformFileForTransit file,
417     int file_open_id,
418     quota::QuotaLimitType quota_policy) {
419   CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id);
420   DCHECK(dispatcher);
421   dispatcher->DidOpenFile(IPC::PlatformFileForTransitToPlatformFile(file),
422                           file_open_id,
423                           quota_policy);
424   dispatchers_.Remove(request_id);
425 }
426 
427 }  // namespace content
428