Home | History | Annotate | Download | only in fileapi
      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 
     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(
    100       const std::vector<fileapi::DirectoryEntry>& entries,
    101       bool has_more) {
    102     directory_callback_.Run(entries, has_more);
    103   }
    104 
    105   void DidOpenFileSystem(const std::string& name,
    106                          const GURL& root) {
    107     filesystem_callback_.Run(name, root);
    108   }
    109 
    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 
    116   void DidWrite(int64 bytes, bool complete) {
    117     write_callback_.Run(bytes, complete);
    118   }
    119 
    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:
    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 
    143 FileSystemDispatcher::FileSystemDispatcher() {
    144 }
    145 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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