Home | History | Annotate | Download | only in fileapi
      1 // Copyright (c) 2013 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 "webkit/browser/fileapi/async_file_util_adapter.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/sequenced_task_runner.h"
      9 #include "base/task_runner_util.h"
     10 #include "webkit/browser/fileapi/file_system_context.h"
     11 #include "webkit/browser/fileapi/file_system_file_util.h"
     12 #include "webkit/browser/fileapi/file_system_operation_context.h"
     13 #include "webkit/browser/fileapi/file_system_url.h"
     14 #include "webkit/common/blob/shareable_file_reference.h"
     15 #include "webkit/common/fileapi/file_system_util.h"
     16 
     17 using base::Bind;
     18 using base::Callback;
     19 using base::Owned;
     20 using base::PlatformFileError;
     21 using base::Unretained;
     22 using webkit_blob::ShareableFileReference;
     23 
     24 namespace fileapi {
     25 
     26 namespace {
     27 
     28 class EnsureFileExistsHelper {
     29  public:
     30   EnsureFileExistsHelper() : error_(base::PLATFORM_FILE_OK), created_(false) {}
     31 
     32   void RunWork(FileSystemFileUtil* file_util,
     33                FileSystemOperationContext* context,
     34                const FileSystemURL& url) {
     35     error_ = file_util->EnsureFileExists(context, url, &created_);
     36   }
     37 
     38   void Reply(const AsyncFileUtil::EnsureFileExistsCallback& callback) {
     39     callback.Run(error_, created_);
     40   }
     41 
     42  private:
     43   base::PlatformFileError error_;
     44   bool created_;
     45   DISALLOW_COPY_AND_ASSIGN(EnsureFileExistsHelper);
     46 };
     47 
     48 class GetFileInfoHelper {
     49  public:
     50   GetFileInfoHelper()
     51       : error_(base::PLATFORM_FILE_OK) {}
     52 
     53   void GetFileInfo(FileSystemFileUtil* file_util,
     54                    FileSystemOperationContext* context,
     55                    const FileSystemURL& url) {
     56     error_ = file_util->GetFileInfo(context, url, &file_info_, &platform_path_);
     57   }
     58 
     59   void CreateSnapshotFile(FileSystemFileUtil* file_util,
     60                           FileSystemOperationContext* context,
     61                           const FileSystemURL& url) {
     62     scoped_file_ = file_util->CreateSnapshotFile(
     63         context, url, &error_, &file_info_, &platform_path_);
     64   }
     65 
     66   void ReplyFileInfo(const AsyncFileUtil::GetFileInfoCallback& callback) {
     67     callback.Run(error_, file_info_);
     68   }
     69 
     70   void ReplySnapshotFile(
     71       const AsyncFileUtil::CreateSnapshotFileCallback& callback) {
     72     callback.Run(error_, file_info_, platform_path_,
     73                   ShareableFileReference::GetOrCreate(scoped_file_.Pass()));
     74   }
     75 
     76  private:
     77   base::PlatformFileError error_;
     78   base::PlatformFileInfo file_info_;
     79   base::FilePath platform_path_;
     80   webkit_blob::ScopedFile scoped_file_;
     81   DISALLOW_COPY_AND_ASSIGN(GetFileInfoHelper);
     82 };
     83 
     84 class ReadDirectoryHelper {
     85  public:
     86   ReadDirectoryHelper() : error_(base::PLATFORM_FILE_OK) {}
     87 
     88   void RunWork(FileSystemFileUtil* file_util,
     89                FileSystemOperationContext* context,
     90                const FileSystemURL& url) {
     91     base::PlatformFileInfo file_info;
     92     base::FilePath platform_path;
     93     PlatformFileError error = file_util->GetFileInfo(
     94         context, url, &file_info, &platform_path);
     95     if (error != base::PLATFORM_FILE_OK) {
     96       error_ = error;
     97       return;
     98     }
     99     if (!file_info.is_directory) {
    100       error_ = base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY;
    101       return;
    102     }
    103 
    104     scoped_ptr<FileSystemFileUtil::AbstractFileEnumerator> file_enum(
    105         file_util->CreateFileEnumerator(context, url));
    106 
    107     base::FilePath current;
    108     while (!(current = file_enum->Next()).empty()) {
    109       DirectoryEntry entry;
    110       entry.is_directory = file_enum->IsDirectory();
    111       entry.name = VirtualPath::BaseName(current).value();
    112       entry.size = file_enum->Size();
    113       entry.last_modified_time = file_enum->LastModifiedTime();
    114       entries_.push_back(entry);
    115     }
    116     error_ = base::PLATFORM_FILE_OK;
    117   }
    118 
    119   void Reply(const AsyncFileUtil::ReadDirectoryCallback& callback) {
    120     callback.Run(error_, entries_, false /* has_more */);
    121   }
    122 
    123  private:
    124   base::PlatformFileError error_;
    125   std::vector<DirectoryEntry> entries_;
    126   DISALLOW_COPY_AND_ASSIGN(ReadDirectoryHelper);
    127 };
    128 
    129 void RunCreateOrOpenCallback(
    130     const AsyncFileUtil::CreateOrOpenCallback& callback,
    131     base::PlatformFileError result,
    132     base::PassPlatformFile file,
    133     bool created) {
    134   callback.Run(result, file, base::Closure());
    135 }
    136 
    137 }  // namespace
    138 
    139 AsyncFileUtilAdapter::AsyncFileUtilAdapter(
    140     FileSystemFileUtil* sync_file_util)
    141     : sync_file_util_(sync_file_util) {
    142   DCHECK(sync_file_util_.get());
    143 }
    144 
    145 AsyncFileUtilAdapter::~AsyncFileUtilAdapter() {
    146 }
    147 
    148 void AsyncFileUtilAdapter::CreateOrOpen(
    149     scoped_ptr<FileSystemOperationContext> context,
    150     const FileSystemURL& url,
    151     int file_flags,
    152     const CreateOrOpenCallback& callback) {
    153   FileSystemOperationContext* context_ptr = context.release();
    154   const bool success = base::FileUtilProxy::RelayCreateOrOpen(
    155       context_ptr->task_runner(),
    156       Bind(&FileSystemFileUtil::CreateOrOpen, Unretained(sync_file_util_.get()),
    157            context_ptr, url, file_flags),
    158       Bind(&FileSystemFileUtil::Close, Unretained(sync_file_util_.get()),
    159            base::Owned(context_ptr)),
    160       Bind(&RunCreateOrOpenCallback, callback));
    161   DCHECK(success);
    162 }
    163 
    164 void AsyncFileUtilAdapter::EnsureFileExists(
    165     scoped_ptr<FileSystemOperationContext> context,
    166     const FileSystemURL& url,
    167     const EnsureFileExistsCallback& callback) {
    168   EnsureFileExistsHelper* helper = new EnsureFileExistsHelper;
    169   FileSystemOperationContext* context_ptr = context.release();
    170   const bool success = context_ptr->task_runner()->PostTaskAndReply(
    171         FROM_HERE,
    172         Bind(&EnsureFileExistsHelper::RunWork, Unretained(helper),
    173              sync_file_util_.get(), base::Owned(context_ptr), url),
    174         Bind(&EnsureFileExistsHelper::Reply, Owned(helper), callback));
    175   DCHECK(success);
    176 }
    177 
    178 void AsyncFileUtilAdapter::CreateDirectory(
    179     scoped_ptr<FileSystemOperationContext> context,
    180     const FileSystemURL& url,
    181     bool exclusive,
    182     bool recursive,
    183     const StatusCallback& callback) {
    184   FileSystemOperationContext* context_ptr = context.release();
    185   const bool success = base::PostTaskAndReplyWithResult(
    186       context_ptr->task_runner(), FROM_HERE,
    187       Bind(&FileSystemFileUtil::CreateDirectory,
    188            Unretained(sync_file_util_.get()),
    189            base::Owned(context_ptr), url, exclusive, recursive),
    190       callback);
    191   DCHECK(success);
    192 }
    193 
    194 void AsyncFileUtilAdapter::GetFileInfo(
    195     scoped_ptr<FileSystemOperationContext> context,
    196     const FileSystemURL& url,
    197     const GetFileInfoCallback& callback) {
    198   FileSystemOperationContext* context_ptr = context.release();
    199   GetFileInfoHelper* helper = new GetFileInfoHelper;
    200   const bool success = context_ptr->task_runner()->PostTaskAndReply(
    201         FROM_HERE,
    202         Bind(&GetFileInfoHelper::GetFileInfo, Unretained(helper),
    203              sync_file_util_.get(), base::Owned(context_ptr), url),
    204         Bind(&GetFileInfoHelper::ReplyFileInfo, Owned(helper), callback));
    205   DCHECK(success);
    206 }
    207 
    208 void AsyncFileUtilAdapter::ReadDirectory(
    209     scoped_ptr<FileSystemOperationContext> context,
    210     const FileSystemURL& url,
    211     const ReadDirectoryCallback& callback) {
    212   FileSystemOperationContext* context_ptr = context.release();
    213   ReadDirectoryHelper* helper = new ReadDirectoryHelper;
    214   const bool success = context_ptr->task_runner()->PostTaskAndReply(
    215         FROM_HERE,
    216         Bind(&ReadDirectoryHelper::RunWork, Unretained(helper),
    217              sync_file_util_.get(), base::Owned(context_ptr), url),
    218         Bind(&ReadDirectoryHelper::Reply, Owned(helper), callback));
    219   DCHECK(success);
    220 }
    221 
    222 void AsyncFileUtilAdapter::Touch(
    223     scoped_ptr<FileSystemOperationContext> context,
    224     const FileSystemURL& url,
    225     const base::Time& last_access_time,
    226     const base::Time& last_modified_time,
    227     const StatusCallback& callback) {
    228   FileSystemOperationContext* context_ptr = context.release();
    229   const bool success = base::PostTaskAndReplyWithResult(
    230       context_ptr->task_runner(), FROM_HERE,
    231       Bind(&FileSystemFileUtil::Touch, Unretained(sync_file_util_.get()),
    232            base::Owned(context_ptr), url,
    233            last_access_time, last_modified_time),
    234       callback);
    235   DCHECK(success);
    236 }
    237 
    238 void AsyncFileUtilAdapter::Truncate(
    239     scoped_ptr<FileSystemOperationContext> context,
    240     const FileSystemURL& url,
    241     int64 length,
    242     const StatusCallback& callback) {
    243   FileSystemOperationContext* context_ptr = context.release();
    244   const bool success = base::PostTaskAndReplyWithResult(
    245       context_ptr->task_runner(), FROM_HERE,
    246       Bind(&FileSystemFileUtil::Truncate, Unretained(sync_file_util_.get()),
    247            base::Owned(context_ptr), url, length),
    248       callback);
    249   DCHECK(success);
    250 }
    251 
    252 void AsyncFileUtilAdapter::CopyFileLocal(
    253     scoped_ptr<FileSystemOperationContext> context,
    254     const FileSystemURL& src_url,
    255     const FileSystemURL& dest_url,
    256     const StatusCallback& callback) {
    257   FileSystemOperationContext* context_ptr = context.release();
    258   const bool success = base::PostTaskAndReplyWithResult(
    259       context_ptr->task_runner(), FROM_HERE,
    260       Bind(&FileSystemFileUtil::CopyOrMoveFile,
    261            Unretained(sync_file_util_.get()),
    262            base::Owned(context_ptr), src_url, dest_url, true /* copy */),
    263       callback);
    264   DCHECK(success);
    265 }
    266 
    267 void AsyncFileUtilAdapter::MoveFileLocal(
    268     scoped_ptr<FileSystemOperationContext> context,
    269     const FileSystemURL& src_url,
    270     const FileSystemURL& dest_url,
    271     const StatusCallback& callback) {
    272   FileSystemOperationContext* context_ptr = context.release();
    273   const bool success = base::PostTaskAndReplyWithResult(
    274       context_ptr->task_runner(), FROM_HERE,
    275       Bind(&FileSystemFileUtil::CopyOrMoveFile,
    276            Unretained(sync_file_util_.get()),
    277            base::Owned(context_ptr), src_url, dest_url, false /* copy */),
    278       callback);
    279   DCHECK(success);
    280 }
    281 
    282 void AsyncFileUtilAdapter::CopyInForeignFile(
    283       scoped_ptr<FileSystemOperationContext> context,
    284       const base::FilePath& src_file_path,
    285       const FileSystemURL& dest_url,
    286       const StatusCallback& callback) {
    287   FileSystemOperationContext* context_ptr = context.release();
    288   const bool success = base::PostTaskAndReplyWithResult(
    289       context_ptr->task_runner(), FROM_HERE,
    290       Bind(&FileSystemFileUtil::CopyInForeignFile,
    291            Unretained(sync_file_util_.get()),
    292            base::Owned(context_ptr), src_file_path, dest_url),
    293       callback);
    294   DCHECK(success);
    295 }
    296 
    297 void AsyncFileUtilAdapter::DeleteFile(
    298     scoped_ptr<FileSystemOperationContext> context,
    299     const FileSystemURL& url,
    300     const StatusCallback& callback) {
    301   FileSystemOperationContext* context_ptr = context.release();
    302   const bool success = base::PostTaskAndReplyWithResult(
    303       context_ptr->task_runner(), FROM_HERE,
    304       Bind(&FileSystemFileUtil::DeleteFile,
    305            Unretained(sync_file_util_.get()),
    306            base::Owned(context_ptr), url),
    307       callback);
    308   DCHECK(success);
    309 }
    310 
    311 void AsyncFileUtilAdapter::DeleteDirectory(
    312     scoped_ptr<FileSystemOperationContext> context,
    313     const FileSystemURL& url,
    314     const StatusCallback& callback) {
    315   FileSystemOperationContext* context_ptr = context.release();
    316   const bool success = base::PostTaskAndReplyWithResult(
    317       context_ptr->task_runner(), FROM_HERE,
    318       Bind(&FileSystemFileUtil::DeleteDirectory,
    319            Unretained(sync_file_util_.get()),
    320            base::Owned(context_ptr), url),
    321       callback);
    322   DCHECK(success);
    323 }
    324 
    325 void AsyncFileUtilAdapter::DeleteRecursively(
    326     scoped_ptr<FileSystemOperationContext> context,
    327     const FileSystemURL& url,
    328     const StatusCallback& callback) {
    329   callback.Run(base::PLATFORM_FILE_ERROR_INVALID_OPERATION);
    330 }
    331 
    332 void AsyncFileUtilAdapter::CreateSnapshotFile(
    333     scoped_ptr<FileSystemOperationContext> context,
    334     const FileSystemURL& url,
    335     const CreateSnapshotFileCallback& callback) {
    336   FileSystemOperationContext* context_ptr = context.release();
    337   GetFileInfoHelper* helper = new GetFileInfoHelper;
    338   const bool success = context_ptr->task_runner()->PostTaskAndReply(
    339         FROM_HERE,
    340         Bind(&GetFileInfoHelper::CreateSnapshotFile, Unretained(helper),
    341              sync_file_util_.get(), base::Owned(context_ptr), url),
    342         Bind(&GetFileInfoHelper::ReplySnapshotFile, Owned(helper), callback));
    343   DCHECK(success);
    344 }
    345 
    346 }  // namespace fileapi
    347