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