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 
     14 namespace content {
     15 
     16 class FileSystemDispatcher::CallbackDispatcher {
     17  public:
     18   typedef CallbackDispatcher self;
     19   typedef FileSystemDispatcher::StatusCallback StatusCallback;
     20   typedef FileSystemDispatcher::MetadataCallback MetadataCallback;
     21   typedef FileSystemDispatcher::ReadDirectoryCallback ReadDirectoryCallback;
     22   typedef FileSystemDispatcher::OpenFileSystemCallback OpenFileSystemCallback;
     23   typedef FileSystemDispatcher::WriteCallback WriteCallback;
     24   typedef FileSystemDispatcher::OpenFileCallback OpenFileCallback;
     25 
     26   static CallbackDispatcher* Create(const StatusCallback& callback) {
     27     CallbackDispatcher* dispatcher = new CallbackDispatcher;
     28     dispatcher->status_callback_ = callback;
     29     dispatcher->error_callback_ = callback;
     30     return dispatcher;
     31   }
     32   static CallbackDispatcher* Create(const MetadataCallback& callback,
     33                                     const StatusCallback& error_callback) {
     34     CallbackDispatcher* dispatcher = new CallbackDispatcher;
     35     dispatcher->metadata_callback_ = callback;
     36     dispatcher->error_callback_ = error_callback;
     37     return dispatcher;
     38   }
     39   static CallbackDispatcher* Create(const CreateSnapshotFileCallback& callback,
     40                                     const StatusCallback& error_callback) {
     41     CallbackDispatcher* dispatcher = new CallbackDispatcher;
     42     dispatcher->snapshot_callback_ = callback;
     43     dispatcher->error_callback_ = error_callback;
     44     return dispatcher;
     45   }
     46   static CallbackDispatcher* Create(const ReadDirectoryCallback& callback,
     47                                     const StatusCallback& error_callback) {
     48     CallbackDispatcher* dispatcher = new CallbackDispatcher;
     49     dispatcher->directory_callback_ = callback;
     50     dispatcher->error_callback_ = error_callback;
     51     return dispatcher;
     52   }
     53   static CallbackDispatcher* Create(const OpenFileSystemCallback& callback,
     54                                     const StatusCallback& error_callback) {
     55     CallbackDispatcher* dispatcher = new CallbackDispatcher;
     56     dispatcher->filesystem_callback_ = callback;
     57     dispatcher->error_callback_ = error_callback;
     58     return dispatcher;
     59   }
     60   static CallbackDispatcher* Create(const WriteCallback& callback,
     61                                     const StatusCallback& error_callback) {
     62     CallbackDispatcher* dispatcher = new CallbackDispatcher;
     63     dispatcher->write_callback_ = callback;
     64     dispatcher->error_callback_ = error_callback;
     65     return dispatcher;
     66   }
     67   static CallbackDispatcher* Create(const OpenFileCallback& callback,
     68                                     const StatusCallback& error_callback) {
     69     CallbackDispatcher* dispatcher = new CallbackDispatcher;
     70     dispatcher->open_callback_ = callback;
     71     dispatcher->error_callback_ = error_callback;
     72     return dispatcher;
     73   }
     74 
     75   ~CallbackDispatcher() {}
     76 
     77   void DidSucceed() {
     78     status_callback_.Run(base::PLATFORM_FILE_OK);
     79   }
     80 
     81   void DidFail(base::PlatformFileError error_code) {
     82     error_callback_.Run(error_code);
     83   }
     84 
     85   void DidReadMetadata(
     86       const base::PlatformFileInfo& file_info) {
     87     metadata_callback_.Run(file_info);
     88   }
     89 
     90   void DidCreateSnapshotFile(
     91       const base::PlatformFileInfo& file_info,
     92       const base::FilePath& platform_path,
     93       int request_id) {
     94     snapshot_callback_.Run(file_info, platform_path, request_id);
     95   }
     96 
     97   void DidReadDirectory(
     98       const std::vector<fileapi::DirectoryEntry>& entries,
     99       bool has_more) {
    100     directory_callback_.Run(entries, has_more);
    101   }
    102 
    103   void DidOpenFileSystem(const std::string& name,
    104                          const GURL& root) {
    105     filesystem_callback_.Run(name, root);
    106   }
    107 
    108   void DidWrite(int64 bytes, bool complete) {
    109     write_callback_.Run(bytes, complete);
    110   }
    111 
    112   void DidOpenFile(base::PlatformFile file,
    113                    int file_open_id,
    114                    quota::QuotaLimitType quota_policy) {
    115     open_callback_.Run(file, file_open_id, quota_policy);
    116   }
    117 
    118  private:
    119   CallbackDispatcher() {}
    120 
    121   StatusCallback status_callback_;
    122   MetadataCallback metadata_callback_;
    123   CreateSnapshotFileCallback snapshot_callback_;
    124   ReadDirectoryCallback directory_callback_;
    125   OpenFileSystemCallback filesystem_callback_;
    126   WriteCallback write_callback_;
    127   OpenFileCallback open_callback_;
    128 
    129   StatusCallback error_callback_;
    130 
    131   DISALLOW_COPY_AND_ASSIGN(CallbackDispatcher);
    132 };
    133 
    134 FileSystemDispatcher::FileSystemDispatcher() {
    135 }
    136 
    137 FileSystemDispatcher::~FileSystemDispatcher() {
    138   // Make sure we fire all the remaining callbacks.
    139   for (IDMap<CallbackDispatcher, IDMapOwnPointer>::iterator
    140            iter(&dispatchers_); !iter.IsAtEnd(); iter.Advance()) {
    141     int request_id = iter.GetCurrentKey();
    142     CallbackDispatcher* dispatcher = iter.GetCurrentValue();
    143     DCHECK(dispatcher);
    144     dispatcher->DidFail(base::PLATFORM_FILE_ERROR_ABORT);
    145     dispatchers_.Remove(request_id);
    146   }
    147 }
    148 
    149 bool FileSystemDispatcher::OnMessageReceived(const IPC::Message& msg) {
    150   bool handled = true;
    151   IPC_BEGIN_MESSAGE_MAP(FileSystemDispatcher, msg)
    152     IPC_MESSAGE_HANDLER(FileSystemMsg_DidOpenFileSystem, OnDidOpenFileSystem)
    153     IPC_MESSAGE_HANDLER(FileSystemMsg_DidSucceed, OnDidSucceed)
    154     IPC_MESSAGE_HANDLER(FileSystemMsg_DidReadDirectory, OnDidReadDirectory)
    155     IPC_MESSAGE_HANDLER(FileSystemMsg_DidReadMetadata, OnDidReadMetadata)
    156     IPC_MESSAGE_HANDLER(FileSystemMsg_DidCreateSnapshotFile,
    157                         OnDidCreateSnapshotFile)
    158     IPC_MESSAGE_HANDLER(FileSystemMsg_DidFail, OnDidFail)
    159     IPC_MESSAGE_HANDLER(FileSystemMsg_DidWrite, OnDidWrite)
    160     IPC_MESSAGE_HANDLER(FileSystemMsg_DidOpenFile, OnDidOpenFile)
    161     IPC_MESSAGE_UNHANDLED(handled = false)
    162   IPC_END_MESSAGE_MAP()
    163   return handled;
    164 }
    165 
    166 void FileSystemDispatcher::OpenFileSystem(
    167     const GURL& origin_url, fileapi::FileSystemType type,
    168     long long size, bool create,
    169     const OpenFileSystemCallback& success_callback,
    170     const StatusCallback& error_callback) {
    171   int request_id = dispatchers_.Add(
    172       CallbackDispatcher::Create(success_callback, error_callback));
    173   ChildThread::current()->Send(new FileSystemHostMsg_Open(
    174           request_id, origin_url, type, size, create));
    175 }
    176 
    177 void FileSystemDispatcher::DeleteFileSystem(
    178     const GURL& origin_url,
    179     fileapi::FileSystemType type,
    180     const StatusCallback& callback) {
    181   int request_id = dispatchers_.Add(CallbackDispatcher::Create(callback));
    182   ChildThread::current()->Send(new FileSystemHostMsg_DeleteFileSystem(
    183           request_id, origin_url, type));
    184 }
    185 
    186 void FileSystemDispatcher::Move(
    187     const GURL& src_path,
    188     const GURL& dest_path,
    189     const StatusCallback& callback) {
    190   int request_id = dispatchers_.Add(CallbackDispatcher::Create(callback));
    191   ChildThread::current()->Send(new FileSystemHostMsg_Move(
    192           request_id, src_path, dest_path));
    193 }
    194 
    195 void FileSystemDispatcher::Copy(
    196     const GURL& src_path,
    197     const GURL& dest_path,
    198     const StatusCallback& callback) {
    199   int request_id = dispatchers_.Add(CallbackDispatcher::Create(callback));
    200   ChildThread::current()->Send(new FileSystemHostMsg_Copy(
    201       request_id, src_path, dest_path));
    202 }
    203 
    204 void FileSystemDispatcher::Remove(
    205     const GURL& path,
    206     bool recursive,
    207     const StatusCallback& callback) {
    208   int request_id = dispatchers_.Add(CallbackDispatcher::Create(callback));
    209   ChildThread::current()->Send(
    210       new FileSystemMsg_Remove(request_id, path, recursive));
    211 }
    212 
    213 void FileSystemDispatcher::ReadMetadata(
    214     const GURL& path,
    215     const MetadataCallback& success_callback,
    216     const StatusCallback& error_callback) {
    217   int request_id = dispatchers_.Add(
    218       CallbackDispatcher::Create(success_callback, error_callback));
    219   ChildThread::current()->Send(
    220       new FileSystemHostMsg_ReadMetadata(request_id, path));
    221 }
    222 
    223 void FileSystemDispatcher::CreateFile(
    224     const GURL& path,
    225     bool exclusive,
    226     const StatusCallback& callback) {
    227   int request_id = dispatchers_.Add(CallbackDispatcher::Create(callback));
    228   ChildThread::current()->Send(new FileSystemHostMsg_Create(
    229       request_id, path, exclusive,
    230       false /* is_directory */, false /* recursive */));
    231 }
    232 
    233 void FileSystemDispatcher::CreateDirectory(
    234     const GURL& path,
    235     bool exclusive,
    236     bool recursive,
    237     const StatusCallback& callback) {
    238   int request_id = dispatchers_.Add(CallbackDispatcher::Create(callback));
    239   ChildThread::current()->Send(new FileSystemHostMsg_Create(
    240       request_id, path, exclusive, true /* is_directory */, recursive));
    241 }
    242 
    243 void FileSystemDispatcher::Exists(
    244     const GURL& path,
    245     bool is_directory,
    246     const StatusCallback& callback) {
    247   int request_id = dispatchers_.Add(CallbackDispatcher::Create(callback));
    248   ChildThread::current()->Send(
    249       new FileSystemHostMsg_Exists(request_id, path, is_directory));
    250 }
    251 
    252 void FileSystemDispatcher::ReadDirectory(
    253     const GURL& path,
    254     const ReadDirectoryCallback& success_callback,
    255     const StatusCallback& error_callback) {
    256   int request_id = dispatchers_.Add(
    257       CallbackDispatcher::Create(success_callback, error_callback));
    258   ChildThread::current()->Send(
    259       new FileSystemHostMsg_ReadDirectory(request_id, path));
    260 }
    261 
    262 void FileSystemDispatcher::Truncate(
    263     const GURL& path,
    264     int64 offset,
    265     int* request_id_out,
    266     const StatusCallback& callback) {
    267   int request_id = dispatchers_.Add(CallbackDispatcher::Create(callback));
    268   ChildThread::current()->Send(
    269       new FileSystemHostMsg_Truncate(request_id, path, offset));
    270 
    271   if (request_id_out)
    272     *request_id_out = request_id;
    273 }
    274 
    275 void FileSystemDispatcher::Write(
    276     const GURL& path,
    277     const GURL& blob_url,
    278     int64 offset,
    279     int* request_id_out,
    280     const WriteCallback& success_callback,
    281     const StatusCallback& error_callback) {
    282   int request_id = dispatchers_.Add(
    283       CallbackDispatcher::Create(success_callback, error_callback));
    284   ChildThread::current()->Send(
    285       new FileSystemHostMsg_Write(request_id, path, blob_url, offset));
    286 
    287   if (request_id_out)
    288     *request_id_out = request_id;
    289 }
    290 
    291 void FileSystemDispatcher::Cancel(
    292     int request_id_to_cancel,
    293     const StatusCallback& callback) {
    294   int request_id = dispatchers_.Add(CallbackDispatcher::Create(callback));
    295   ChildThread::current()->Send(new FileSystemHostMsg_CancelWrite(
    296       request_id, request_id_to_cancel));
    297 }
    298 
    299 void FileSystemDispatcher::TouchFile(
    300     const GURL& path,
    301     const base::Time& last_access_time,
    302     const base::Time& last_modified_time,
    303     const StatusCallback& callback) {
    304   int request_id = dispatchers_.Add(CallbackDispatcher::Create(callback));
    305   ChildThread::current()->Send(
    306       new FileSystemHostMsg_TouchFile(
    307           request_id, path, last_access_time, last_modified_time));
    308 }
    309 
    310 void FileSystemDispatcher::OpenFile(
    311     const GURL& file_path,
    312     int file_flags,
    313     const OpenFileCallback& success_callback,
    314     const StatusCallback& error_callback) {
    315   int request_id = dispatchers_.Add(
    316       CallbackDispatcher::Create(success_callback, error_callback));
    317   ChildThread::current()->Send(
    318       new FileSystemHostMsg_OpenFile(
    319           request_id, file_path, file_flags));
    320 }
    321 
    322 void FileSystemDispatcher::NotifyCloseFile(int file_open_id) {
    323   ChildThread::current()->Send(
    324       new FileSystemHostMsg_NotifyCloseFile(file_open_id));
    325 }
    326 
    327 void FileSystemDispatcher::CreateSnapshotFile(
    328     const GURL& file_path,
    329     const CreateSnapshotFileCallback& success_callback,
    330     const StatusCallback& error_callback) {
    331   int request_id = dispatchers_.Add(
    332       CallbackDispatcher::Create(success_callback, error_callback));
    333   ChildThread::current()->Send(
    334       new FileSystemHostMsg_CreateSnapshotFile(
    335           request_id, file_path));
    336 }
    337 
    338 void FileSystemDispatcher::OnDidOpenFileSystem(int request_id,
    339                                                const std::string& name,
    340                                                const GURL& root) {
    341   DCHECK(root.is_valid());
    342   CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id);
    343   DCHECK(dispatcher);
    344   dispatcher->DidOpenFileSystem(name, root);
    345   dispatchers_.Remove(request_id);
    346 }
    347 
    348 void FileSystemDispatcher::OnDidSucceed(int request_id) {
    349   CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id);
    350   DCHECK(dispatcher);
    351   dispatcher->DidSucceed();
    352   dispatchers_.Remove(request_id);
    353 }
    354 
    355 void FileSystemDispatcher::OnDidReadMetadata(
    356     int request_id, const base::PlatformFileInfo& file_info) {
    357   CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id);
    358   DCHECK(dispatcher);
    359   dispatcher->DidReadMetadata(file_info);
    360   dispatchers_.Remove(request_id);
    361 }
    362 
    363 void FileSystemDispatcher::OnDidCreateSnapshotFile(
    364     int request_id, const base::PlatformFileInfo& file_info,
    365     const base::FilePath& platform_path) {
    366   CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id);
    367   DCHECK(dispatcher);
    368   dispatcher->DidCreateSnapshotFile(file_info, platform_path, request_id);
    369   dispatchers_.Remove(request_id);
    370 }
    371 
    372 void FileSystemDispatcher::OnDidReadDirectory(
    373     int request_id,
    374     const std::vector<fileapi::DirectoryEntry>& entries,
    375     bool has_more) {
    376   CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id);
    377   DCHECK(dispatcher);
    378   dispatcher->DidReadDirectory(entries, has_more);
    379   dispatchers_.Remove(request_id);
    380 }
    381 
    382 void FileSystemDispatcher::OnDidFail(
    383     int request_id, base::PlatformFileError error_code) {
    384   CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id);
    385   DCHECK(dispatcher);
    386   dispatcher->DidFail(error_code);
    387   dispatchers_.Remove(request_id);
    388 }
    389 
    390 void FileSystemDispatcher::OnDidWrite(
    391     int request_id, int64 bytes, bool complete) {
    392   CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id);
    393   DCHECK(dispatcher);
    394   dispatcher->DidWrite(bytes, complete);
    395   if (complete)
    396     dispatchers_.Remove(request_id);
    397 }
    398 
    399 void FileSystemDispatcher::OnDidOpenFile(
    400     int request_id,
    401     IPC::PlatformFileForTransit file,
    402     int file_open_id,
    403     quota::QuotaLimitType quota_policy) {
    404   CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id);
    405   DCHECK(dispatcher);
    406   dispatcher->DidOpenFile(IPC::PlatformFileForTransitToPlatformFile(file),
    407                           file_open_id,
    408                           quota_policy);
    409   dispatchers_.Remove(request_id);
    410 }
    411 
    412 }  // namespace content
    413