Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(153)

Unified Diff: webkit/browser/fileapi/copy_or_move_operation_delegate.cc

Issue 539143002: Migrate webkit/browser/ to storage/browser/ (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: webkit/browser/fileapi/copy_or_move_operation_delegate.cc
diff --git a/webkit/browser/fileapi/copy_or_move_operation_delegate.cc b/webkit/browser/fileapi/copy_or_move_operation_delegate.cc
deleted file mode 100644
index 6bb089b9540a7f61708fbbdcb4e557144ac402f9..0000000000000000000000000000000000000000
--- a/webkit/browser/fileapi/copy_or_move_operation_delegate.cc
+++ /dev/null
@@ -1,995 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "webkit/browser/fileapi/copy_or_move_operation_delegate.h"
-
-#include "base/bind.h"
-#include "base/files/file_path.h"
-#include "net/base/io_buffer.h"
-#include "net/base/net_errors.h"
-#include "webkit/browser/blob/file_stream_reader.h"
-#include "webkit/browser/fileapi/copy_or_move_file_validator.h"
-#include "webkit/browser/fileapi/file_stream_writer.h"
-#include "webkit/browser/fileapi/file_system_context.h"
-#include "webkit/browser/fileapi/file_system_operation_runner.h"
-#include "webkit/browser/fileapi/file_system_url.h"
-#include "webkit/browser/fileapi/recursive_operation_delegate.h"
-#include "webkit/common/blob/shareable_file_reference.h"
-#include "webkit/common/fileapi/file_system_util.h"
-
-namespace storage {
-
-const int64 kFlushIntervalInBytes = 10 << 20; // 10MB.
-
-class CopyOrMoveOperationDelegate::CopyOrMoveImpl {
- public:
- virtual ~CopyOrMoveImpl() {}
- virtual void Run(
- const CopyOrMoveOperationDelegate::StatusCallback& callback) = 0;
- virtual void Cancel() = 0;
-
- protected:
- CopyOrMoveImpl() {}
-
- private:
- DISALLOW_COPY_AND_ASSIGN(CopyOrMoveImpl);
-};
-
-namespace {
-
-// Copies a file on a (same) file system. Just delegate the operation to
-// |operation_runner|.
-class CopyOrMoveOnSameFileSystemImpl
- : public CopyOrMoveOperationDelegate::CopyOrMoveImpl {
- public:
- CopyOrMoveOnSameFileSystemImpl(
- FileSystemOperationRunner* operation_runner,
- CopyOrMoveOperationDelegate::OperationType operation_type,
- const FileSystemURL& src_url,
- const FileSystemURL& dest_url,
- CopyOrMoveOperationDelegate::CopyOrMoveOption option,
- const FileSystemOperation::CopyFileProgressCallback&
- file_progress_callback)
- : operation_runner_(operation_runner),
- operation_type_(operation_type),
- src_url_(src_url),
- dest_url_(dest_url),
- option_(option),
- file_progress_callback_(file_progress_callback) {
- }
-
- virtual void Run(
- const CopyOrMoveOperationDelegate::StatusCallback& callback) OVERRIDE {
- if (operation_type_ == CopyOrMoveOperationDelegate::OPERATION_MOVE) {
- operation_runner_->MoveFileLocal(src_url_, dest_url_, option_, callback);
- } else {
- operation_runner_->CopyFileLocal(
- src_url_, dest_url_, option_, file_progress_callback_, callback);
- }
- }
-
- virtual void Cancel() OVERRIDE {
- // We can do nothing for the copy/move operation on a local file system.
- // Assuming the operation is quickly done, it should be ok to just wait
- // for the completion.
- }
-
- private:
- FileSystemOperationRunner* operation_runner_;
- CopyOrMoveOperationDelegate::OperationType operation_type_;
- FileSystemURL src_url_;
- FileSystemURL dest_url_;
- CopyOrMoveOperationDelegate::CopyOrMoveOption option_;
- FileSystemOperation::CopyFileProgressCallback file_progress_callback_;
- DISALLOW_COPY_AND_ASSIGN(CopyOrMoveOnSameFileSystemImpl);
-};
-
-// Specifically for cross file system copy/move operation, this class creates
-// a snapshot file, validates it if necessary, runs copying process,
-// validates the created file, and removes source file for move (noop for
-// copy).
-class SnapshotCopyOrMoveImpl
- : public CopyOrMoveOperationDelegate::CopyOrMoveImpl {
- public:
- SnapshotCopyOrMoveImpl(
- FileSystemOperationRunner* operation_runner,
- CopyOrMoveOperationDelegate::OperationType operation_type,
- const FileSystemURL& src_url,
- const FileSystemURL& dest_url,
- CopyOrMoveOperationDelegate::CopyOrMoveOption option,
- CopyOrMoveFileValidatorFactory* validator_factory,
- const FileSystemOperation::CopyFileProgressCallback&
- file_progress_callback)
- : operation_runner_(operation_runner),
- operation_type_(operation_type),
- src_url_(src_url),
- dest_url_(dest_url),
- option_(option),
- validator_factory_(validator_factory),
- file_progress_callback_(file_progress_callback),
- cancel_requested_(false),
- weak_factory_(this) {
- }
-
- virtual void Run(
- const CopyOrMoveOperationDelegate::StatusCallback& callback) OVERRIDE {
- file_progress_callback_.Run(0);
- operation_runner_->CreateSnapshotFile(
- src_url_,
- base::Bind(&SnapshotCopyOrMoveImpl::RunAfterCreateSnapshot,
- weak_factory_.GetWeakPtr(), callback));
- }
-
- virtual void Cancel() OVERRIDE {
- cancel_requested_ = true;
- }
-
- private:
- void RunAfterCreateSnapshot(
- const CopyOrMoveOperationDelegate::StatusCallback& callback,
- base::File::Error error,
- const base::File::Info& file_info,
- const base::FilePath& platform_path,
- const scoped_refptr<storage::ShareableFileReference>& file_ref) {
- if (cancel_requested_)
- error = base::File::FILE_ERROR_ABORT;
-
- if (error != base::File::FILE_OK) {
- callback.Run(error);
- return;
- }
-
- // For now we assume CreateSnapshotFile always return a valid local file
- // path.
- DCHECK(!platform_path.empty());
-
- if (!validator_factory_) {
- // No validation is needed.
- RunAfterPreWriteValidation(platform_path, file_info, file_ref, callback,
- base::File::FILE_OK);
- return;
- }
-
- // Run pre write validation.
- PreWriteValidation(
- platform_path,
- base::Bind(&SnapshotCopyOrMoveImpl::RunAfterPreWriteValidation,
- weak_factory_.GetWeakPtr(),
- platform_path, file_info, file_ref, callback));
- }
-
- void RunAfterPreWriteValidation(
- const base::FilePath& platform_path,
- const base::File::Info& file_info,
- const scoped_refptr<storage::ShareableFileReference>& file_ref,
- const CopyOrMoveOperationDelegate::StatusCallback& callback,
- base::File::Error error) {
- if (cancel_requested_)
- error = base::File::FILE_ERROR_ABORT;
-
- if (error != base::File::FILE_OK) {
- callback.Run(error);
- return;
- }
-
- // |file_ref| is unused but necessary to keep the file alive until
- // CopyInForeignFile() is completed.
- operation_runner_->CopyInForeignFile(
- platform_path, dest_url_,
- base::Bind(&SnapshotCopyOrMoveImpl::RunAfterCopyInForeignFile,
- weak_factory_.GetWeakPtr(), file_info, file_ref, callback));
- }
-
- void RunAfterCopyInForeignFile(
- const base::File::Info& file_info,
- const scoped_refptr<storage::ShareableFileReference>& file_ref,
- const CopyOrMoveOperationDelegate::StatusCallback& callback,
- base::File::Error error) {
- if (cancel_requested_)
- error = base::File::FILE_ERROR_ABORT;
-
- if (error != base::File::FILE_OK) {
- callback.Run(error);
- return;
- }
-
- file_progress_callback_.Run(file_info.size);
-
- if (option_ == FileSystemOperation::OPTION_NONE) {
- RunAfterTouchFile(callback, base::File::FILE_OK);
- return;
- }
-
- operation_runner_->TouchFile(
- dest_url_, base::Time::Now() /* last_access */,
- file_info.last_modified,
- base::Bind(&SnapshotCopyOrMoveImpl::RunAfterTouchFile,
- weak_factory_.GetWeakPtr(), callback));
- }
-
- void RunAfterTouchFile(
- const CopyOrMoveOperationDelegate::StatusCallback& callback,
- base::File::Error error) {
- // Even if TouchFile is failed, just ignore it.
-
- if (cancel_requested_) {
- callback.Run(base::File::FILE_ERROR_ABORT);
- return;
- }
-
- // |validator_| is NULL when the destination filesystem does not do
- // validation.
- if (!validator_) {
- // No validation is needed.
- RunAfterPostWriteValidation(callback, base::File::FILE_OK);
- return;
- }
-
- PostWriteValidation(
- base::Bind(&SnapshotCopyOrMoveImpl::RunAfterPostWriteValidation,
- weak_factory_.GetWeakPtr(), callback));
- }
-
- void RunAfterPostWriteValidation(
- const CopyOrMoveOperationDelegate::StatusCallback& callback,
- base::File::Error error) {
- if (cancel_requested_) {
- callback.Run(base::File::FILE_ERROR_ABORT);
- return;
- }
-
- if (error != base::File::FILE_OK) {
- // Failed to validate. Remove the destination file.
- operation_runner_->Remove(
- dest_url_, true /* recursive */,
- base::Bind(&SnapshotCopyOrMoveImpl::DidRemoveDestForError,
- weak_factory_.GetWeakPtr(), error, callback));
- return;
- }
-
- if (operation_type_ == CopyOrMoveOperationDelegate::OPERATION_COPY) {
- callback.Run(base::File::FILE_OK);
- return;
- }
-
- DCHECK_EQ(CopyOrMoveOperationDelegate::OPERATION_MOVE, operation_type_);
-
- // Remove the source for finalizing move operation.
- operation_runner_->Remove(
- src_url_, true /* recursive */,
- base::Bind(&SnapshotCopyOrMoveImpl::RunAfterRemoveSourceForMove,
- weak_factory_.GetWeakPtr(), callback));
- }
-
- void RunAfterRemoveSourceForMove(
- const CopyOrMoveOperationDelegate::StatusCallback& callback,
- base::File::Error error) {
- if (cancel_requested_)
- error = base::File::FILE_ERROR_ABORT;
-
- if (error == base::File::FILE_ERROR_NOT_FOUND)
- error = base::File::FILE_OK;
- callback.Run(error);
- }
-
- void DidRemoveDestForError(
- base::File::Error prior_error,
- const CopyOrMoveOperationDelegate::StatusCallback& callback,
- base::File::Error error) {
- if (error != base::File::FILE_OK) {
- VLOG(1) << "Error removing destination file after validation error: "
- << error;
- }
- callback.Run(prior_error);
- }
-
- // Runs pre-write validation.
- void PreWriteValidation(
- const base::FilePath& platform_path,
- const CopyOrMoveOperationDelegate::StatusCallback& callback) {
- DCHECK(validator_factory_);
- validator_.reset(
- validator_factory_->CreateCopyOrMoveFileValidator(
- src_url_, platform_path));
- validator_->StartPreWriteValidation(callback);
- }
-
- // Runs post-write validation.
- void PostWriteValidation(
- const CopyOrMoveOperationDelegate::StatusCallback& callback) {
- operation_runner_->CreateSnapshotFile(
- dest_url_,
- base::Bind(
- &SnapshotCopyOrMoveImpl::PostWriteValidationAfterCreateSnapshotFile,
- weak_factory_.GetWeakPtr(), callback));
- }
-
- void PostWriteValidationAfterCreateSnapshotFile(
- const CopyOrMoveOperationDelegate::StatusCallback& callback,
- base::File::Error error,
- const base::File::Info& file_info,
- const base::FilePath& platform_path,
- const scoped_refptr<storage::ShareableFileReference>& file_ref) {
- if (cancel_requested_)
- error = base::File::FILE_ERROR_ABORT;
-
- if (error != base::File::FILE_OK) {
- callback.Run(error);
- return;
- }
-
- DCHECK(validator_);
- // Note: file_ref passed here to keep the file alive until after
- // the StartPostWriteValidation operation finishes.
- validator_->StartPostWriteValidation(
- platform_path,
- base::Bind(&SnapshotCopyOrMoveImpl::DidPostWriteValidation,
- weak_factory_.GetWeakPtr(), file_ref, callback));
- }
-
- // |file_ref| is unused; it is passed here to make sure the reference is
- // alive until after post-write validation is complete.
- void DidPostWriteValidation(
- const scoped_refptr<storage::ShareableFileReference>& file_ref,
- const CopyOrMoveOperationDelegate::StatusCallback& callback,
- base::File::Error error) {
- callback.Run(error);
- }
-
- FileSystemOperationRunner* operation_runner_;
- CopyOrMoveOperationDelegate::OperationType operation_type_;
- FileSystemURL src_url_;
- FileSystemURL dest_url_;
-
- CopyOrMoveOperationDelegate::CopyOrMoveOption option_;
- CopyOrMoveFileValidatorFactory* validator_factory_;
- scoped_ptr<CopyOrMoveFileValidator> validator_;
- FileSystemOperation::CopyFileProgressCallback file_progress_callback_;
- bool cancel_requested_;
- base::WeakPtrFactory<SnapshotCopyOrMoveImpl> weak_factory_;
- DISALLOW_COPY_AND_ASSIGN(SnapshotCopyOrMoveImpl);
-};
-
-// The size of buffer for StreamCopyHelper.
-const int kReadBufferSize = 32768;
-
-// To avoid too many progress callbacks, it should be called less
-// frequently than 50ms.
-const int kMinProgressCallbackInvocationSpanInMilliseconds = 50;
-
-// Specifically for cross file system copy/move operation, this class uses
-// stream reader and writer for copying. Validator is not supported, so if
-// necessary SnapshotCopyOrMoveImpl should be used.
-class StreamCopyOrMoveImpl
- : public CopyOrMoveOperationDelegate::CopyOrMoveImpl {
- public:
- StreamCopyOrMoveImpl(
- FileSystemOperationRunner* operation_runner,
- CopyOrMoveOperationDelegate::OperationType operation_type,
- const FileSystemURL& src_url,
- const FileSystemURL& dest_url,
- CopyOrMoveOperationDelegate::CopyOrMoveOption option,
- scoped_ptr<storage::FileStreamReader> reader,
- scoped_ptr<FileStreamWriter> writer,
- const FileSystemOperation::CopyFileProgressCallback&
- file_progress_callback)
- : operation_runner_(operation_runner),
- operation_type_(operation_type),
- src_url_(src_url),
- dest_url_(dest_url),
- option_(option),
- reader_(reader.Pass()),
- writer_(writer.Pass()),
- file_progress_callback_(file_progress_callback),
- cancel_requested_(false),
- weak_factory_(this) {}
-
- virtual void Run(
- const CopyOrMoveOperationDelegate::StatusCallback& callback) OVERRIDE {
- // Reader can be created even if the entry does not exist or the entry is
- // a directory. To check errors before destination file creation,
- // check metadata first.
- operation_runner_->GetMetadata(
- src_url_,
- base::Bind(&StreamCopyOrMoveImpl::RunAfterGetMetadataForSource,
- weak_factory_.GetWeakPtr(), callback));
- }
-
- virtual void Cancel() OVERRIDE {
- cancel_requested_ = true;
- if (copy_helper_)
- copy_helper_->Cancel();
- }
-
- private:
- void RunAfterGetMetadataForSource(
- const CopyOrMoveOperationDelegate::StatusCallback& callback,
- base::File::Error error,
- const base::File::Info& file_info) {
- if (cancel_requested_)
- error = base::File::FILE_ERROR_ABORT;
-
- if (error != base::File::FILE_OK) {
- callback.Run(error);
- return;
- }
-
- if (file_info.is_directory) {
- // If not a directory, failed with appropriate error code.
- callback.Run(base::File::FILE_ERROR_NOT_A_FILE);
- return;
- }
-
- // To use FileStreamWriter, we need to ensure the destination file exists.
- operation_runner_->CreateFile(
- dest_url_,
- true /* exclusive */,
- base::Bind(&StreamCopyOrMoveImpl::RunAfterCreateFileForDestination,
- weak_factory_.GetWeakPtr(),
- callback,
- file_info.last_modified));
- }
-
- void RunAfterCreateFileForDestination(
- const CopyOrMoveOperationDelegate::StatusCallback& callback,
- const base::Time& last_modified,
- base::File::Error error) {
- if (cancel_requested_)
- error = base::File::FILE_ERROR_ABORT;
-
- if (error != base::File::FILE_OK &&
- error != base::File::FILE_ERROR_EXISTS) {
- callback.Run(error);
- return;
- }
-
- if (error == base::File::FILE_ERROR_EXISTS) {
- operation_runner_->Truncate(
- dest_url_,
- 0 /* length */,
- base::Bind(&StreamCopyOrMoveImpl::RunAfterTruncateForDestination,
- weak_factory_.GetWeakPtr(),
- callback,
- last_modified));
- return;
- }
- RunAfterTruncateForDestination(
- callback, last_modified, base::File::FILE_OK);
- }
-
- void RunAfterTruncateForDestination(
- const CopyOrMoveOperationDelegate::StatusCallback& callback,
- const base::Time& last_modified,
- base::File::Error error) {
- if (cancel_requested_)
- error = base::File::FILE_ERROR_ABORT;
-
- if (error != base::File::FILE_OK) {
- callback.Run(error);
- return;
- }
-
- const bool need_flush = dest_url_.mount_option().copy_sync_option() ==
- storage::COPY_SYNC_OPTION_SYNC;
-
- DCHECK(!copy_helper_);
- copy_helper_.reset(
- new CopyOrMoveOperationDelegate::StreamCopyHelper(
- reader_.Pass(), writer_.Pass(),
- need_flush,
- kReadBufferSize,
- file_progress_callback_,
- base::TimeDelta::FromMilliseconds(
- kMinProgressCallbackInvocationSpanInMilliseconds)));
- copy_helper_->Run(
- base::Bind(&StreamCopyOrMoveImpl::RunAfterStreamCopy,
- weak_factory_.GetWeakPtr(), callback, last_modified));
- }
-
- void RunAfterStreamCopy(
- const CopyOrMoveOperationDelegate::StatusCallback& callback,
- const base::Time& last_modified,
- base::File::Error error) {
- if (cancel_requested_)
- error = base::File::FILE_ERROR_ABORT;
-
- if (error != base::File::FILE_OK) {
- callback.Run(error);
- return;
- }
-
- if (option_ == FileSystemOperation::OPTION_NONE) {
- RunAfterTouchFile(callback, base::File::FILE_OK);
- return;
- }
-
- operation_runner_->TouchFile(
- dest_url_, base::Time::Now() /* last_access */, last_modified,
- base::Bind(&StreamCopyOrMoveImpl::RunAfterTouchFile,
- weak_factory_.GetWeakPtr(), callback));
- }
-
- void RunAfterTouchFile(
- const CopyOrMoveOperationDelegate::StatusCallback& callback,
- base::File::Error error) {
- // Even if TouchFile is failed, just ignore it.
- if (cancel_requested_) {
- callback.Run(base::File::FILE_ERROR_ABORT);
- return;
- }
-
- if (operation_type_ == CopyOrMoveOperationDelegate::OPERATION_COPY) {
- callback.Run(base::File::FILE_OK);
- return;
- }
-
- DCHECK_EQ(CopyOrMoveOperationDelegate::OPERATION_MOVE, operation_type_);
-
- // Remove the source for finalizing move operation.
- operation_runner_->Remove(
- src_url_, false /* recursive */,
- base::Bind(&StreamCopyOrMoveImpl::RunAfterRemoveForMove,
- weak_factory_.GetWeakPtr(), callback));
- }
-
- void RunAfterRemoveForMove(
- const CopyOrMoveOperationDelegate::StatusCallback& callback,
- base::File::Error error) {
- if (cancel_requested_)
- error = base::File::FILE_ERROR_ABORT;
- if (error == base::File::FILE_ERROR_NOT_FOUND)
- error = base::File::FILE_OK;
- callback.Run(error);
- }
-
- FileSystemOperationRunner* operation_runner_;
- CopyOrMoveOperationDelegate::OperationType operation_type_;
- FileSystemURL src_url_;
- FileSystemURL dest_url_;
- CopyOrMoveOperationDelegate::CopyOrMoveOption option_;
- scoped_ptr<storage::FileStreamReader> reader_;
- scoped_ptr<FileStreamWriter> writer_;
- FileSystemOperation::CopyFileProgressCallback file_progress_callback_;
- scoped_ptr<CopyOrMoveOperationDelegate::StreamCopyHelper> copy_helper_;
- bool cancel_requested_;
- base::WeakPtrFactory<StreamCopyOrMoveImpl> weak_factory_;
- DISALLOW_COPY_AND_ASSIGN(StreamCopyOrMoveImpl);
-};
-
-} // namespace
-
-CopyOrMoveOperationDelegate::StreamCopyHelper::StreamCopyHelper(
- scoped_ptr<storage::FileStreamReader> reader,
- scoped_ptr<FileStreamWriter> writer,
- bool need_flush,
- int buffer_size,
- const FileSystemOperation::CopyFileProgressCallback& file_progress_callback,
- const base::TimeDelta& min_progress_callback_invocation_span)
- : reader_(reader.Pass()),
- writer_(writer.Pass()),
- need_flush_(need_flush),
- file_progress_callback_(file_progress_callback),
- io_buffer_(new net::IOBufferWithSize(buffer_size)),
- num_copied_bytes_(0),
- previous_flush_offset_(0),
- min_progress_callback_invocation_span_(
- min_progress_callback_invocation_span),
- cancel_requested_(false),
- weak_factory_(this) {
-}
-
-CopyOrMoveOperationDelegate::StreamCopyHelper::~StreamCopyHelper() {
-}
-
-void CopyOrMoveOperationDelegate::StreamCopyHelper::Run(
- const StatusCallback& callback) {
- file_progress_callback_.Run(0);
- last_progress_callback_invocation_time_ = base::Time::Now();
- Read(callback);
-}
-
-void CopyOrMoveOperationDelegate::StreamCopyHelper::Cancel() {
- cancel_requested_ = true;
-}
-
-void CopyOrMoveOperationDelegate::StreamCopyHelper::Read(
- const StatusCallback& callback) {
- int result = reader_->Read(
- io_buffer_.get(), io_buffer_->size(),
- base::Bind(&StreamCopyHelper::DidRead,
- weak_factory_.GetWeakPtr(), callback));
- if (result != net::ERR_IO_PENDING)
- DidRead(callback, result);
-}
-
-void CopyOrMoveOperationDelegate::StreamCopyHelper::DidRead(
- const StatusCallback& callback, int result) {
- if (cancel_requested_) {
- callback.Run(base::File::FILE_ERROR_ABORT);
- return;
- }
-
- if (result < 0) {
- callback.Run(NetErrorToFileError(result));
- return;
- }
-
- if (result == 0) {
- // Here is the EOF.
- if (need_flush_)
- Flush(callback, true /* is_eof */);
- else
- callback.Run(base::File::FILE_OK);
- return;
- }
-
- Write(callback, new net::DrainableIOBuffer(io_buffer_.get(), result));
-}
-
-void CopyOrMoveOperationDelegate::StreamCopyHelper::Write(
- const StatusCallback& callback,
- scoped_refptr<net::DrainableIOBuffer> buffer) {
- DCHECK_GT(buffer->BytesRemaining(), 0);
-
- int result = writer_->Write(
- buffer.get(), buffer->BytesRemaining(),
- base::Bind(&StreamCopyHelper::DidWrite,
- weak_factory_.GetWeakPtr(), callback, buffer));
- if (result != net::ERR_IO_PENDING)
- DidWrite(callback, buffer, result);
-}
-
-void CopyOrMoveOperationDelegate::StreamCopyHelper::DidWrite(
- const StatusCallback& callback,
- scoped_refptr<net::DrainableIOBuffer> buffer,
- int result) {
- if (cancel_requested_) {
- callback.Run(base::File::FILE_ERROR_ABORT);
- return;
- }
-
- if (result < 0) {
- callback.Run(NetErrorToFileError(result));
- return;
- }
-
- buffer->DidConsume(result);
- num_copied_bytes_ += result;
-
- // Check the elapsed time since last |file_progress_callback_| invocation.
- base::Time now = base::Time::Now();
- if (now - last_progress_callback_invocation_time_ >=
- min_progress_callback_invocation_span_) {
- file_progress_callback_.Run(num_copied_bytes_);
- last_progress_callback_invocation_time_ = now;
- }
-
- if (buffer->BytesRemaining() > 0) {
- Write(callback, buffer);
- return;
- }
-
- if (need_flush_ &&
- (num_copied_bytes_ - previous_flush_offset_) > kFlushIntervalInBytes) {
- Flush(callback, false /* not is_eof */);
- } else {
- Read(callback);
- }
-}
-
-void CopyOrMoveOperationDelegate::StreamCopyHelper::Flush(
- const StatusCallback& callback, bool is_eof) {
- int result = writer_->Flush(
- base::Bind(&StreamCopyHelper::DidFlush,
- weak_factory_.GetWeakPtr(), callback, is_eof));
- if (result != net::ERR_IO_PENDING)
- DidFlush(callback, is_eof, result);
-}
-
-void CopyOrMoveOperationDelegate::StreamCopyHelper::DidFlush(
- const StatusCallback& callback, bool is_eof, int result) {
- if (cancel_requested_) {
- callback.Run(base::File::FILE_ERROR_ABORT);
- return;
- }
-
- previous_flush_offset_ = num_copied_bytes_;
- if (is_eof)
- callback.Run(NetErrorToFileError(result));
- else
- Read(callback);
-}
-
-CopyOrMoveOperationDelegate::CopyOrMoveOperationDelegate(
- FileSystemContext* file_system_context,
- const FileSystemURL& src_root,
- const FileSystemURL& dest_root,
- OperationType operation_type,
- CopyOrMoveOption option,
- const CopyProgressCallback& progress_callback,
- const StatusCallback& callback)
- : RecursiveOperationDelegate(file_system_context),
- src_root_(src_root),
- dest_root_(dest_root),
- operation_type_(operation_type),
- option_(option),
- progress_callback_(progress_callback),
- callback_(callback),
- weak_factory_(this) {
- same_file_system_ = src_root_.IsInSameFileSystem(dest_root_);
-}
-
-CopyOrMoveOperationDelegate::~CopyOrMoveOperationDelegate() {
- STLDeleteElements(&running_copy_set_);
-}
-
-void CopyOrMoveOperationDelegate::Run() {
- // Not supported; this should never be called.
- NOTREACHED();
-}
-
-void CopyOrMoveOperationDelegate::RunRecursively() {
- // Perform light-weight checks first.
-
- // It is an error to try to copy/move an entry into its child.
- if (same_file_system_ && src_root_.path().IsParent(dest_root_.path())) {
- callback_.Run(base::File::FILE_ERROR_INVALID_OPERATION);
- return;
- }
-
- if (same_file_system_ && src_root_.path() == dest_root_.path()) {
- // In JS API this should return error, but we return success because Pepper
- // wants to return success and we have a code path that returns error in
- // Blink for JS (http://crbug.com/329517).
- callback_.Run(base::File::FILE_OK);
- return;
- }
-
- // Start to process the source directory recursively.
- // TODO(kinuko): This could be too expensive for same_file_system_==true
- // and operation==MOVE case, probably we can just rename the root directory.
- // http://crbug.com/172187
- StartRecursiveOperation(src_root_, callback_);
-}
-
-void CopyOrMoveOperationDelegate::ProcessFile(
- const FileSystemURL& src_url,
- const StatusCallback& callback) {
- if (!progress_callback_.is_null()) {
- progress_callback_.Run(
- FileSystemOperation::BEGIN_COPY_ENTRY, src_url, FileSystemURL(), 0);
- }
-
- FileSystemURL dest_url = CreateDestURL(src_url);
- CopyOrMoveImpl* impl = NULL;
- if (same_file_system_ &&
- (file_system_context()
- ->GetFileSystemBackend(src_url.type())
- ->HasInplaceCopyImplementation(src_url.type()) ||
- operation_type_ == OperationType::OPERATION_MOVE)) {
- impl = new CopyOrMoveOnSameFileSystemImpl(
- operation_runner(), operation_type_, src_url, dest_url, option_,
- base::Bind(&CopyOrMoveOperationDelegate::OnCopyFileProgress,
- weak_factory_.GetWeakPtr(), src_url));
- } else {
- // Cross filesystem case.
- base::File::Error error = base::File::FILE_ERROR_FAILED;
- CopyOrMoveFileValidatorFactory* validator_factory =
- file_system_context()->GetCopyOrMoveFileValidatorFactory(
- dest_root_.type(), &error);
- if (error != base::File::FILE_OK) {
- callback.Run(error);
- return;
- }
-
- if (!validator_factory) {
- scoped_ptr<storage::FileStreamReader> reader =
- file_system_context()->CreateFileStreamReader(
- src_url, 0, base::Time());
- scoped_ptr<FileStreamWriter> writer =
- file_system_context()->CreateFileStreamWriter(dest_url, 0);
- if (reader && writer) {
- impl = new StreamCopyOrMoveImpl(
- operation_runner(), operation_type_, src_url, dest_url, option_,
- reader.Pass(), writer.Pass(),
- base::Bind(&CopyOrMoveOperationDelegate::OnCopyFileProgress,
- weak_factory_.GetWeakPtr(), src_url));
- }
- }
-
- if (!impl) {
- impl = new SnapshotCopyOrMoveImpl(
- operation_runner(), operation_type_, src_url, dest_url, option_,
- validator_factory,
- base::Bind(&CopyOrMoveOperationDelegate::OnCopyFileProgress,
- weak_factory_.GetWeakPtr(), src_url));
- }
- }
-
- // Register the running task.
- running_copy_set_.insert(impl);
- impl->Run(base::Bind(
- &CopyOrMoveOperationDelegate::DidCopyOrMoveFile,
- weak_factory_.GetWeakPtr(), src_url, dest_url, callback, impl));
-}
-
-void CopyOrMoveOperationDelegate::ProcessDirectory(
- const FileSystemURL& src_url,
- const StatusCallback& callback) {
- if (src_url == src_root_) {
- // The src_root_ looks to be a directory.
- // Try removing the dest_root_ to see if it exists and/or it is an
- // empty directory.
- // We do not invoke |progress_callback_| for source root, because it is
- // already called in ProcessFile().
- operation_runner()->RemoveDirectory(
- dest_root_,
- base::Bind(&CopyOrMoveOperationDelegate::DidTryRemoveDestRoot,
- weak_factory_.GetWeakPtr(), callback));
- return;
- }
-
- if (!progress_callback_.is_null()) {
- progress_callback_.Run(
- FileSystemOperation::BEGIN_COPY_ENTRY, src_url, FileSystemURL(), 0);
- }
-
- ProcessDirectoryInternal(src_url, CreateDestURL(src_url), callback);
-}
-
-void CopyOrMoveOperationDelegate::PostProcessDirectory(
- const FileSystemURL& src_url,
- const StatusCallback& callback) {
- if (option_ == FileSystemOperation::OPTION_NONE) {
- PostProcessDirectoryAfterTouchFile(
- src_url, callback, base::File::FILE_OK);
- return;
- }
-
- operation_runner()->GetMetadata(
- src_url,
- base::Bind(
- &CopyOrMoveOperationDelegate::PostProcessDirectoryAfterGetMetadata,
- weak_factory_.GetWeakPtr(), src_url, callback));
-}
-
-void CopyOrMoveOperationDelegate::OnCancel() {
- // Request to cancel all running Copy/Move file.
- for (std::set<CopyOrMoveImpl*>::iterator iter = running_copy_set_.begin();
- iter != running_copy_set_.end(); ++iter)
- (*iter)->Cancel();
-}
-
-void CopyOrMoveOperationDelegate::DidCopyOrMoveFile(
- const FileSystemURL& src_url,
- const FileSystemURL& dest_url,
- const StatusCallback& callback,
- CopyOrMoveImpl* impl,
- base::File::Error error) {
- running_copy_set_.erase(impl);
- delete impl;
-
- if (!progress_callback_.is_null() && error == base::File::FILE_OK) {
- progress_callback_.Run(
- FileSystemOperation::END_COPY_ENTRY, src_url, dest_url, 0);
- }
-
- callback.Run(error);
-}
-
-void CopyOrMoveOperationDelegate::DidTryRemoveDestRoot(
- const StatusCallback& callback,
- base::File::Error error) {
- if (error == base::File::FILE_ERROR_NOT_A_DIRECTORY) {
- callback_.Run(base::File::FILE_ERROR_INVALID_OPERATION);
- return;
- }
- if (error != base::File::FILE_OK &&
- error != base::File::FILE_ERROR_NOT_FOUND) {
- callback_.Run(error);
- return;
- }
-
- ProcessDirectoryInternal(src_root_, dest_root_, callback);
-}
-
-void CopyOrMoveOperationDelegate::ProcessDirectoryInternal(
- const FileSystemURL& src_url,
- const FileSystemURL& dest_url,
- const StatusCallback& callback) {
- // If operation_type == Move we may need to record directories and
- // restore directory timestamps in the end, though it may have
- // negative performance impact.
- // See http://crbug.com/171284 for more details.
- operation_runner()->CreateDirectory(
- dest_url, false /* exclusive */, false /* recursive */,
- base::Bind(&CopyOrMoveOperationDelegate::DidCreateDirectory,
- weak_factory_.GetWeakPtr(), src_url, dest_url, callback));
-}
-
-void CopyOrMoveOperationDelegate::DidCreateDirectory(
- const FileSystemURL& src_url,
- const FileSystemURL& dest_url,
- const StatusCallback& callback,
- base::File::Error error) {
- if (!progress_callback_.is_null() && error == base::File::FILE_OK) {
- progress_callback_.Run(
- FileSystemOperation::END_COPY_ENTRY, src_url, dest_url, 0);
- }
-
- callback.Run(error);
-}
-
-void CopyOrMoveOperationDelegate::PostProcessDirectoryAfterGetMetadata(
- const FileSystemURL& src_url,
- const StatusCallback& callback,
- base::File::Error error,
- const base::File::Info& file_info) {
- if (error != base::File::FILE_OK) {
- // Ignore the error, and run post process which should run after TouchFile.
- PostProcessDirectoryAfterTouchFile(
- src_url, callback, base::File::FILE_OK);
- return;
- }
-
- operation_runner()->TouchFile(
- CreateDestURL(src_url), base::Time::Now() /* last access */,
- file_info.last_modified,
- base::Bind(
- &CopyOrMoveOperationDelegate::PostProcessDirectoryAfterTouchFile,
- weak_factory_.GetWeakPtr(), src_url, callback));
-}
-
-void CopyOrMoveOperationDelegate::PostProcessDirectoryAfterTouchFile(
- const FileSystemURL& src_url,
- const StatusCallback& callback,
- base::File::Error error) {
- // Even if the TouchFile is failed, just ignore it.
-
- if (operation_type_ == OPERATION_COPY) {
- callback.Run(base::File::FILE_OK);
- return;
- }
-
- DCHECK_EQ(OPERATION_MOVE, operation_type_);
-
- // All files and subdirectories in the directory should be moved here,
- // so remove the source directory for finalizing move operation.
- operation_runner()->Remove(
- src_url, false /* recursive */,
- base::Bind(&CopyOrMoveOperationDelegate::DidRemoveSourceForMove,
- weak_factory_.GetWeakPtr(), callback));
-}
-
-void CopyOrMoveOperationDelegate::DidRemoveSourceForMove(
- const StatusCallback& callback,
- base::File::Error error) {
- if (error == base::File::FILE_ERROR_NOT_FOUND)
- error = base::File::FILE_OK;
- callback.Run(error);
-}
-
-void CopyOrMoveOperationDelegate::OnCopyFileProgress(
- const FileSystemURL& src_url, int64 size) {
- if (!progress_callback_.is_null()) {
- progress_callback_.Run(
- FileSystemOperation::PROGRESS, src_url, FileSystemURL(), size);
- }
-}
-
-FileSystemURL CopyOrMoveOperationDelegate::CreateDestURL(
- const FileSystemURL& src_url) const {
- DCHECK_EQ(src_root_.type(), src_url.type());
- DCHECK_EQ(src_root_.origin(), src_url.origin());
-
- base::FilePath relative = dest_root_.virtual_path();
- src_root_.virtual_path().AppendRelativePath(src_url.virtual_path(),
- &relative);
- return file_system_context()->CreateCrackedFileSystemURL(
- dest_root_.origin(),
- dest_root_.mount_type(),
- relative);
-}
-
-} // namespace storage

Powered by Google App Engine
This is Rietveld 408576698