Home | History | Annotate | Download | only in local
      1 // Copyright 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 "chrome/browser/sync_file_system/local/syncable_file_system_operation.h"
      6 
      7 #include "base/logging.h"
      8 #include "chrome/browser/sync_file_system/local/local_file_sync_context.h"
      9 #include "chrome/browser/sync_file_system/local/sync_file_system_backend.h"
     10 #include "chrome/browser/sync_file_system/local/syncable_file_operation_runner.h"
     11 #include "chrome/browser/sync_file_system/syncable_file_system_util.h"
     12 #include "net/url_request/url_request.h"
     13 #include "storage/browser/fileapi/file_system_context.h"
     14 #include "storage/browser/fileapi/file_system_operation.h"
     15 #include "storage/browser/fileapi/file_system_operation_context.h"
     16 #include "storage/browser/fileapi/file_system_url.h"
     17 #include "storage/browser/fileapi/file_writer_delegate.h"
     18 #include "storage/common/blob/shareable_file_reference.h"
     19 
     20 using storage::FileSystemURL;
     21 
     22 namespace sync_file_system {
     23 
     24 namespace {
     25 
     26 void WriteCallbackAdapter(
     27     const SyncableFileSystemOperation::WriteCallback& callback,
     28     base::File::Error status) {
     29   callback.Run(status, 0, true);
     30 }
     31 
     32 }  // namespace
     33 
     34 class SyncableFileSystemOperation::QueueableTask
     35     : public SyncableFileOperationRunner::Task {
     36  public:
     37   QueueableTask(base::WeakPtr<SyncableFileSystemOperation> operation,
     38                 const base::Closure& task)
     39       : operation_(operation),
     40         task_(task),
     41         target_paths_(operation->target_paths_) {}
     42 
     43   virtual ~QueueableTask() {
     44     DCHECK(!operation_);
     45   }
     46 
     47   virtual void Run() OVERRIDE {
     48     if (!operation_)
     49       return;
     50     DCHECK(!task_.is_null());
     51     task_.Run();
     52     operation_.reset();
     53   }
     54 
     55   virtual void Cancel() OVERRIDE {
     56     DCHECK(!task_.is_null());
     57     if (operation_)
     58       operation_->OnCancelled();
     59     task_.Reset();
     60     operation_.reset();
     61   }
     62 
     63   virtual const std::vector<FileSystemURL>& target_paths() const OVERRIDE {
     64     return target_paths_;
     65   }
     66 
     67  private:
     68   base::WeakPtr<SyncableFileSystemOperation> operation_;
     69   base::Closure task_;
     70   std::vector<FileSystemURL> target_paths_;
     71   DISALLOW_COPY_AND_ASSIGN(QueueableTask);
     72 };
     73 
     74 SyncableFileSystemOperation::~SyncableFileSystemOperation() {}
     75 
     76 void SyncableFileSystemOperation::CreateFile(
     77     const FileSystemURL& url,
     78     bool exclusive,
     79     const StatusCallback& callback) {
     80   DCHECK(CalledOnValidThread());
     81   if (!operation_runner_.get()) {
     82     callback.Run(base::File::FILE_ERROR_NOT_FOUND);
     83     return;
     84   }
     85   DCHECK(operation_runner_.get());
     86   target_paths_.push_back(url);
     87   completion_callback_ = callback;
     88   scoped_ptr<SyncableFileOperationRunner::Task> task(new QueueableTask(
     89       weak_factory_.GetWeakPtr(),
     90       base::Bind(&FileSystemOperation::CreateFile,
     91                  base::Unretained(impl_.get()),
     92                  url, exclusive,
     93                  base::Bind(&self::DidFinish, weak_factory_.GetWeakPtr()))));
     94   operation_runner_->PostOperationTask(task.Pass());
     95 }
     96 
     97 void SyncableFileSystemOperation::CreateDirectory(
     98     const FileSystemURL& url,
     99     bool exclusive,
    100     bool recursive,
    101     const StatusCallback& callback) {
    102   DCHECK(CalledOnValidThread());
    103   if (!operation_runner_.get()) {
    104     callback.Run(base::File::FILE_ERROR_NOT_FOUND);
    105     return;
    106   }
    107   DCHECK(operation_runner_.get());
    108   target_paths_.push_back(url);
    109   completion_callback_ = callback;
    110   scoped_ptr<SyncableFileOperationRunner::Task> task(new QueueableTask(
    111       weak_factory_.GetWeakPtr(),
    112       base::Bind(&FileSystemOperation::CreateDirectory,
    113                  base::Unretained(impl_.get()),
    114                  url, exclusive, recursive,
    115                  base::Bind(&self::DidFinish, weak_factory_.GetWeakPtr()))));
    116   operation_runner_->PostOperationTask(task.Pass());
    117 }
    118 
    119 void SyncableFileSystemOperation::Copy(
    120     const FileSystemURL& src_url,
    121     const FileSystemURL& dest_url,
    122     CopyOrMoveOption option,
    123     const CopyProgressCallback& progress_callback,
    124     const StatusCallback& callback) {
    125   DCHECK(CalledOnValidThread());
    126   if (!operation_runner_.get()) {
    127     callback.Run(base::File::FILE_ERROR_NOT_FOUND);
    128     return;
    129   }
    130   DCHECK(operation_runner_.get());
    131   target_paths_.push_back(dest_url);
    132   completion_callback_ = callback;
    133   scoped_ptr<SyncableFileOperationRunner::Task> task(new QueueableTask(
    134       weak_factory_.GetWeakPtr(),
    135       base::Bind(&FileSystemOperation::Copy,
    136                  base::Unretained(impl_.get()),
    137                  src_url, dest_url, option, progress_callback,
    138                  base::Bind(&self::DidFinish, weak_factory_.GetWeakPtr()))));
    139   operation_runner_->PostOperationTask(task.Pass());
    140 }
    141 
    142 void SyncableFileSystemOperation::Move(
    143     const FileSystemURL& src_url,
    144     const FileSystemURL& dest_url,
    145     CopyOrMoveOption option,
    146     const StatusCallback& callback) {
    147   DCHECK(CalledOnValidThread());
    148   if (!operation_runner_.get()) {
    149     callback.Run(base::File::FILE_ERROR_NOT_FOUND);
    150     return;
    151   }
    152   DCHECK(operation_runner_.get());
    153   target_paths_.push_back(src_url);
    154   target_paths_.push_back(dest_url);
    155   completion_callback_ = callback;
    156   scoped_ptr<SyncableFileOperationRunner::Task> task(new QueueableTask(
    157       weak_factory_.GetWeakPtr(),
    158       base::Bind(&FileSystemOperation::Move,
    159                  base::Unretained(impl_.get()),
    160                  src_url, dest_url, option,
    161                  base::Bind(&self::DidFinish, weak_factory_.GetWeakPtr()))));
    162   operation_runner_->PostOperationTask(task.Pass());
    163 }
    164 
    165 void SyncableFileSystemOperation::DirectoryExists(
    166     const FileSystemURL& url,
    167     const StatusCallback& callback) {
    168   DCHECK(CalledOnValidThread());
    169   impl_->DirectoryExists(url, callback);
    170 }
    171 
    172 void SyncableFileSystemOperation::FileExists(
    173     const FileSystemURL& url,
    174     const StatusCallback& callback) {
    175   DCHECK(CalledOnValidThread());
    176   impl_->FileExists(url, callback);
    177 }
    178 
    179 void SyncableFileSystemOperation::GetMetadata(
    180     const FileSystemURL& url,
    181     const GetMetadataCallback& callback) {
    182   DCHECK(CalledOnValidThread());
    183   impl_->GetMetadata(url, callback);
    184 }
    185 
    186 void SyncableFileSystemOperation::ReadDirectory(
    187     const FileSystemURL& url,
    188     const ReadDirectoryCallback& callback) {
    189   DCHECK(CalledOnValidThread());
    190   // This is a read operation and there'd be no hard to let it go even if
    191   // directory operation is disabled. (And we should allow this if it's made
    192   // on the root directory)
    193   impl_->ReadDirectory(url, callback);
    194 }
    195 
    196 void SyncableFileSystemOperation::Remove(
    197     const FileSystemURL& url, bool recursive,
    198     const StatusCallback& callback) {
    199   DCHECK(CalledOnValidThread());
    200   if (!operation_runner_.get()) {
    201     callback.Run(base::File::FILE_ERROR_NOT_FOUND);
    202     return;
    203   }
    204   DCHECK(operation_runner_.get());
    205   target_paths_.push_back(url);
    206   completion_callback_ = callback;
    207   scoped_ptr<SyncableFileOperationRunner::Task> task(new QueueableTask(
    208       weak_factory_.GetWeakPtr(),
    209       base::Bind(&FileSystemOperation::Remove,
    210                  base::Unretained(impl_.get()),
    211                  url, recursive,
    212                  base::Bind(&self::DidFinish, weak_factory_.GetWeakPtr()))));
    213   operation_runner_->PostOperationTask(task.Pass());
    214 }
    215 
    216 void SyncableFileSystemOperation::Write(
    217     const FileSystemURL& url,
    218     scoped_ptr<storage::FileWriterDelegate> writer_delegate,
    219     scoped_ptr<net::URLRequest> blob_request,
    220     const WriteCallback& callback) {
    221   DCHECK(CalledOnValidThread());
    222   if (!operation_runner_.get()) {
    223     callback.Run(base::File::FILE_ERROR_NOT_FOUND, 0, true);
    224     return;
    225   }
    226   DCHECK(operation_runner_.get());
    227   target_paths_.push_back(url);
    228   completion_callback_ = base::Bind(&WriteCallbackAdapter, callback);
    229   scoped_ptr<SyncableFileOperationRunner::Task> task(new QueueableTask(
    230       weak_factory_.GetWeakPtr(),
    231       base::Bind(&FileSystemOperation::Write,
    232                  base::Unretained(impl_.get()),
    233                  url,
    234                  base::Passed(&writer_delegate),
    235                  base::Passed(&blob_request),
    236                  base::Bind(&self::DidWrite, weak_factory_.GetWeakPtr(),
    237                             callback))));
    238   operation_runner_->PostOperationTask(task.Pass());
    239 }
    240 
    241 void SyncableFileSystemOperation::Truncate(
    242     const FileSystemURL& url, int64 length,
    243     const StatusCallback& callback) {
    244   DCHECK(CalledOnValidThread());
    245   if (!operation_runner_.get()) {
    246     callback.Run(base::File::FILE_ERROR_NOT_FOUND);
    247     return;
    248   }
    249   DCHECK(operation_runner_.get());
    250   target_paths_.push_back(url);
    251   completion_callback_ = callback;
    252   scoped_ptr<SyncableFileOperationRunner::Task> task(new QueueableTask(
    253       weak_factory_.GetWeakPtr(),
    254       base::Bind(&FileSystemOperation::Truncate,
    255                  base::Unretained(impl_.get()),
    256                  url, length,
    257                  base::Bind(&self::DidFinish, weak_factory_.GetWeakPtr()))));
    258   operation_runner_->PostOperationTask(task.Pass());
    259 }
    260 
    261 void SyncableFileSystemOperation::TouchFile(
    262     const FileSystemURL& url,
    263     const base::Time& last_access_time,
    264     const base::Time& last_modified_time,
    265     const StatusCallback& callback) {
    266   DCHECK(CalledOnValidThread());
    267   impl_->TouchFile(url, last_access_time, last_modified_time, callback);
    268 }
    269 
    270 void SyncableFileSystemOperation::OpenFile(
    271     const FileSystemURL& url,
    272     int file_flags,
    273     const OpenFileCallback& callback) {
    274   NOTREACHED();
    275 }
    276 
    277 void SyncableFileSystemOperation::Cancel(
    278     const StatusCallback& cancel_callback) {
    279   DCHECK(CalledOnValidThread());
    280   impl_->Cancel(cancel_callback);
    281 }
    282 
    283 void SyncableFileSystemOperation::CreateSnapshotFile(
    284     const FileSystemURL& path,
    285     const SnapshotFileCallback& callback) {
    286   DCHECK(CalledOnValidThread());
    287   impl_->CreateSnapshotFile(path, callback);
    288 }
    289 
    290 void SyncableFileSystemOperation::CopyInForeignFile(
    291     const base::FilePath& src_local_disk_path,
    292     const FileSystemURL& dest_url,
    293     const StatusCallback& callback) {
    294   DCHECK(CalledOnValidThread());
    295   if (!operation_runner_.get()) {
    296     callback.Run(base::File::FILE_ERROR_NOT_FOUND);
    297     return;
    298   }
    299   DCHECK(operation_runner_.get());
    300   target_paths_.push_back(dest_url);
    301   completion_callback_ = callback;
    302   scoped_ptr<SyncableFileOperationRunner::Task> task(new QueueableTask(
    303       weak_factory_.GetWeakPtr(),
    304       base::Bind(&FileSystemOperation::CopyInForeignFile,
    305                  base::Unretained(impl_.get()),
    306                  src_local_disk_path, dest_url,
    307                  base::Bind(&self::DidFinish, weak_factory_.GetWeakPtr()))));
    308   operation_runner_->PostOperationTask(task.Pass());
    309 }
    310 
    311 void SyncableFileSystemOperation::RemoveFile(
    312     const FileSystemURL& url,
    313     const StatusCallback& callback) {
    314   DCHECK(CalledOnValidThread());
    315   impl_->RemoveFile(url, callback);
    316 }
    317 
    318 void SyncableFileSystemOperation::RemoveDirectory(
    319     const FileSystemURL& url,
    320     const StatusCallback& callback) {
    321   DCHECK(CalledOnValidThread());
    322   impl_->RemoveDirectory(url, callback);
    323 }
    324 
    325 void SyncableFileSystemOperation::CopyFileLocal(
    326     const FileSystemURL& src_url,
    327     const FileSystemURL& dest_url,
    328     CopyOrMoveOption option,
    329     const CopyFileProgressCallback& progress_callback,
    330     const StatusCallback& callback) {
    331   DCHECK(CalledOnValidThread());
    332   impl_->CopyFileLocal(src_url, dest_url, option, progress_callback, callback);
    333 }
    334 
    335 void SyncableFileSystemOperation::MoveFileLocal(
    336     const FileSystemURL& src_url,
    337     const FileSystemURL& dest_url,
    338     CopyOrMoveOption option,
    339     const StatusCallback& callback) {
    340   DCHECK(CalledOnValidThread());
    341   impl_->MoveFileLocal(src_url, dest_url, option, callback);
    342 }
    343 
    344 base::File::Error SyncableFileSystemOperation::SyncGetPlatformPath(
    345     const FileSystemURL& url,
    346     base::FilePath* platform_path) {
    347   return impl_->SyncGetPlatformPath(url, platform_path);
    348 }
    349 
    350 SyncableFileSystemOperation::SyncableFileSystemOperation(
    351     const FileSystemURL& url,
    352     storage::FileSystemContext* file_system_context,
    353     scoped_ptr<storage::FileSystemOperationContext> operation_context)
    354     : url_(url), weak_factory_(this) {
    355   DCHECK(file_system_context);
    356   SyncFileSystemBackend* backend =
    357       SyncFileSystemBackend::GetBackend(file_system_context);
    358   DCHECK(backend);
    359   if (!backend->sync_context()) {
    360     // Syncable FileSystem is opened in a file system context which doesn't
    361     // support (or is not initialized for) the API.
    362     // Returning here to leave operation_runner_ as NULL.
    363     return;
    364   }
    365   impl_.reset(storage::FileSystemOperation::Create(
    366       url_, file_system_context, operation_context.Pass()));
    367   operation_runner_ = backend->sync_context()->operation_runner();
    368 }
    369 
    370 void SyncableFileSystemOperation::DidFinish(base::File::Error status) {
    371   DCHECK(CalledOnValidThread());
    372   DCHECK(!completion_callback_.is_null());
    373   if (operation_runner_.get())
    374     operation_runner_->OnOperationCompleted(target_paths_);
    375   completion_callback_.Run(status);
    376 }
    377 
    378 void SyncableFileSystemOperation::DidWrite(
    379     const WriteCallback& callback,
    380     base::File::Error result,
    381     int64 bytes,
    382     bool complete) {
    383   DCHECK(CalledOnValidThread());
    384   if (!complete) {
    385     callback.Run(result, bytes, complete);
    386     return;
    387   }
    388   if (operation_runner_.get())
    389     operation_runner_->OnOperationCompleted(target_paths_);
    390   callback.Run(result, bytes, complete);
    391 }
    392 
    393 void SyncableFileSystemOperation::OnCancelled() {
    394   DCHECK(!completion_callback_.is_null());
    395   completion_callback_.Run(base::File::FILE_ERROR_ABORT);
    396 }
    397 
    398 }  // namespace sync_file_system
    399