diff options
author | hidehiko@chromium.org <hidehiko@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-09-12 13:07:42 +0000 |
---|---|---|
committer | hidehiko@chromium.org <hidehiko@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-09-12 13:07:42 +0000 |
commit | b2ef40c775cba50c908f1b72d377a19b8c457b36 (patch) | |
tree | ed74257b5534b026a220106a5063a70c363a49d3 /webkit | |
parent | cf90f2e21739d39319d9f04cde8ceb4cefc0fb6c (diff) | |
download | chromium_src-b2ef40c775cba50c908f1b72d377a19b8c457b36.zip chromium_src-b2ef40c775cba50c908f1b72d377a19b8c457b36.tar.gz chromium_src-b2ef40c775cba50c908f1b72d377a19b8c457b36.tar.bz2 |
Implement CopyProgressCallback on CopyOrMoveOperationDelegate.
By this CL, FileSystemOperationRunner::Copy starts to support progress callback.
BUG=278038
TEST=Ran content_unittests
Review URL: https://chromiumcodereview.appspot.com/23558011
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@222770 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit')
7 files changed, 205 insertions, 23 deletions
diff --git a/webkit/browser/fileapi/async_file_test_helper.cc b/webkit/browser/fileapi/async_file_test_helper.cc index eaf8441..a6dab38 100644 --- a/webkit/browser/fileapi/async_file_test_helper.cc +++ b/webkit/browser/fileapi/async_file_test_helper.cc @@ -94,10 +94,18 @@ base::PlatformFileError AsyncFileTestHelper::Copy( FileSystemContext* context, const FileSystemURL& src, const FileSystemURL& dest) { + return CopyWithProgress(context, src, dest, CopyProgressCallback()); +} + +base::PlatformFileError AsyncFileTestHelper::CopyWithProgress( + FileSystemContext* context, + const FileSystemURL& src, + const FileSystemURL& dest, + const CopyProgressCallback& progress_callback) { base::PlatformFileError result = base::PLATFORM_FILE_ERROR_FAILED; base::RunLoop run_loop; context->operation_runner()->Copy( - src, dest, FileSystemOperationRunner::CopyProgressCallback(), + src, dest, progress_callback, AssignAndQuitCallback(&run_loop, &result)); run_loop.Run(); return result; diff --git a/webkit/browser/fileapi/async_file_test_helper.h b/webkit/browser/fileapi/async_file_test_helper.h index da27bf2..168400f 100644 --- a/webkit/browser/fileapi/async_file_test_helper.h +++ b/webkit/browser/fileapi/async_file_test_helper.h @@ -23,6 +23,7 @@ class FileSystemURL; class AsyncFileTestHelper { public: typedef FileSystemOperation::FileEntryList FileEntryList; + typedef FileSystemOperation::CopyProgressCallback CopyProgressCallback; static const int64 kDontCheckSize; @@ -31,6 +32,13 @@ class AsyncFileTestHelper { const FileSystemURL& src, const FileSystemURL& dest); + // Same as Copy, but this supports |progress_callback|. + static base::PlatformFileError CopyWithProgress( + FileSystemContext* context, + const FileSystemURL& src, + const FileSystemURL& dest, + const CopyProgressCallback& progress_callback); + // Performs Move from |src| to |dest| and returns the status code. static base::PlatformFileError Move(FileSystemContext* context, const FileSystemURL& src, diff --git a/webkit/browser/fileapi/copy_or_move_operation_delegate.cc b/webkit/browser/fileapi/copy_or_move_operation_delegate.cc index 37e9a93..7634a88 100644 --- a/webkit/browser/fileapi/copy_or_move_operation_delegate.cc +++ b/webkit/browser/fileapi/copy_or_move_operation_delegate.cc @@ -37,11 +37,14 @@ class CopyOrMoveOnSameFileSystemImpl FileSystemOperationRunner* operation_runner, CopyOrMoveOperationDelegate::OperationType operation_type, const FileSystemURL& src_url, - const FileSystemURL& dest_url) + const FileSystemURL& dest_url, + const FileSystemOperation::CopyFileProgressCallback& + file_progress_callback) : operation_runner_(operation_runner), operation_type_(operation_type), src_url_(src_url), - dest_url_(dest_url) { + dest_url_(dest_url), + file_progress_callback_(file_progress_callback) { } virtual void Run( @@ -49,10 +52,8 @@ class CopyOrMoveOnSameFileSystemImpl if (operation_type_ == CopyOrMoveOperationDelegate::OPERATION_MOVE) { operation_runner_->MoveFileLocal(src_url_, dest_url_, callback); } else { - // TODO(hidehiko): Support progress callback. operation_runner_->CopyFileLocal( - src_url_, dest_url_, - FileSystemOperationRunner::CopyFileProgressCallback(), callback); + src_url_, dest_url_, file_progress_callback_, callback); } } @@ -61,6 +62,7 @@ class CopyOrMoveOnSameFileSystemImpl CopyOrMoveOperationDelegate::OperationType operation_type_; FileSystemURL src_url_; FileSystemURL dest_url_; + FileSystemOperation::CopyFileProgressCallback file_progress_callback_; DISALLOW_COPY_AND_ASSIGN(CopyOrMoveOnSameFileSystemImpl); }; @@ -76,17 +78,21 @@ class SnapshotCopyOrMoveImpl CopyOrMoveOperationDelegate::OperationType operation_type, const FileSystemURL& src_url, const FileSystemURL& dest_url, - CopyOrMoveFileValidatorFactory* validator_factory) + 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), validator_factory_(validator_factory), + file_progress_callback_(file_progress_callback), 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, @@ -111,8 +117,8 @@ class SnapshotCopyOrMoveImpl if (!validator_factory_) { // No validation is needed. - RunAfterPreWriteValidation( - platform_path, file_ref, callback, base::PLATFORM_FILE_OK); + RunAfterPreWriteValidation(platform_path, file_info, file_ref, callback, + base::PLATFORM_FILE_OK); return; } @@ -121,11 +127,12 @@ class SnapshotCopyOrMoveImpl platform_path, base::Bind(&SnapshotCopyOrMoveImpl::RunAfterPreWriteValidation, weak_factory_.GetWeakPtr(), - platform_path, file_ref, callback)); + platform_path, file_info, file_ref, callback)); } void RunAfterPreWriteValidation( const base::FilePath& platform_path, + const base::PlatformFileInfo& file_info, const scoped_refptr<webkit_blob::ShareableFileReference>& file_ref, const CopyOrMoveOperationDelegate::StatusCallback& callback, base::PlatformFileError error) { @@ -139,10 +146,11 @@ class SnapshotCopyOrMoveImpl operation_runner_->CopyInForeignFile( platform_path, dest_url_, base::Bind(&SnapshotCopyOrMoveImpl::RunAfterCopyInForeignFile, - weak_factory_.GetWeakPtr(), file_ref, callback)); + weak_factory_.GetWeakPtr(), file_info, file_ref, callback)); } void RunAfterCopyInForeignFile( + const base::PlatformFileInfo& file_info, const scoped_refptr<webkit_blob::ShareableFileReference>& file_ref, const CopyOrMoveOperationDelegate::StatusCallback& callback, base::PlatformFileError error) { @@ -151,6 +159,8 @@ class SnapshotCopyOrMoveImpl return; } + file_progress_callback_.Run(file_info.size); + // |validator_| is NULL when the destination filesystem does not do // validation. if (!validator_) { @@ -265,6 +275,7 @@ class SnapshotCopyOrMoveImpl FileSystemURL dest_url_; CopyOrMoveFileValidatorFactory* validator_factory_; scoped_ptr<CopyOrMoveFileValidator> validator_; + FileSystemOperation::CopyFileProgressCallback file_progress_callback_; base::WeakPtrFactory<SnapshotCopyOrMoveImpl> weak_factory_; DISALLOW_COPY_AND_ASSIGN(SnapshotCopyOrMoveImpl); @@ -278,11 +289,13 @@ CopyOrMoveOperationDelegate::CopyOrMoveOperationDelegate( const FileSystemURL& src_root, const FileSystemURL& dest_root, OperationType operation_type, + const CopyProgressCallback& progress_callback, const StatusCallback& callback) : RecursiveOperationDelegate(file_system_context), src_root_(src_root), dest_root_(dest_root), operation_type_(operation_type), + progress_callback_(progress_callback), callback_(callback), weak_factory_(this) { same_file_system_ = src_root_.IsInSameFileSystem(dest_root_); @@ -312,33 +325,57 @@ void CopyOrMoveOperationDelegate::RunRecursively() { return; } + if (!progress_callback_.is_null()) { + progress_callback_.Run( + FileSystemOperation::BEGIN_COPY_ENTRY, src_root_, 0); + } + // First try to copy/move it as a file. CopyOrMoveFile(src_root_, dest_root_, base::Bind(&CopyOrMoveOperationDelegate::DidTryCopyOrMoveFile, weak_factory_.GetWeakPtr())); } -void CopyOrMoveOperationDelegate::ProcessFile(const FileSystemURL& src_url, - const StatusCallback& callback) { - CopyOrMoveFile(src_url, CreateDestURL(src_url), 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, 0); + + CopyOrMoveFile(src_url, CreateDestURL(src_url), + base::Bind(&CopyOrMoveOperationDelegate::DidCopyEntry, + weak_factory_.GetWeakPtr(), src_url, callback)); } -void CopyOrMoveOperationDelegate::ProcessDirectory(const FileSystemURL& src_url, - const StatusCallback& callback) { +void CopyOrMoveOperationDelegate::ProcessDirectory( + const FileSystemURL& src_url, + const StatusCallback& callback) { FileSystemURL dest_url = CreateDestURL(src_url); + if (!progress_callback_.is_null() && src_url != src_root_) { + // We do not invoke |progress_callback_| for source root, because it is + // already called in RunRecursively(). + progress_callback_.Run(FileSystemOperation::BEGIN_COPY_ENTRY, src_url, 0); + } + // 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 */, callback); + dest_url, false /* exclusive */, false /* recursive */, + base::Bind(&CopyOrMoveOperationDelegate::DidCopyEntry, + weak_factory_.GetWeakPtr(), src_url, callback)); } void CopyOrMoveOperationDelegate::DidTryCopyOrMoveFile( base::PlatformFileError error) { - if (error == base::PLATFORM_FILE_OK || - error != base::PLATFORM_FILE_ERROR_NOT_A_FILE) { + if (error != base::PLATFORM_FILE_ERROR_NOT_A_FILE) { + if (error == base::PLATFORM_FILE_OK && !progress_callback_.is_null()) { + progress_callback_.Run( + FileSystemOperation::END_COPY_ENTRY, src_root_, 0); + } + callback_.Run(error); return; } @@ -408,7 +445,9 @@ void CopyOrMoveOperationDelegate::CopyOrMoveFile( CopyOrMoveImpl* impl = NULL; if (same_file_system_) { impl = new CopyOrMoveOnSameFileSystemImpl( - operation_runner(), operation_type_, src_url, dest_url); + operation_runner(), operation_type_, src_url, dest_url, + base::Bind(&CopyOrMoveOperationDelegate::OnCopyFileProgress, + weak_factory_.GetWeakPtr(), src_url)); } else { // Cross filesystem case. // TODO(hidehiko): Support stream based copy. crbug.com/279287. @@ -423,7 +462,9 @@ void CopyOrMoveOperationDelegate::CopyOrMoveFile( impl = new SnapshotCopyOrMoveImpl( operation_runner(), operation_type_, src_url, dest_url, - validator_factory); + validator_factory, + base::Bind(&CopyOrMoveOperationDelegate::OnCopyFileProgress, + weak_factory_.GetWeakPtr(), src_url)); } // Register the running task. @@ -432,6 +473,16 @@ void CopyOrMoveOperationDelegate::CopyOrMoveFile( weak_factory_.GetWeakPtr(), impl, callback)); } +void CopyOrMoveOperationDelegate::DidCopyEntry( + const FileSystemURL& src_url, + const StatusCallback& callback, + base::PlatformFileError error) { + if (!progress_callback_.is_null() && error == base::PLATFORM_FILE_OK) + progress_callback_.Run(FileSystemOperation::END_COPY_ENTRY, src_url, 0); + + callback.Run(error); +} + void CopyOrMoveOperationDelegate::DidCopyOrMoveFile( CopyOrMoveImpl* impl, const StatusCallback& callback, @@ -441,6 +492,12 @@ void CopyOrMoveOperationDelegate::DidCopyOrMoveFile( callback.Run(error); } +void CopyOrMoveOperationDelegate::OnCopyFileProgress( + const FileSystemURL& src_url, int64 size) { + if (!progress_callback_.is_null()) + progress_callback_.Run(FileSystemOperation::PROGRESS, src_url, size); +} + FileSystemURL CopyOrMoveOperationDelegate::CreateDestURL( const FileSystemURL& src_url) const { DCHECK_EQ(src_root_.type(), src_url.type()); diff --git a/webkit/browser/fileapi/copy_or_move_operation_delegate.h b/webkit/browser/fileapi/copy_or_move_operation_delegate.h index 5f629ca..cb409ce 100644 --- a/webkit/browser/fileapi/copy_or_move_operation_delegate.h +++ b/webkit/browser/fileapi/copy_or_move_operation_delegate.h @@ -24,6 +24,7 @@ class CopyOrMoveOperationDelegate : public RecursiveOperationDelegate { public: class CopyOrMoveImpl; + typedef FileSystemOperation::CopyProgressCallback CopyProgressCallback; enum OperationType { OPERATION_COPY, @@ -35,6 +36,7 @@ class CopyOrMoveOperationDelegate const FileSystemURL& src_root, const FileSystemURL& dest_root, OperationType operation_type, + const CopyProgressCallback& progress_callback, const StatusCallback& callback); virtual ~CopyOrMoveOperationDelegate(); @@ -55,6 +57,11 @@ class CopyOrMoveOperationDelegate void DidRemoveSourceForMove(const StatusCallback& callback, base::PlatformFileError error); + void DidCopyEntry(const FileSystemURL& src_url, + const StatusCallback& callback, + base::PlatformFileError error); + void OnCopyFileProgress(const FileSystemURL& src_url, int64 size); + // Starts Copy (or Move based on |operation_type_|) from |src_url| to // |dest_url|. Upon completion |callback| is invoked. // This can be run for multiple files in parallel. @@ -71,6 +78,7 @@ class CopyOrMoveOperationDelegate FileSystemURL dest_root_; bool same_file_system_; OperationType operation_type_; + CopyProgressCallback progress_callback_; StatusCallback callback_; std::set<CopyOrMoveImpl*> running_copy_set_; diff --git a/webkit/browser/fileapi/copy_or_move_operation_delegate_unittest.cc b/webkit/browser/fileapi/copy_or_move_operation_delegate_unittest.cc index 183becd..fa2314d 100644 --- a/webkit/browser/fileapi/copy_or_move_operation_delegate_unittest.cc +++ b/webkit/browser/fileapi/copy_or_move_operation_delegate_unittest.cc @@ -93,6 +93,24 @@ class TestValidatorFactory : public CopyOrMoveFileValidatorFactory { }; }; +// Records CopyProgressCallback invocations. +struct ProgressRecord { + FileSystemOperation::CopyProgressType type; + FileSystemURL url; + int64 size; +}; + +void RecordProgressCallback(std::vector<ProgressRecord>* records, + FileSystemOperation::CopyProgressType type, + const FileSystemURL& url, + int64 size) { + ProgressRecord record; + record.type = type; + record.url = url; + record.size = size; + records->push_back(record); +} + } // namespace class CopyOrMoveOperationTestHelper { @@ -194,6 +212,14 @@ class CopyOrMoveOperationTestHelper { return AsyncFileTestHelper::Copy(file_system_context_.get(), src, dest); } + base::PlatformFileError CopyWithProgress( + const FileSystemURL& src, + const FileSystemURL& dest, + const AsyncFileTestHelper::CopyProgressCallback& progress_callback) { + return AsyncFileTestHelper::CopyWithProgress( + file_system_context_.get(), src, dest, progress_callback); + } + base::PlatformFileError Move(const FileSystemURL& src, const FileSystemURL& dest) { return AsyncFileTestHelper::Move(file_system_context_.get(), src, dest); @@ -453,7 +479,10 @@ TEST(LocalFileSystemCopyOrMoveOperationTest, CopyDirectory) { int64 src_increase = helper.GetSourceUsage() - src_initial_usage; // Copy it. - ASSERT_EQ(base::PLATFORM_FILE_OK, helper.Copy(src, dest)); + ASSERT_EQ(base::PLATFORM_FILE_OK, + helper.CopyWithProgress( + src, dest, + AsyncFileTestHelper::CopyProgressCallback())); // Verify. ASSERT_TRUE(helper.DirectoryExists(src)); @@ -559,4 +588,71 @@ TEST(LocalFileSystemCopyOrMoveOperationTest, CopySingleFileNoValidator) { ASSERT_EQ(base::PLATFORM_FILE_ERROR_SECURITY, helper.Copy(src, dest)); } +TEST(LocalFileSystemCopyOrMoveOperationTest, ProgressCallback) { + CopyOrMoveOperationTestHelper helper(GURL("http://foo"), + kFileSystemTypeTemporary, + kFileSystemTypePersistent); + helper.SetUp(); + + FileSystemURL src = helper.SourceURL("a"); + FileSystemURL dest = helper.DestURL("b"); + + // Set up a source directory. + ASSERT_EQ(base::PLATFORM_FILE_OK, helper.CreateDirectory(src)); + ASSERT_EQ(base::PLATFORM_FILE_OK, + helper.SetUpTestCaseFiles(src, + test::kRegularTestCases, + test::kRegularTestCaseSize)); + + std::vector<ProgressRecord> records; + ASSERT_EQ(base::PLATFORM_FILE_OK, + helper.CopyWithProgress(src, dest, + base::Bind(&RecordProgressCallback, + base::Unretained(&records)))); + + // Verify progress callback. + for (size_t i = 0; i < test::kRegularTestCaseSize; ++i) { + const test::TestCaseRecord& test_case = test::kRegularTestCases[i]; + + FileSystemURL src_url = + helper.SourceURL( + std::string("a/") + base::FilePath(test_case.path).AsUTF8Unsafe()); + + // Find the first and last progress record. + size_t begin_index = records.size(); + size_t end_index = records.size(); + for (size_t j = 0; j < records.size(); ++j) { + if (records[j].url == src_url) { + if (begin_index == records.size()) + begin_index = j; + end_index = j; + } + } + + // The record should be found. + ASSERT_NE(begin_index, records.size()); + ASSERT_NE(end_index, records.size()); + ASSERT_NE(begin_index, end_index); + + EXPECT_EQ(FileSystemOperation::BEGIN_COPY_ENTRY, + records[begin_index].type); + EXPECT_EQ(FileSystemOperation::END_COPY_ENTRY, records[end_index].type); + + if (test_case.is_directory) { + // For directory copy, the progress shouldn't be interlaced. + EXPECT_EQ(begin_index + 1, end_index); + } else { + // PROGRESS event's size should be assending order. + int64 current_size = 0; + for (size_t j = begin_index + 1; j < end_index; ++j) { + if (records[j].url == src_url) { + EXPECT_EQ(FileSystemOperation::PROGRESS, records[j].type); + EXPECT_GE(records[j].size, current_size); + current_size = records[j].size; + } + } + } + } +} + } // namespace fileapi diff --git a/webkit/browser/fileapi/file_system_operation_impl.cc b/webkit/browser/fileapi/file_system_operation_impl.cc index 5b1c228..a4c60e4 100644 --- a/webkit/browser/fileapi/file_system_operation_impl.cc +++ b/webkit/browser/fileapi/file_system_operation_impl.cc @@ -80,6 +80,7 @@ void FileSystemOperationImpl::Copy( file_system_context(), src_url, dest_url, CopyOrMoveOperationDelegate::OPERATION_COPY, + progress_callback, base::Bind(&FileSystemOperationImpl::DidFinishOperation, weak_factory_.GetWeakPtr(), callback))); recursive_operation_delegate_->RunRecursively(); @@ -95,6 +96,7 @@ void FileSystemOperationImpl::Move(const FileSystemURL& src_url, file_system_context(), src_url, dest_url, CopyOrMoveOperationDelegate::OPERATION_MOVE, + FileSystemOperation::CopyProgressCallback(), base::Bind(&FileSystemOperationImpl::DidFinishOperation, weak_factory_.GetWeakPtr(), callback))); recursive_operation_delegate_->RunRecursively(); @@ -284,7 +286,6 @@ void FileSystemOperationImpl::CopyFileLocal( DCHECK(SetPendingOperationType(kOperationCopy)); DCHECK(src_url.IsInSameFileSystem(dest_url)); - // TODO(hidehiko): Support progress_callback. GetUsageAndQuotaThenRunTask( dest_url, base::Bind(&FileSystemOperationImpl::DoCopyFileLocal, diff --git a/webkit/browser/fileapi/file_system_url.h b/webkit/browser/fileapi/file_system_url.h index 36b862e..d6443e6 100644 --- a/webkit/browser/fileapi/file_system_url.h +++ b/webkit/browser/fileapi/file_system_url.h @@ -130,6 +130,10 @@ class WEBKIT_STORAGE_BROWSER_EXPORT FileSystemURL { bool operator==(const FileSystemURL& that) const; + bool operator!=(const FileSystemURL& that) const { + return !(*this == that); + } + struct WEBKIT_STORAGE_BROWSER_EXPORT Comparator { bool operator() (const FileSystemURL& lhs, const FileSystemURL& rhs) const; }; |