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