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   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 
     84   ~CallbackDispatcher() {}
     85 
     86   void DidSucceed() {
     87     status_callback_.Run(base::PLATFORM_FILE_OK);
     88   }
     89 
     90   void DidFail(base::PlatformFileError error_code) {
     91     error_callback_.Run(error_code);
     92   }
     93 
     94   void DidReadMetadata(
     95       const base::PlatformFileInfo& file_info) {
     96     metadata_callback_.Run(file_info);
     97   }
     98 
     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 
    106   void DidReadDirectory(
    107       const std::vector<fileapi::DirectoryEntry>& entries,
    108       bool has_more) {
    109     directory_callback_.Run(entries, has_more);
    110   }
    111 
    112   void DidOpenFileSystem(const std::string& name,
    113                          const GURL& root) {
    114     filesystem_callback_.Run(name, root);
    115   }
    116 
    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 
    123   void DidWrite(int64 bytes, bool complete) {
    124     write_callback_.Run(bytes, complete);
    125   }
    126 
    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:
    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 
    150 FileSystemDispatcher::FileSystemDispatcher() {
    151 }
    152 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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