• 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   }
Create(const OpenFileCallback & callback,const StatusCallback & error_callback)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 
~CallbackDispatcher()84   ~CallbackDispatcher() {}
85 
DidSucceed()86   void DidSucceed() {
87     status_callback_.Run(base::PLATFORM_FILE_OK);
88   }
89 
DidFail(base::PlatformFileError error_code)90   void DidFail(base::PlatformFileError error_code) {
91     error_callback_.Run(error_code);
92   }
93 
DidReadMetadata(const base::PlatformFileInfo & file_info)94   void DidReadMetadata(
95       const base::PlatformFileInfo& file_info) {
96     metadata_callback_.Run(file_info);
97   }
98 
DidCreateSnapshotFile(const base::PlatformFileInfo & file_info,const base::FilePath & platform_path,int request_id)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 
DidReadDirectory(const std::vector<fileapi::DirectoryEntry> & entries,bool has_more)106   void DidReadDirectory(
107       const std::vector<fileapi::DirectoryEntry>& entries,
108       bool has_more) {
109     directory_callback_.Run(entries, has_more);
110   }
111 
DidOpenFileSystem(const std::string & name,const GURL & root)112   void DidOpenFileSystem(const std::string& name,
113                          const GURL& root) {
114     filesystem_callback_.Run(name, root);
115   }
116 
DidResolveURL(const fileapi::FileSystemInfo & info,const base::FilePath & file_path,bool is_directory)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 
DidWrite(int64 bytes,bool complete)123   void DidWrite(int64 bytes, bool complete) {
124     write_callback_.Run(bytes, complete);
125   }
126 
DidOpenFile(base::PlatformFile file,int file_open_id,quota::QuotaLimitType quota_policy)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:
CallbackDispatcher()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 
FileSystemDispatcher()150 FileSystemDispatcher::FileSystemDispatcher() {
151 }
152 
~FileSystemDispatcher()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 
OnMessageReceived(const IPC::Message & msg)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 
OpenFileSystem(const GURL & origin_url,fileapi::FileSystemType type,const OpenFileSystemCallback & success_callback,const StatusCallback & error_callback)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 
ResolveURL(const GURL & filesystem_url,const ResolveURLCallback & success_callback,const StatusCallback & error_callback)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 
DeleteFileSystem(const GURL & origin_url,fileapi::FileSystemType type,const StatusCallback & callback)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 
Move(const GURL & src_path,const GURL & dest_path,const StatusCallback & callback)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 
Copy(const GURL & src_path,const GURL & dest_path,const StatusCallback & callback)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 
Remove(const GURL & path,bool recursive,const StatusCallback & callback)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 
ReadMetadata(const GURL & path,const MetadataCallback & success_callback,const StatusCallback & error_callback)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 
CreateFile(const GURL & path,bool exclusive,const StatusCallback & callback)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 
CreateDirectory(const GURL & path,bool exclusive,bool recursive,const StatusCallback & callback)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 
Exists(const GURL & path,bool is_directory,const StatusCallback & callback)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 
ReadDirectory(const GURL & path,const ReadDirectoryCallback & success_callback,const StatusCallback & error_callback)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 
Truncate(const GURL & path,int64 offset,int * request_id_out,const StatusCallback & callback)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 
WriteDeprecated(const GURL & path,const GURL & blob_url,int64 offset,int * request_id_out,const WriteCallback & success_callback,const StatusCallback & error_callback)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 
Write(const GURL & path,const std::string & blob_id,int64 offset,int * request_id_out,const WriteCallback & success_callback,const StatusCallback & error_callback)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 
Cancel(int request_id_to_cancel,const StatusCallback & callback)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 
TouchFile(const GURL & path,const base::Time & last_access_time,const base::Time & last_modified_time,const StatusCallback & callback)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 
CreateSnapshotFile(const GURL & file_path,const CreateSnapshotFileCallback & success_callback,const StatusCallback & error_callback)354 void FileSystemDispatcher::CreateSnapshotFile(
355     const GURL& file_path,
356     const CreateSnapshotFileCallback& success_callback,
357     const StatusCallback& error_callback) {
358   int request_id = dispatchers_.Add(
359       CallbackDispatcher::Create(success_callback, error_callback));
360   ChildThread::current()->Send(
361       new FileSystemHostMsg_CreateSnapshotFile(
362           request_id, file_path));
363 }
364 
OnDidOpenFileSystem(int request_id,const std::string & name,const GURL & root)365 void FileSystemDispatcher::OnDidOpenFileSystem(int request_id,
366                                                const std::string& name,
367                                                const GURL& root) {
368   DCHECK(root.is_valid());
369   CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id);
370   DCHECK(dispatcher);
371   dispatcher->DidOpenFileSystem(name, root);
372   dispatchers_.Remove(request_id);
373 }
374 
OnDidResolveURL(int request_id,const fileapi::FileSystemInfo & info,const base::FilePath & file_path,bool is_directory)375 void FileSystemDispatcher::OnDidResolveURL(int request_id,
376                                            const fileapi::FileSystemInfo& info,
377                                            const base::FilePath& file_path,
378                                            bool is_directory) {
379   DCHECK(info.root_url.is_valid());
380   CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id);
381   DCHECK(dispatcher);
382   dispatcher->DidResolveURL(info, file_path, is_directory);
383   dispatchers_.Remove(request_id);
384 }
385 
OnDidSucceed(int request_id)386 void FileSystemDispatcher::OnDidSucceed(int request_id) {
387   CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id);
388   DCHECK(dispatcher);
389   dispatcher->DidSucceed();
390   dispatchers_.Remove(request_id);
391 }
392 
OnDidReadMetadata(int request_id,const base::PlatformFileInfo & file_info)393 void FileSystemDispatcher::OnDidReadMetadata(
394     int request_id, const base::PlatformFileInfo& file_info) {
395   CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id);
396   DCHECK(dispatcher);
397   dispatcher->DidReadMetadata(file_info);
398   dispatchers_.Remove(request_id);
399 }
400 
OnDidCreateSnapshotFile(int request_id,const base::PlatformFileInfo & file_info,const base::FilePath & platform_path)401 void FileSystemDispatcher::OnDidCreateSnapshotFile(
402     int request_id, const base::PlatformFileInfo& file_info,
403     const base::FilePath& platform_path) {
404   CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id);
405   DCHECK(dispatcher);
406   dispatcher->DidCreateSnapshotFile(file_info, platform_path, request_id);
407   dispatchers_.Remove(request_id);
408 }
409 
OnDidReadDirectory(int request_id,const std::vector<fileapi::DirectoryEntry> & entries,bool has_more)410 void FileSystemDispatcher::OnDidReadDirectory(
411     int request_id,
412     const std::vector<fileapi::DirectoryEntry>& entries,
413     bool has_more) {
414   CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id);
415   DCHECK(dispatcher);
416   dispatcher->DidReadDirectory(entries, has_more);
417   dispatchers_.Remove(request_id);
418 }
419 
OnDidFail(int request_id,base::PlatformFileError error_code)420 void FileSystemDispatcher::OnDidFail(
421     int request_id, base::PlatformFileError error_code) {
422   CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id);
423   DCHECK(dispatcher);
424   dispatcher->DidFail(error_code);
425   dispatchers_.Remove(request_id);
426 }
427 
OnDidWrite(int request_id,int64 bytes,bool complete)428 void FileSystemDispatcher::OnDidWrite(
429     int request_id, int64 bytes, bool complete) {
430   CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id);
431   DCHECK(dispatcher);
432   dispatcher->DidWrite(bytes, complete);
433   if (complete)
434     dispatchers_.Remove(request_id);
435 }
436 
OnDidOpenFile(int request_id,IPC::PlatformFileForTransit file,int file_open_id,quota::QuotaLimitType quota_policy)437 void FileSystemDispatcher::OnDidOpenFile(
438     int request_id,
439     IPC::PlatformFileForTransit file,
440     int file_open_id,
441     quota::QuotaLimitType quota_policy) {
442   CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id);
443   DCHECK(dispatcher);
444   dispatcher->DidOpenFile(IPC::PlatformFileForTransitToPlatformFile(file),
445                           file_open_id,
446                           quota_policy);
447   dispatchers_.Remove(request_id);
448 }
449 
450 }  // namespace content
451