OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "webkit/fileapi/file_system_operation.h" | 5 #include "webkit/fileapi/file_system_operation.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/sequenced_task_runner.h" | 8 #include "base/sequenced_task_runner.h" |
9 #include "base/time.h" | 9 #include "base/time.h" |
10 #include "base/utf_string_conversions.h" | 10 #include "base/utf_string_conversions.h" |
(...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
283 path_url, &src_path_, &src_util_, PATH_FOR_WRITE); | 283 path_url, &src_path_, &src_util_, PATH_FOR_WRITE); |
284 if (result != base::PLATFORM_FILE_OK) { | 284 if (result != base::PLATFORM_FILE_OK) { |
285 callback.Run(result, 0, false); | 285 callback.Run(result, 0, false); |
286 delete this; | 286 delete this; |
287 return; | 287 return; |
288 } | 288 } |
289 DCHECK(blob_url.is_valid()); | 289 DCHECK(blob_url.is_valid()); |
290 file_writer_delegate_.reset(new FileWriterDelegate( | 290 file_writer_delegate_.reset(new FileWriterDelegate( |
291 this, src_path_, offset)); | 291 this, src_path_, offset)); |
292 set_write_callback(callback); | 292 set_write_callback(callback); |
293 blob_request_.reset( | 293 scoped_ptr<net::URLRequest> blob_request( |
294 new net::URLRequest(blob_url, file_writer_delegate_.get())); | 294 new net::URLRequest(blob_url, file_writer_delegate_.get())); |
295 blob_request_->set_context(url_request_context); | 295 blob_request->set_context(url_request_context); |
296 | 296 |
297 GetUsageAndQuotaThenRunTask( | 297 GetUsageAndQuotaThenRunTask( |
298 src_path_.origin(), src_path_.type(), | 298 src_path_.origin(), src_path_.type(), |
299 base::Bind(&FileSystemOperation::DoWrite, base::Unretained(this)), | 299 base::Bind(&FileSystemOperation::DoWrite, weak_factory_.GetWeakPtr(), |
| 300 base::Passed(&blob_request)), |
300 base::Bind(callback, base::PLATFORM_FILE_ERROR_FAILED, 0, true)); | 301 base::Bind(callback, base::PLATFORM_FILE_ERROR_FAILED, 0, true)); |
301 } | 302 } |
302 | 303 |
303 void FileSystemOperation::Truncate(const GURL& path_url, int64 length, | 304 void FileSystemOperation::Truncate(const GURL& path_url, int64 length, |
304 const StatusCallback& callback) { | 305 const StatusCallback& callback) { |
305 DCHECK(SetPendingOperationType(kOperationTruncate)); | 306 DCHECK(SetPendingOperationType(kOperationTruncate)); |
306 | 307 |
307 base::PlatformFileError result = SetUpFileSystemPath( | 308 base::PlatformFileError result = SetUpFileSystemPath( |
308 path_url, &src_path_, &src_util_, PATH_FOR_WRITE); | 309 path_url, &src_path_, &src_util_, PATH_FOR_WRITE); |
309 if (result != base::PLATFORM_FILE_OK) { | 310 if (result != base::PLATFORM_FILE_OK) { |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
382 base::Bind(callback, base::PLATFORM_FILE_ERROR_FAILED, | 383 base::Bind(callback, base::PLATFORM_FILE_ERROR_FAILED, |
383 base::kInvalidPlatformFileValue, | 384 base::kInvalidPlatformFileValue, |
384 base::kNullProcessHandle)); | 385 base::kNullProcessHandle)); |
385 } | 386 } |
386 | 387 |
387 // We can only get here on a write or truncate that's not yet completed. | 388 // We can only get here on a write or truncate that's not yet completed. |
388 // We don't support cancelling any other operation at this time. | 389 // We don't support cancelling any other operation at this time. |
389 void FileSystemOperation::Cancel(const StatusCallback& cancel_callback) { | 390 void FileSystemOperation::Cancel(const StatusCallback& cancel_callback) { |
390 if (file_writer_delegate_.get()) { | 391 if (file_writer_delegate_.get()) { |
391 DCHECK_EQ(kOperationWrite, pending_operation_); | 392 DCHECK_EQ(kOperationWrite, pending_operation_); |
| 393 |
392 // Writes are done without proxying through FileUtilProxy after the initial | 394 // Writes are done without proxying through FileUtilProxy after the initial |
393 // opening of the PlatformFile. All state changes are done on this thread, | 395 // opening of the PlatformFile. All state changes are done on this thread, |
394 // so we're guaranteed to be able to shut down atomically. We do need to | 396 // so we're guaranteed to be able to shut down atomically. |
395 // check that the file has been opened [which means the blob_request_ has | 397 const bool delete_now = file_writer_delegate_->Cancel(); |
396 // been created], so we know how much we need to do. | |
397 if (blob_request_.get()) | |
398 // This halts any calls to file_writer_delegate_ from blob_request_. | |
399 blob_request_->Cancel(); | |
400 | 398 |
401 if (!write_callback_.is_null()) { | 399 if (!write_callback_.is_null()) { |
402 // Notify the failure status to the ongoing operation's callback. | 400 // Notify the failure status to the ongoing operation's callback. |
403 write_callback_.Run(base::PLATFORM_FILE_ERROR_ABORT, 0, false); | 401 write_callback_.Run(base::PLATFORM_FILE_ERROR_ABORT, 0, false); |
404 // Do not delete this FileSystemOperation object yet. As a result of | |
405 // abort, this->DidWrite is called later and there we delete this object. | |
406 } | 402 } |
407 cancel_callback.Run(base::PLATFORM_FILE_OK); | 403 cancel_callback.Run(base::PLATFORM_FILE_OK); |
408 write_callback_.Reset(); | 404 write_callback_.Reset(); |
| 405 |
| 406 if (delete_now) { |
| 407 delete this; |
| 408 return; |
| 409 } |
409 } else { | 410 } else { |
410 DCHECK_EQ(kOperationTruncate, pending_operation_); | 411 DCHECK_EQ(kOperationTruncate, pending_operation_); |
411 // We're cancelling a truncate operation, but we can't actually stop it | 412 // We're cancelling a truncate operation, but we can't actually stop it |
412 // since it's been proxied to another thread. We need to save the | 413 // since it's been proxied to another thread. We need to save the |
413 // cancel_callback so that when the truncate returns, it can see that it's | 414 // cancel_callback so that when the truncate returns, it can see that it's |
414 // been cancelled, report it, and report that the cancel has succeeded. | 415 // been cancelled, report it, and report that the cancel has succeeded. |
415 DCHECK(cancel_callback_.is_null()); | 416 DCHECK(cancel_callback_.is_null()); |
416 cancel_callback_ = cancel_callback; | 417 cancel_callback_ = cancel_callback; |
417 } | 418 } |
418 } | 419 } |
(...skipping 24 matching lines...) Expand all Loading... |
443 const SnapshotFileCallback& callback) { | 444 const SnapshotFileCallback& callback) { |
444 GetMetadata(path_url, base::Bind(&GetMetadataForSnapshot, callback)); | 445 GetMetadata(path_url, base::Bind(&GetMetadataForSnapshot, callback)); |
445 } | 446 } |
446 | 447 |
447 FileSystemOperation::FileSystemOperation( | 448 FileSystemOperation::FileSystemOperation( |
448 FileSystemContext* file_system_context) | 449 FileSystemContext* file_system_context) |
449 : operation_context_(file_system_context), | 450 : operation_context_(file_system_context), |
450 src_util_(NULL), | 451 src_util_(NULL), |
451 dest_util_(NULL), | 452 dest_util_(NULL), |
452 peer_handle_(base::kNullProcessHandle), | 453 peer_handle_(base::kNullProcessHandle), |
453 pending_operation_(kOperationNone) { | 454 pending_operation_(kOperationNone), |
| 455 weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { |
454 } | 456 } |
455 | 457 |
456 void FileSystemOperation::GetUsageAndQuotaThenRunTask( | 458 void FileSystemOperation::GetUsageAndQuotaThenRunTask( |
457 const GURL& origin, FileSystemType type, | 459 const GURL& origin, FileSystemType type, |
458 const base::Closure& task, | 460 const base::Closure& task, |
459 const base::Closure& error_callback) { | 461 const base::Closure& error_callback) { |
460 quota::QuotaManagerProxy* quota_manager_proxy = | 462 quota::QuotaManagerProxy* quota_manager_proxy = |
461 file_system_context()->quota_manager_proxy(); | 463 file_system_context()->quota_manager_proxy(); |
462 if (!quota_manager_proxy || | 464 if (!quota_manager_proxy || |
463 !file_system_context()->GetQuotaUtil(type)) { | 465 !file_system_context()->GetQuotaUtil(type)) { |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
533 | 535 |
534 void FileSystemOperation::DoMove(const StatusCallback& callback) { | 536 void FileSystemOperation::DoMove(const StatusCallback& callback) { |
535 FileSystemFileUtilProxy::Move( | 537 FileSystemFileUtilProxy::Move( |
536 &operation_context_, | 538 &operation_context_, |
537 src_util_, dest_util_, | 539 src_util_, dest_util_, |
538 src_path_, dest_path_, | 540 src_path_, dest_path_, |
539 base::Bind(&FileSystemOperation::DidFinishFileOperation, | 541 base::Bind(&FileSystemOperation::DidFinishFileOperation, |
540 base::Owned(this), callback)); | 542 base::Owned(this), callback)); |
541 } | 543 } |
542 | 544 |
543 void FileSystemOperation::DoWrite() { | 545 void FileSystemOperation::DoWrite(scoped_ptr<net::URLRequest> blob_request) { |
544 int file_flags = base::PLATFORM_FILE_OPEN | | 546 int file_flags = base::PLATFORM_FILE_OPEN | |
545 base::PLATFORM_FILE_WRITE | | 547 base::PLATFORM_FILE_WRITE | |
546 base::PLATFORM_FILE_ASYNC; | 548 base::PLATFORM_FILE_ASYNC; |
547 | 549 |
| 550 // We may get deleted on the way so allocate a new operation context |
| 551 // to keep it alive. |
| 552 FileSystemOperationContext* write_context = new FileSystemOperationContext( |
| 553 operation_context_); |
548 FileSystemFileUtilProxy::CreateOrOpen( | 554 FileSystemFileUtilProxy::CreateOrOpen( |
549 &operation_context_, src_util_, src_path_, file_flags, | 555 write_context, src_util_, src_path_, file_flags, |
550 base::Bind(&FileSystemOperation::OnFileOpenedForWrite, | 556 base::Bind(&FileSystemOperation::OnFileOpenedForWrite, |
551 base::Unretained(this))); | 557 weak_factory_.GetWeakPtr(), |
| 558 base::Passed(&blob_request), |
| 559 base::Owned(write_context))); |
552 } | 560 } |
553 | 561 |
554 void FileSystemOperation::DoTruncate(const StatusCallback& callback, | 562 void FileSystemOperation::DoTruncate(const StatusCallback& callback, |
555 int64 length) { | 563 int64 length) { |
556 FileSystemFileUtilProxy::Truncate( | 564 FileSystemFileUtilProxy::Truncate( |
557 &operation_context_, src_util_, src_path_, length, | 565 &operation_context_, src_util_, src_path_, length, |
558 base::Bind(&FileSystemOperation::DidFinishFileOperation, | 566 base::Bind(&FileSystemOperation::DidFinishFileOperation, |
559 base::Owned(this), callback)); | 567 base::Owned(this), callback)); |
560 } | 568 } |
561 | 569 |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
657 const OpenFileCallback& callback, | 665 const OpenFileCallback& callback, |
658 base::PlatformFileError rv, | 666 base::PlatformFileError rv, |
659 base::PassPlatformFile file, | 667 base::PassPlatformFile file, |
660 bool unused) { | 668 bool unused) { |
661 if (rv == base::PLATFORM_FILE_OK) | 669 if (rv == base::PLATFORM_FILE_OK) |
662 CHECK_NE(base::kNullProcessHandle, peer_handle_); | 670 CHECK_NE(base::kNullProcessHandle, peer_handle_); |
663 callback.Run(rv, file.ReleaseValue(), peer_handle_); | 671 callback.Run(rv, file.ReleaseValue(), peer_handle_); |
664 } | 672 } |
665 | 673 |
666 void FileSystemOperation::OnFileOpenedForWrite( | 674 void FileSystemOperation::OnFileOpenedForWrite( |
| 675 scoped_ptr<net::URLRequest> blob_request, |
| 676 FileSystemOperationContext* unused, |
667 base::PlatformFileError rv, | 677 base::PlatformFileError rv, |
668 base::PassPlatformFile file, | 678 base::PassPlatformFile file, |
669 bool created) { | 679 bool created) { |
670 if (rv != base::PLATFORM_FILE_OK) { | 680 if (rv != base::PLATFORM_FILE_OK) { |
671 if (!write_callback_.is_null()) | 681 if (!write_callback_.is_null()) |
672 write_callback_.Run(rv, 0, false); | 682 write_callback_.Run(rv, 0, false); |
673 delete this; | 683 delete this; |
674 return; | 684 return; |
675 } | 685 } |
676 file_writer_delegate_->Start(file.ReleaseValue(), blob_request_.get()); | 686 file_writer_delegate_->Start(file.ReleaseValue(), blob_request.Pass()); |
677 } | 687 } |
678 | 688 |
679 base::PlatformFileError FileSystemOperation::SetUpFileSystemPath( | 689 base::PlatformFileError FileSystemOperation::SetUpFileSystemPath( |
680 const GURL& path_url, | 690 const GURL& path_url, |
681 FileSystemPath* file_system_path, | 691 FileSystemPath* file_system_path, |
682 FileSystemFileUtil** file_util, | 692 FileSystemFileUtil** file_util, |
683 SetUpPathMode mode) { | 693 SetUpPathMode mode) { |
684 DCHECK(file_system_path); | 694 DCHECK(file_system_path); |
685 GURL origin_url; | 695 GURL origin_url; |
686 FileSystemType type; | 696 FileSystemType type; |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
736 } | 746 } |
737 | 747 |
738 bool FileSystemOperation::SetPendingOperationType(OperationType type) { | 748 bool FileSystemOperation::SetPendingOperationType(OperationType type) { |
739 if (pending_operation_ != kOperationNone) | 749 if (pending_operation_ != kOperationNone) |
740 return false; | 750 return false; |
741 pending_operation_ = type; | 751 pending_operation_ = type; |
742 return true; | 752 return true; |
743 } | 753 } |
744 | 754 |
745 } // namespace fileapi | 755 } // namespace fileapi |
OLD | NEW |