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/files/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 "storage/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(const std::vector<storage::DirectoryEntry>& entries,
    100                         bool has_more) {
    101     directory_callback_.Run(entries, has_more);
    102   }
    103 
    104   void DidOpenFileSystem(const std::string& name,
    105                          const GURL& root) {
    106     filesystem_callback_.Run(name, root);
    107   }
    108 
    109   void DidResolveURL(const storage::FileSystemInfo& info,
    110                      const base::FilePath& file_path,
    111                      bool is_directory) {
    112     resolve_callback_.Run(info, file_path, is_directory);
    113   }
    114 
    115   void DidWrite(int64 bytes, bool complete) {
    116     write_callback_.Run(bytes, complete);
    117   }
    118 
    119  private:
    120   CallbackDispatcher() {}
    121 
    122   StatusCallback status_callback_;
    123   MetadataCallback metadata_callback_;
    124   CreateSnapshotFileCallback snapshot_callback_;
    125   ReadDirectoryCallback directory_callback_;
    126   OpenFileSystemCallback filesystem_callback_;
    127   ResolveURLCallback resolve_callback_;
    128   WriteCallback write_callback_;
    129 
    130   StatusCallback error_callback_;
    131 
    132   DISALLOW_COPY_AND_ASSIGN(CallbackDispatcher);
    133 };
    134 
    135 FileSystemDispatcher::FileSystemDispatcher() {
    136 }
    137 
    138 FileSystemDispatcher::~FileSystemDispatcher() {
    139   // Make sure we fire all the remaining callbacks.
    140   for (IDMap<CallbackDispatcher, IDMapOwnPointer>::iterator
    141            iter(&dispatchers_); !iter.IsAtEnd(); iter.Advance()) {
    142     int request_id = iter.GetCurrentKey();
    143     CallbackDispatcher* dispatcher = iter.GetCurrentValue();
    144     DCHECK(dispatcher);
    145     dispatcher->DidFail(base::File::FILE_ERROR_ABORT);
    146     dispatchers_.Remove(request_id);
    147   }
    148 }
    149 
    150 bool FileSystemDispatcher::OnMessageReceived(const IPC::Message& msg) {
    151   bool handled = true;
    152   IPC_BEGIN_MESSAGE_MAP(FileSystemDispatcher, msg)
    153     IPC_MESSAGE_HANDLER(FileSystemMsg_DidOpenFileSystem, OnDidOpenFileSystem)
    154     IPC_MESSAGE_HANDLER(FileSystemMsg_DidResolveURL, OnDidResolveURL)
    155     IPC_MESSAGE_HANDLER(FileSystemMsg_DidSucceed, OnDidSucceed)
    156     IPC_MESSAGE_HANDLER(FileSystemMsg_DidReadDirectory, OnDidReadDirectory)
    157     IPC_MESSAGE_HANDLER(FileSystemMsg_DidReadMetadata, OnDidReadMetadata)
    158     IPC_MESSAGE_HANDLER(FileSystemMsg_DidCreateSnapshotFile,
    159                         OnDidCreateSnapshotFile)
    160     IPC_MESSAGE_HANDLER(FileSystemMsg_DidFail, OnDidFail)
    161     IPC_MESSAGE_HANDLER(FileSystemMsg_DidWrite, OnDidWrite)
    162     IPC_MESSAGE_UNHANDLED(handled = false)
    163   IPC_END_MESSAGE_MAP()
    164   return handled;
    165 }
    166 
    167 void FileSystemDispatcher::OpenFileSystem(
    168     const GURL& origin_url,
    169     storage::FileSystemType type,
    170     const OpenFileSystemCallback& success_callback,
    171     const StatusCallback& error_callback) {
    172   int request_id = dispatchers_.Add(
    173       CallbackDispatcher::Create(success_callback, error_callback));
    174   ChildThread::current()->Send(new FileSystemHostMsg_OpenFileSystem(
    175       request_id, origin_url, type));
    176 }
    177 
    178 void FileSystemDispatcher::ResolveURL(
    179     const GURL& filesystem_url,
    180     const ResolveURLCallback& success_callback,
    181     const StatusCallback& error_callback) {
    182   int request_id = dispatchers_.Add(
    183       CallbackDispatcher::Create(success_callback, error_callback));
    184   ChildThread::current()->Send(new FileSystemHostMsg_ResolveURL(
    185           request_id, filesystem_url));
    186 }
    187 
    188 void FileSystemDispatcher::DeleteFileSystem(const GURL& origin_url,
    189                                             storage::FileSystemType type,
    190                                             const StatusCallback& callback) {
    191   int request_id = dispatchers_.Add(CallbackDispatcher::Create(callback));
    192   ChildThread::current()->Send(new FileSystemHostMsg_DeleteFileSystem(
    193           request_id, origin_url, type));
    194 }
    195 
    196 void FileSystemDispatcher::Move(
    197     const GURL& src_path,
    198     const GURL& dest_path,
    199     const StatusCallback& callback) {
    200   int request_id = dispatchers_.Add(CallbackDispatcher::Create(callback));
    201   ChildThread::current()->Send(new FileSystemHostMsg_Move(
    202           request_id, src_path, dest_path));
    203 }
    204 
    205 void FileSystemDispatcher::Copy(
    206     const GURL& src_path,
    207     const GURL& dest_path,
    208     const StatusCallback& callback) {
    209   int request_id = dispatchers_.Add(CallbackDispatcher::Create(callback));
    210   ChildThread::current()->Send(new FileSystemHostMsg_Copy(
    211       request_id, src_path, dest_path));
    212 }
    213 
    214 void FileSystemDispatcher::Remove(
    215     const GURL& path,
    216     bool recursive,
    217     const StatusCallback& callback) {
    218   int request_id = dispatchers_.Add(CallbackDispatcher::Create(callback));
    219   ChildThread::current()->Send(
    220       new FileSystemHostMsg_Remove(request_id, path, recursive));
    221 }
    222 
    223 void FileSystemDispatcher::ReadMetadata(
    224     const GURL& path,
    225     const MetadataCallback& success_callback,
    226     const StatusCallback& error_callback) {
    227   int request_id = dispatchers_.Add(
    228       CallbackDispatcher::Create(success_callback, error_callback));
    229   ChildThread::current()->Send(
    230       new FileSystemHostMsg_ReadMetadata(request_id, path));
    231 }
    232 
    233 void FileSystemDispatcher::CreateFile(
    234     const GURL& path,
    235     bool exclusive,
    236     const StatusCallback& callback) {
    237   int request_id = dispatchers_.Add(CallbackDispatcher::Create(callback));
    238   ChildThread::current()->Send(new FileSystemHostMsg_Create(
    239       request_id, path, exclusive,
    240       false /* is_directory */, false /* recursive */));
    241 }
    242 
    243 void FileSystemDispatcher::CreateDirectory(
    244     const GURL& path,
    245     bool exclusive,
    246     bool recursive,
    247     const StatusCallback& callback) {
    248   int request_id = dispatchers_.Add(CallbackDispatcher::Create(callback));
    249   ChildThread::current()->Send(new FileSystemHostMsg_Create(
    250       request_id, path, exclusive, true /* is_directory */, recursive));
    251 }
    252 
    253 void FileSystemDispatcher::Exists(
    254     const GURL& path,
    255     bool is_directory,
    256     const StatusCallback& callback) {
    257   int request_id = dispatchers_.Add(CallbackDispatcher::Create(callback));
    258   ChildThread::current()->Send(
    259       new FileSystemHostMsg_Exists(request_id, path, is_directory));
    260 }
    261 
    262 void FileSystemDispatcher::ReadDirectory(
    263     const GURL& path,
    264     const ReadDirectoryCallback& success_callback,
    265     const StatusCallback& error_callback) {
    266   int request_id = dispatchers_.Add(
    267       CallbackDispatcher::Create(success_callback, error_callback));
    268   ChildThread::current()->Send(
    269       new FileSystemHostMsg_ReadDirectory(request_id, path));
    270 }
    271 
    272 void FileSystemDispatcher::Truncate(
    273     const GURL& path,
    274     int64 offset,
    275     int* request_id_out,
    276     const StatusCallback& callback) {
    277   int request_id = dispatchers_.Add(CallbackDispatcher::Create(callback));
    278   ChildThread::current()->Send(
    279       new FileSystemHostMsg_Truncate(request_id, path, offset));
    280 
    281   if (request_id_out)
    282     *request_id_out = request_id;
    283 }
    284 
    285 void FileSystemDispatcher::Write(
    286     const GURL& path,
    287     const std::string& blob_id,
    288     int64 offset,
    289     int* request_id_out,
    290     const WriteCallback& success_callback,
    291     const StatusCallback& error_callback) {
    292   int request_id = dispatchers_.Add(
    293       CallbackDispatcher::Create(success_callback, error_callback));
    294   ChildThread::current()->Send(
    295       new FileSystemHostMsg_Write(request_id, path, blob_id, offset));
    296 
    297   if (request_id_out)
    298     *request_id_out = request_id;
    299 }
    300 
    301 void FileSystemDispatcher::Cancel(
    302     int request_id_to_cancel,
    303     const StatusCallback& callback) {
    304   int request_id = dispatchers_.Add(CallbackDispatcher::Create(callback));
    305   ChildThread::current()->Send(new FileSystemHostMsg_CancelWrite(
    306       request_id, request_id_to_cancel));
    307 }
    308 
    309 void FileSystemDispatcher::TouchFile(
    310     const GURL& path,
    311     const base::Time& last_access_time,
    312     const base::Time& last_modified_time,
    313     const StatusCallback& callback) {
    314   int request_id = dispatchers_.Add(CallbackDispatcher::Create(callback));
    315   ChildThread::current()->Send(
    316       new FileSystemHostMsg_TouchFile(
    317           request_id, path, last_access_time, last_modified_time));
    318 }
    319 
    320 void FileSystemDispatcher::CreateSnapshotFile(
    321     const GURL& file_path,
    322     const CreateSnapshotFileCallback& success_callback,
    323     const StatusCallback& error_callback) {
    324   int request_id = dispatchers_.Add(
    325       CallbackDispatcher::Create(success_callback, error_callback));
    326   ChildThread::current()->Send(
    327       new FileSystemHostMsg_CreateSnapshotFile(
    328           request_id, file_path));
    329 }
    330 
    331 void FileSystemDispatcher::OnDidOpenFileSystem(int request_id,
    332                                                const std::string& name,
    333                                                const GURL& root) {
    334   DCHECK(root.is_valid());
    335   CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id);
    336   DCHECK(dispatcher);
    337   dispatcher->DidOpenFileSystem(name, root);
    338   dispatchers_.Remove(request_id);
    339 }
    340 
    341 void FileSystemDispatcher::OnDidResolveURL(int request_id,
    342                                            const storage::FileSystemInfo& info,
    343                                            const base::FilePath& file_path,
    344                                            bool is_directory) {
    345   DCHECK(info.root_url.is_valid());
    346   CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id);
    347   DCHECK(dispatcher);
    348   dispatcher->DidResolveURL(info, file_path, is_directory);
    349   dispatchers_.Remove(request_id);
    350 }
    351 
    352 void FileSystemDispatcher::OnDidSucceed(int request_id) {
    353   CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id);
    354   DCHECK(dispatcher);
    355   dispatcher->DidSucceed();
    356   dispatchers_.Remove(request_id);
    357 }
    358 
    359 void FileSystemDispatcher::OnDidReadMetadata(
    360     int request_id, const base::File::Info& file_info) {
    361   CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id);
    362   DCHECK(dispatcher);
    363   dispatcher->DidReadMetadata(file_info);
    364   dispatchers_.Remove(request_id);
    365 }
    366 
    367 void FileSystemDispatcher::OnDidCreateSnapshotFile(
    368     int request_id, const base::File::Info& file_info,
    369     const base::FilePath& platform_path) {
    370   CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id);
    371   DCHECK(dispatcher);
    372   dispatcher->DidCreateSnapshotFile(file_info, platform_path, request_id);
    373   dispatchers_.Remove(request_id);
    374 }
    375 
    376 void FileSystemDispatcher::OnDidReadDirectory(
    377     int request_id,
    378     const std::vector<storage::DirectoryEntry>& entries,
    379     bool has_more) {
    380   CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id);
    381   DCHECK(dispatcher);
    382   dispatcher->DidReadDirectory(entries, has_more);
    383   if (!has_more)
    384     dispatchers_.Remove(request_id);
    385 }
    386 
    387 void FileSystemDispatcher::OnDidFail(
    388     int request_id, base::File::Error error_code) {
    389   CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id);
    390   DCHECK(dispatcher);
    391   dispatcher->DidFail(error_code);
    392   dispatchers_.Remove(request_id);
    393 }
    394 
    395 void FileSystemDispatcher::OnDidWrite(
    396     int request_id, int64 bytes, bool complete) {
    397   CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id);
    398   DCHECK(dispatcher);
    399   dispatcher->DidWrite(bytes, complete);
    400   if (complete)
    401     dispatchers_.Remove(request_id);
    402 }
    403 
    404 }  // namespace content
    405