diff options
author | kkanetkar@chromium.org <kkanetkar@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-09-16 04:46:14 +0000 |
---|---|---|
committer | kkanetkar@chromium.org <kkanetkar@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-09-16 04:46:14 +0000 |
commit | f05ca65c8857804c078f06b260f3175493dd4720 (patch) | |
tree | f3d22e6412bf18bf9597729d91c468c4846ab598 | |
parent | 88dd4bc31fbce0e6cfe7612ba3fccd08407c1cb2 (diff) | |
download | chromium_src-f05ca65c8857804c078f06b260f3175493dd4720.zip chromium_src-f05ca65c8857804c078f06b260f3175493dd4720.tar.gz chromium_src-f05ca65c8857804c078f06b260f3175493dd4720.tar.bz2 |
Test shell impl for WebKit's File System API:BUG=52799TEST=none
Also refactored a bunch of code from chrome/browser to webkit/fileapi for reuse.
Added class hierarchy. Test shell and browser operations now inherit from
common webkit/fileapi/file_system_operation.
Review URL: http://codereview.chromium.org/3186009
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@59616 0039d316-1c4b-4281-b951-d872f2087c98
19 files changed, 1037 insertions, 103 deletions
diff --git a/chrome/DEPS b/chrome/DEPS index e38a2f8..1fe3cbd 100644 --- a/chrome/DEPS +++ b/chrome/DEPS @@ -29,6 +29,9 @@ include_rules = [ # Allow inclusion of the database library. "+webkit/database", + # Allow inclusion of the fileapi library. + "+webkit/fileapi", + # Allow Apple code ImageAndTextCell. "+third_party/apple", diff --git a/chrome/browser/file_system/chrome_file_system_operation.cc b/chrome/browser/file_system/chrome_file_system_operation.cc new file mode 100644 index 0000000..020aa3e --- /dev/null +++ b/chrome/browser/file_system/chrome_file_system_operation.cc @@ -0,0 +1,14 @@ +// Copyright (c) 2010 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 "chrome/browser/file_system/chrome_file_system_operation.h" + +#include "chrome/browser/chrome_thread.h" + +ChromeFileSystemOperation::ChromeFileSystemOperation( + int request_id, fileapi::FileSystemOperationClient* client) + : fileapi::FileSystemOperation(client, + ChromeThread::GetMessageLoopProxyForThread(ChromeThread::FILE)), + request_id_(request_id) { } + diff --git a/chrome/browser/file_system/chrome_file_system_operation.h b/chrome/browser/file_system/chrome_file_system_operation.h new file mode 100644 index 0000000..33d61ca --- /dev/null +++ b/chrome/browser/file_system/chrome_file_system_operation.h @@ -0,0 +1,28 @@ +// Copyright (c) 2010 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. + +#ifndef CHROME_BROWSER_FILE_SYSTEM_CHROME_FILE_SYSTEM_OPERATION_H_ +#define CHROME_BROWSER_FILE_SYSTEM_CHROME_FILE_SYSTEM_OPERATION_H_ + +#include "webkit/fileapi/file_system_operation.h" + +// This class is designed to serve one-time file system operation per instance. +// Each operation method (CreateFile, CreateDirectory, Copy, Move, +// DirectoryExists, GetMetadata, ReadDirectory and Remove) must be called +// only once in its lifetime. +class ChromeFileSystemOperation : public fileapi::FileSystemOperation { + public: + ChromeFileSystemOperation( + int request_id, fileapi::FileSystemOperationClient* client); + + int request_id() const { return request_id_; } + + private: + int request_id_; + + DISALLOW_COPY_AND_ASSIGN(ChromeFileSystemOperation); +}; + +#endif // CHROME_BROWSER_FILE_SYSTEM_CHROME_FILE_SYSTEM_OPERATION_H_ + diff --git a/chrome/browser/file_system/chrome_file_system_operation_unittest.cc b/chrome/browser/file_system/chrome_file_system_operation_unittest.cc new file mode 100644 index 0000000..57ca164 --- /dev/null +++ b/chrome/browser/file_system/chrome_file_system_operation_unittest.cc @@ -0,0 +1,571 @@ +// Copyright (c) 2010 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 "chrome/browser/file_system/chrome_file_system_operation.h" + +#include "base/logging.h" +#include "base/rand_util.h" +#include "base/scoped_ptr.h" +#include "base/scoped_temp_dir.h" +#include "chrome/browser/chrome_thread.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/WebKit/WebKit/chromium/public/WebFileError.h" +#include "webkit/fileapi/file_system_operation_client.h" + +namespace { +int kInvalidRequestId = -1; +int kFileOperationStatusNotSet = 0; +int kFileOperationSucceeded = 1; +} + +using fileapi::FileSystemOperation; + +bool FileExists(FilePath path) { + return file_util::PathExists(path) && !file_util::DirectoryExists(path); +} + +class MockClient: public fileapi::FileSystemOperationClient { + public: + MockClient() + : status_(kFileOperationStatusNotSet), + request_id_(kInvalidRequestId) { + } + + ~MockClient() {} + + virtual void DidFail(WebKit::WebFileError status, + FileSystemOperation* operation) { + status_ = status; + request_id_ = + static_cast<ChromeFileSystemOperation*>(operation)->request_id(); + } + + virtual void DidSucceed(FileSystemOperation* operation) { + status_ = kFileOperationSucceeded; + request_id_ = + static_cast<ChromeFileSystemOperation*>(operation)->request_id(); + } + + virtual void DidReadMetadata( + const base::PlatformFileInfo& info, + FileSystemOperation* operation) { + info_ = info; + request_id_ = + static_cast<ChromeFileSystemOperation*>(operation)->request_id(); + } + + virtual void DidReadDirectory( + const std::vector<base::file_util_proxy::Entry>& entries, + bool has_more, + FileSystemOperation* operation) { + entries_ = entries; + request_id_ = + static_cast<ChromeFileSystemOperation*>(operation)->request_id(); + } + + // Helpers for testing. + int status() const { return status_; } + int request_id() const { return request_id_; } + const base::PlatformFileInfo& info() const { return info_; } + const std::vector<base::file_util_proxy::Entry>& entries() const { + return entries_; + } + + private: + int status_; + int request_id_; + base::PlatformFileInfo info_; + std::vector<base::file_util_proxy::Entry> entries_; +}; + +class ChromeFileSystemOperationTest : public testing::Test { + public: + ChromeFileSystemOperationTest() + : ui_thread_(ChromeThread::UI, &loop_), + file_thread_(ChromeThread::FILE, &loop_) { + base_.CreateUniqueTempDir(); + } + + protected: + virtual void SetUp() { + mock_client_.reset(new MockClient()); + current_request_id_ = kInvalidRequestId; + ASSERT_TRUE(base_.IsValid()); + } + + // Returns a new operation pointer that is created each time it's called. + // The pointer is owned by the test class. + ChromeFileSystemOperation* operation() { + current_request_id_ = base::RandInt(0, kint32max); + operation_.reset(new ChromeFileSystemOperation( + current_request_id_, mock_client_.get())); + return operation_.get(); + } + + scoped_ptr<MockClient> mock_client_; + int current_request_id_; + + MessageLoop loop_; + ChromeThread ui_thread_; + ChromeThread file_thread_; + + // Common temp base for all non-existing file/dir path test cases. + // This is in case a dir on test machine exists. It's better to + // create temp and then create non-existing file paths under it. + ScopedTempDir base_; + + private: + scoped_ptr<ChromeFileSystemOperation> operation_; + + DISALLOW_COPY_AND_ASSIGN(ChromeFileSystemOperationTest); +}; + +TEST_F(ChromeFileSystemOperationTest, TestMoveFailureSrcDoesntExist) { + FilePath src(base_.path().Append(FILE_PATH_LITERAL("a"))); + FilePath dest(base_.path().Append(FILE_PATH_LITERAL("b"))); + operation()->Move(src, dest); + loop_.RunAllPending(); + EXPECT_EQ(WebKit::WebFileErrorNotFound, mock_client_->status()); + EXPECT_EQ(current_request_id_, mock_client_->request_id()); +} + + +TEST_F(ChromeFileSystemOperationTest, TestMoveFailureContainsPath) { + FilePath file_under_base = base_.path().Append(FILE_PATH_LITERAL("b")); + operation()->Move(base_.path(), file_under_base); + loop_.RunAllPending(); + EXPECT_EQ(WebKit::WebFileErrorInvalidModification, mock_client_->status()); + EXPECT_EQ(current_request_id_, mock_client_->request_id()); +} + +TEST_F(ChromeFileSystemOperationTest, TestMoveFailureSrcDirExistsDestFile) { + // Src exists and is dir. Dest is a file. + ScopedTempDir dest_dir; + ASSERT_TRUE(dest_dir.CreateUniqueTempDir()); + FilePath dest_file; + file_util::CreateTemporaryFileInDir(dest_dir.path(), &dest_file); + + operation()->Move(base_.path(), dest_file); + loop_.RunAllPending(); + EXPECT_EQ(mock_client_->status(), WebKit::WebFileErrorInvalidModification); + EXPECT_EQ(current_request_id_, mock_client_->request_id()); +} + +TEST_F(ChromeFileSystemOperationTest, TestMoveFailureDestParentDoesntExist) { + // Dest. parent path does not exist. + ScopedTempDir src_dir; + ASSERT_TRUE(src_dir.CreateUniqueTempDir()); + FilePath nonexisting(base_.path().Append(FILE_PATH_LITERAL("DontExistDir"))); + FilePath nonexisting_file = nonexisting.Append( + FILE_PATH_LITERAL("DontExistFile")); + + operation()->Move(src_dir.path(), nonexisting_file); + loop_.RunAllPending(); + EXPECT_EQ(mock_client_->status(), WebKit::WebFileErrorNotFound); + EXPECT_EQ(current_request_id_, mock_client_->request_id()); +} + +TEST_F(ChromeFileSystemOperationTest, TestMoveSuccessSrcFileAndOverwrite) { + ScopedTempDir src_dir; + ASSERT_TRUE(src_dir.CreateUniqueTempDir()); + FilePath src_file; + file_util::CreateTemporaryFileInDir(src_dir.path(), &src_file); + + ScopedTempDir dest_dir; + ASSERT_TRUE(dest_dir.CreateUniqueTempDir()); + FilePath dest_file; + file_util::CreateTemporaryFileInDir(dest_dir.path(), &dest_file); + + operation()->Move(src_file, dest_file); + loop_.RunAllPending(); + EXPECT_EQ(kFileOperationSucceeded, mock_client_->status()); + EXPECT_TRUE(FileExists(dest_file)); + EXPECT_EQ(current_request_id_, mock_client_->request_id()); +} + +TEST_F(ChromeFileSystemOperationTest, TestMoveSuccessSrcFileAndNew) { + ScopedTempDir src_dir; + ASSERT_TRUE(src_dir.CreateUniqueTempDir()); + FilePath src_file; + file_util::CreateTemporaryFileInDir(src_dir.path(), &src_file); + + ScopedTempDir dest_dir; + ASSERT_TRUE(dest_dir.CreateUniqueTempDir()); + FilePath dest_file(dest_dir.path().Append(FILE_PATH_LITERAL("NewFile"))); + + operation()->Move(src_file, dest_file); + loop_.RunAllPending(); + EXPECT_EQ(kFileOperationSucceeded, mock_client_->status()); + EXPECT_TRUE(FileExists(dest_file)); + EXPECT_EQ(current_request_id_, mock_client_->request_id()); +} + +TEST_F(ChromeFileSystemOperationTest, TestCopyFailureSrcDoesntExist) { + FilePath src(base_.path().Append(FILE_PATH_LITERAL("a"))); + FilePath dest(base_.path().Append(FILE_PATH_LITERAL("b"))); + operation()->Copy(src, dest); + loop_.RunAllPending(); + EXPECT_EQ(WebKit::WebFileErrorNotFound, mock_client_->status()); + EXPECT_EQ(current_request_id_, mock_client_->request_id()); +} + +TEST_F(ChromeFileSystemOperationTest, TestCopyFailureContainsPath) { + FilePath file_under_base = base_.path().Append(FILE_PATH_LITERAL("b")); + operation()->Copy(base_.path(), file_under_base); + loop_.RunAllPending(); + EXPECT_EQ(WebKit::WebFileErrorInvalidModification, mock_client_->status()); + EXPECT_EQ(current_request_id_, mock_client_->request_id()); +} + +TEST_F(ChromeFileSystemOperationTest, TestCopyFailureSrcDirExistsDestFile) { + // Src exists and is dir. Dest is a file. + ScopedTempDir dir; + ASSERT_TRUE(dir.CreateUniqueTempDir()); + FilePath dest_file; + file_util::CreateTemporaryFileInDir(dir.path(), &dest_file); + + operation()->Copy(base_.path(), dest_file); + loop_.RunAllPending(); + EXPECT_EQ(mock_client_->status(), WebKit::WebFileErrorInvalidModification); + EXPECT_EQ(current_request_id_, mock_client_->request_id()); +} + +TEST_F(ChromeFileSystemOperationTest, TestCopyFailureDestParentDoesntExist) { + // Dest. parent path does not exist. + ScopedTempDir dir; + ASSERT_TRUE(dir.CreateUniqueTempDir()); + FilePath src_dir = dir.path(); + + FilePath nonexisting(base_.path().Append(FILE_PATH_LITERAL("DontExistDir"))); + file_util::EnsureEndsWithSeparator(&nonexisting); + FilePath nonexisting_file = nonexisting.Append( + FILE_PATH_LITERAL("DontExistFile")); + + operation()->Copy(src_dir, nonexisting_file); + loop_.RunAllPending(); + EXPECT_EQ(mock_client_->status(), WebKit::WebFileErrorNotFound); + EXPECT_EQ(current_request_id_, mock_client_->request_id()); +} + +TEST_F(ChromeFileSystemOperationTest, TestCopySuccessSrcFileAndOverwrite) { + ScopedTempDir src_dir; + ASSERT_TRUE(src_dir.CreateUniqueTempDir()); + FilePath src_file; + file_util::CreateTemporaryFileInDir(src_dir.path(), &src_file); + + ScopedTempDir dest_dir; + ASSERT_TRUE(dest_dir.CreateUniqueTempDir()); + FilePath dest_file; + file_util::CreateTemporaryFileInDir(dest_dir.path(), &dest_file); + + operation()->Copy(src_file, dest_file); + loop_.RunAllPending(); + EXPECT_EQ(kFileOperationSucceeded, mock_client_->status()); + EXPECT_TRUE(FileExists(dest_file)); + EXPECT_EQ(current_request_id_, mock_client_->request_id()); +} + +TEST_F(ChromeFileSystemOperationTest, TestCopySuccessSrcFileAndNew) { + ScopedTempDir src_dir; + ASSERT_TRUE(src_dir.CreateUniqueTempDir()); + FilePath src_file; + file_util::CreateTemporaryFileInDir(src_dir.path(), &src_file); + + ScopedTempDir dest_dir; + ASSERT_TRUE(dest_dir.CreateUniqueTempDir()); + FilePath dest_file(dest_dir.path().Append(FILE_PATH_LITERAL("NewFile"))); + + operation()->Copy(src_file, dest_file); + loop_.RunAllPending(); + EXPECT_EQ(kFileOperationSucceeded, mock_client_->status()); + EXPECT_TRUE(FileExists(dest_file)); + EXPECT_EQ(current_request_id_, mock_client_->request_id()); +} + +TEST_F(ChromeFileSystemOperationTest, TestCopySuccessSrcDir) { + ScopedTempDir src_dir; + ASSERT_TRUE(src_dir.CreateUniqueTempDir()); + + ScopedTempDir dest_dir; + ASSERT_TRUE(dest_dir.CreateUniqueTempDir()); + + operation()->Copy(src_dir.path(), dest_dir.path()); + loop_.RunAllPending(); + EXPECT_EQ(kFileOperationSucceeded, mock_client_->status()); + EXPECT_EQ(current_request_id_, mock_client_->request_id()); +} + +TEST_F(ChromeFileSystemOperationTest, TestCopyDestParentExistsSuccess) { + ScopedTempDir src_dir; + ASSERT_TRUE(src_dir.CreateUniqueTempDir()); + FilePath src_file; + file_util::CreateTemporaryFileInDir(src_dir.path(), &src_file); + + ScopedTempDir dest_dir; + ASSERT_TRUE(dest_dir.CreateUniqueTempDir()); + + operation()->Copy(src_file, dest_dir.path()); + loop_.RunAllPending(); + EXPECT_EQ(kFileOperationSucceeded, mock_client_->status()); + EXPECT_EQ(current_request_id_, mock_client_->request_id()); + + FilePath src_filename(src_file.BaseName()); + EXPECT_TRUE(FileExists(dest_dir.path().Append(src_filename))); +} + +TEST_F(ChromeFileSystemOperationTest, TestCreateFileFailure) { + // Already existing file and exclusive true. + ScopedTempDir dir; + ASSERT_TRUE(dir.CreateUniqueTempDir()); + FilePath file; + + file_util::CreateTemporaryFileInDir(dir.path(), &file); + operation()->CreateFile(file, true); + loop_.RunAllPending(); + EXPECT_EQ(mock_client_->status(), WebKit::WebFileErrorInvalidModification); + EXPECT_EQ(current_request_id_, mock_client_->request_id()); +} + +TEST_F(ChromeFileSystemOperationTest, TestCreateFileSuccessFileExists) { + // Already existing file and exclusive false. + ScopedTempDir dir; + ASSERT_TRUE(dir.CreateUniqueTempDir()); + FilePath file; + file_util::CreateTemporaryFileInDir(dir.path(), &file); + + operation()->CreateFile(file, false); + loop_.RunAllPending(); + EXPECT_EQ(kFileOperationSucceeded, mock_client_->status()); + EXPECT_TRUE(FileExists(file)); + EXPECT_EQ(current_request_id_, mock_client_->request_id()); +} + +TEST_F(ChromeFileSystemOperationTest, TestCreateFileSuccessExclusive) { + // File doesn't exist but exclusive is true. + ScopedTempDir dir; + ASSERT_TRUE(dir.CreateUniqueTempDir()); + FilePath file = dir.path().Append(FILE_PATH_LITERAL("FileDoesntExist")); + operation()->CreateFile(file, true); + loop_.RunAllPending(); + EXPECT_EQ(kFileOperationSucceeded, mock_client_->status()); + EXPECT_TRUE(FileExists(file)); + EXPECT_EQ(current_request_id_, mock_client_->request_id()); +} + +TEST_F(ChromeFileSystemOperationTest, TestCreateFileSuccessFileDoesntExist) { + // Non existing file. + ScopedTempDir dir; + ASSERT_TRUE(dir.CreateUniqueTempDir()); + FilePath file = dir.path().Append(FILE_PATH_LITERAL("FileDoesntExist")); + operation()->CreateFile(file, false); + loop_.RunAllPending(); + EXPECT_EQ(kFileOperationSucceeded, mock_client_->status()); + EXPECT_EQ(current_request_id_, mock_client_->request_id()); +} + +TEST_F(ChromeFileSystemOperationTest, + TestCreateDirFailureDestParentDoesntExist) { + // Dest. parent path does not exist. + FilePath nonexisting(base_.path().Append( + FILE_PATH_LITERAL("DirDoesntExist"))); + file_util::EnsureEndsWithSeparator(&nonexisting); + FilePath nonexisting_file = nonexisting.Append( + FILE_PATH_LITERAL("FileDoesntExist")); + operation()->CreateDirectory(nonexisting_file, false); + loop_.RunAllPending(); + EXPECT_EQ(WebKit::WebFileErrorNotFound, mock_client_->status()); + EXPECT_EQ(current_request_id_, mock_client_->request_id()); +} + +TEST_F(ChromeFileSystemOperationTest, TestCreateDirFailureDirExists) { + // Exclusive and dir existing at path. + operation()->CreateDirectory(base_.path(), true); + loop_.RunAllPending(); + EXPECT_EQ(WebKit::WebFileErrorInvalidModification, mock_client_->status()); + EXPECT_EQ(current_request_id_, mock_client_->request_id()); +} + +TEST_F(ChromeFileSystemOperationTest, TestCreateDirFailureFileExists) { + // Exclusive true and file existing at path. + ScopedTempDir dir; + ASSERT_TRUE(dir.CreateUniqueTempDir()); + FilePath file; + file_util::CreateTemporaryFileInDir(dir.path(), &file); + operation()->CreateDirectory(file, true); + loop_.RunAllPending(); + EXPECT_EQ(mock_client_->status(), + WebKit::WebFileErrorInvalidModification); + EXPECT_EQ(current_request_id_, mock_client_->request_id()); +} + +TEST_F(ChromeFileSystemOperationTest, TestCreateDirSuccess) { + // Dir exists and exclusive is false. + ScopedTempDir dir; + ASSERT_TRUE(dir.CreateUniqueTempDir()); + operation()->CreateDirectory(dir.path(), false); + loop_.RunAllPending(); + EXPECT_EQ(kFileOperationSucceeded, mock_client_->status()); + EXPECT_EQ(current_request_id_, mock_client_->request_id()); + + // Dir doesn't exist. + FilePath nonexisting_dir_path(FILE_PATH_LITERAL("nonexistingdir")); + operation()->CreateDirectory(nonexisting_dir_path, false); + loop_.RunAllPending(); + EXPECT_EQ(kFileOperationSucceeded, mock_client_->status()); + EXPECT_TRUE(file_util::DirectoryExists(nonexisting_dir_path)); + EXPECT_EQ(current_request_id_, mock_client_->request_id()); +} + +TEST_F(ChromeFileSystemOperationTest, TestCreateDirSuccessExclusive) { + // Dir doesn't exist. + ScopedTempDir dir; + ASSERT_TRUE(dir.CreateUniqueTempDir()); + FilePath nonexisting_dir_path(dir.path().Append( + FILE_PATH_LITERAL("nonexistingdir"))); + + operation()->CreateDirectory(nonexisting_dir_path, true); + loop_.RunAllPending(); + EXPECT_EQ(kFileOperationSucceeded, mock_client_->status()); + EXPECT_TRUE(file_util::DirectoryExists(nonexisting_dir_path)); + EXPECT_EQ(current_request_id_, mock_client_->request_id()); +} + +TEST_F(ChromeFileSystemOperationTest, TestExistsAndMetadataFailure) { + FilePath nonexisting_dir_path(base_.path().Append( + FILE_PATH_LITERAL("nonexistingdir"))); + operation()->GetMetadata(nonexisting_dir_path); + loop_.RunAllPending(); + EXPECT_EQ(WebKit::WebFileErrorNotFound, mock_client_->status()); + + operation()->FileExists(nonexisting_dir_path); + loop_.RunAllPending(); + EXPECT_EQ(WebKit::WebFileErrorNotFound, mock_client_->status()); + EXPECT_EQ(current_request_id_, mock_client_->request_id()); + + file_util::EnsureEndsWithSeparator(&nonexisting_dir_path); + operation()->DirectoryExists(nonexisting_dir_path); + loop_.RunAllPending(); + EXPECT_EQ(WebKit::WebFileErrorNotFound, mock_client_->status()); + EXPECT_EQ(current_request_id_, mock_client_->request_id()); +} + +TEST_F(ChromeFileSystemOperationTest, TestExistsAndMetadataSuccess) { + ScopedTempDir dir; + ASSERT_TRUE(dir.CreateUniqueTempDir()); + + operation()->DirectoryExists(dir.path()); + loop_.RunAllPending(); + EXPECT_EQ(kFileOperationSucceeded, mock_client_->status()); + EXPECT_EQ(current_request_id_, mock_client_->request_id()); + + operation()->GetMetadata(dir.path()); + loop_.RunAllPending(); + EXPECT_EQ(kFileOperationSucceeded, mock_client_->status()); + EXPECT_TRUE(mock_client_->info().is_directory); + EXPECT_EQ(current_request_id_, mock_client_->request_id()); + + FilePath file; + file_util::CreateTemporaryFileInDir(dir.path(), &file); + operation()->FileExists(file); + loop_.RunAllPending(); + EXPECT_EQ(kFileOperationSucceeded, mock_client_->status()); + EXPECT_EQ(current_request_id_, mock_client_->request_id()); + + operation()->GetMetadata(file); + loop_.RunAllPending(); + EXPECT_EQ(kFileOperationSucceeded, mock_client_->status()); + EXPECT_FALSE(mock_client_->info().is_directory); + EXPECT_EQ(current_request_id_, mock_client_->request_id()); +} + +TEST_F(ChromeFileSystemOperationTest, TestReadDirFailure) { + // Path doesn't exists + FilePath nonexisting_dir_path(base_.path().Append( + FILE_PATH_LITERAL("NonExistingDir"))); + file_util::EnsureEndsWithSeparator(&nonexisting_dir_path); + operation()->ReadDirectory(nonexisting_dir_path); + loop_.RunAllPending(); + EXPECT_EQ(WebKit::WebFileErrorNotFound, mock_client_->status()); + EXPECT_EQ(current_request_id_, mock_client_->request_id()); + + // File exists. + ScopedTempDir dir; + ASSERT_TRUE(dir.CreateUniqueTempDir()); + FilePath file; + file_util::CreateTemporaryFileInDir(dir.path(), &file); + operation()->ReadDirectory(file); + loop_.RunAllPending(); + // TODO(kkanetkar) crbug.com/54309 to change the error code. + EXPECT_EQ(WebKit::WebFileErrorNotFound, mock_client_->status()); + EXPECT_EQ(current_request_id_, mock_client_->request_id()); +} + +TEST_F(ChromeFileSystemOperationTest, TestReadDirSuccess) { + // parent_dir + // | | + // child_dir child_file + // Verify reading parent_dir. + ScopedTempDir parent_dir; + ASSERT_TRUE(parent_dir.CreateUniqueTempDir()); + FilePath child_file; + file_util::CreateTemporaryFileInDir(parent_dir.path(), &child_file); + FilePath child_dir; + ASSERT_TRUE(file_util::CreateTemporaryDirInDir(parent_dir.path(), + FILE_PATH_LITERAL("child_dir"), &child_dir)); + + operation()->ReadDirectory(parent_dir.path()); + loop_.RunAllPending(); + EXPECT_EQ(kFileOperationStatusNotSet, mock_client_->status()); + EXPECT_EQ(2u, mock_client_->entries().size()); + EXPECT_EQ(current_request_id_, mock_client_->request_id()); + + for (size_t i = 0; i < mock_client_->entries().size(); ++i) { + if (mock_client_->entries()[i].is_directory) + EXPECT_EQ(child_dir.BaseName().value(), mock_client_->entries()[i].name); + else + EXPECT_EQ(child_file.BaseName().value(), mock_client_->entries()[i].name); + } +} + +TEST_F(ChromeFileSystemOperationTest, TestRemoveFailure) { + // Path doesn't exist. + FilePath nonexisting(base_.path().Append( + FILE_PATH_LITERAL("NonExistingDir"))); + file_util::EnsureEndsWithSeparator(&nonexisting); + + operation()->Remove(nonexisting); + loop_.RunAllPending(); + EXPECT_EQ(WebKit::WebFileErrorNotFound, mock_client_->status()); + EXPECT_EQ(current_request_id_, mock_client_->request_id()); + + // By spec recursive is always false. Non-empty dir should fail. + // parent_dir + // | | + // child_dir child_file + // Verify deleting parent_dir. + ScopedTempDir parent_dir; + ASSERT_TRUE(parent_dir.CreateUniqueTempDir()); + FilePath child_file; + file_util::CreateTemporaryFileInDir(parent_dir.path(), &child_file); + FilePath child_dir; + ASSERT_TRUE(file_util::CreateTemporaryDirInDir(parent_dir.path(), + FILE_PATH_LITERAL("child_dir"), &child_dir)); + + operation()->Remove(parent_dir.path()); + loop_.RunAllPending(); + EXPECT_EQ(WebKit::WebFileErrorInvalidModification, mock_client_->status()); + EXPECT_EQ(current_request_id_, mock_client_->request_id()); +} + +TEST_F(ChromeFileSystemOperationTest, TestRemoveSuccess) { + ScopedTempDir empty_dir; + ASSERT_TRUE(empty_dir.CreateUniqueTempDir()); + EXPECT_TRUE(file_util::DirectoryExists(empty_dir.path())); + + operation()->Remove(empty_dir.path()); + loop_.RunAllPending(); + EXPECT_EQ(kFileOperationSucceeded, mock_client_->status()); + EXPECT_FALSE(file_util::DirectoryExists(empty_dir.path())); + EXPECT_EQ(current_request_id_, mock_client_->request_id()); +} diff --git a/chrome/browser/file_system/file_system_dispatcher_host.cc b/chrome/browser/file_system/file_system_dispatcher_host.cc index e7bf5d8..16e8795 100644 --- a/chrome/browser/file_system/file_system_dispatcher_host.cc +++ b/chrome/browser/file_system/file_system_dispatcher_host.cc @@ -221,25 +221,37 @@ void FileSystemDispatcherHost::OnReadDirectory( } void FileSystemDispatcherHost::DidFail( - WebKit::WebFileError status, int request_id) { + WebKit::WebFileError status, + fileapi::FileSystemOperation* operation) { + int request_id = + static_cast<ChromeFileSystemOperation*>(operation)->request_id(); Send(new ViewMsg_FileSystem_DidFail(request_id, status)); operations_.Remove(request_id); } -void FileSystemDispatcherHost::DidSucceed(int request_id) { +void FileSystemDispatcherHost::DidSucceed( + fileapi::FileSystemOperation* operation) { + int request_id = + static_cast<ChromeFileSystemOperation*>(operation)->request_id(); Send(new ViewMsg_FileSystem_DidSucceed(request_id)); operations_.Remove(request_id); } void FileSystemDispatcherHost::DidReadMetadata( - const base::PlatformFileInfo& info, int request_id) { + const base::PlatformFileInfo& info, + fileapi::FileSystemOperation* operation) { + int request_id = + static_cast<ChromeFileSystemOperation*>(operation)->request_id(); Send(new ViewMsg_FileSystem_DidReadMetadata(request_id, info)); operations_.Remove(request_id); } void FileSystemDispatcherHost::DidReadDirectory( const std::vector<base::file_util_proxy::Entry>& entries, - bool has_more, int request_id) { + bool has_more, + fileapi::FileSystemOperation* operation) { + int request_id = + static_cast<ChromeFileSystemOperation*>(operation)->request_id(); ViewMsg_FileSystem_DidReadDirectory_Params params; params.request_id = request_id; params.entries = entries; @@ -268,10 +280,10 @@ bool FileSystemDispatcherHost::CheckValidFileSystemPath( return true; } -FileSystemOperation* FileSystemDispatcherHost::GetNewOperation( +ChromeFileSystemOperation* FileSystemDispatcherHost::GetNewOperation( int request_id) { - scoped_ptr<FileSystemOperation> operation( - new FileSystemOperation(request_id, this)); + scoped_ptr<ChromeFileSystemOperation> operation( + new ChromeFileSystemOperation(request_id, this)); operations_.AddWithID(operation.get(), request_id); return operation.release(); } diff --git a/chrome/browser/file_system/file_system_dispatcher_host.h b/chrome/browser/file_system/file_system_dispatcher_host.h index 64fd73c..fff7108 100644 --- a/chrome/browser/file_system/file_system_dispatcher_host.h +++ b/chrome/browser/file_system/file_system_dispatcher_host.h @@ -13,9 +13,9 @@ #include "base/platform_file.h" #include "base/scoped_callback_factory.h" #include "base/ref_counted.h" -#include "chrome/browser/file_system/file_system_operation.h" -#include "chrome/browser/file_system/file_system_operation_client.h" +#include "chrome/browser/file_system/chrome_file_system_operation.h" #include "chrome/common/render_messages.h" +#include "webkit/fileapi/file_system_operation_client.h" class FileSystemHostContext; class HostContentSettingsMap; @@ -24,7 +24,7 @@ class ResourceMessageFilter; class FileSystemDispatcherHost : public base::RefCountedThreadSafe<FileSystemDispatcherHost>, - public FileSystemOperationClient { + public fileapi::FileSystemOperationClient { public: FileSystemDispatcherHost(IPC::Message::Sender* sender, FileSystemHostContext* file_system_host_context, @@ -64,19 +64,19 @@ class FileSystemDispatcherHost void Send(IPC::Message* message); // FileSystemOperationClient methods. - virtual void DidFail(WebKit::WebFileError status, int request_id); - virtual void DidSucceed(int request_id); + virtual void DidFail(WebKit::WebFileError status, + fileapi::FileSystemOperation* operation); + virtual void DidSucceed(fileapi::FileSystemOperation* operation); virtual void DidReadMetadata( const base::PlatformFileInfo& info, - int request_id); + fileapi::FileSystemOperation* operation); virtual void DidReadDirectory( const std::vector<base::file_util_proxy::Entry>& entries, - bool has_more, - int request_id); + bool has_more, fileapi::FileSystemOperation* operation); private: - // Creates a new FileSystemOperation. - FileSystemOperation* GetNewOperation(int request_id); + // Creates a new ChromeFileSystemOperation. + ChromeFileSystemOperation* GetNewOperation(int request_id); // Checks the validity of a given |path|. Returns true if the given |path| // is valid as a path for FileSystem API. Otherwise it sends back a @@ -97,7 +97,7 @@ class FileSystemDispatcherHost scoped_refptr<HostContentSettingsMap> host_content_settings_map_; // Keeps ongoing file system operations. - typedef IDMap<FileSystemOperation, IDMapOwnPointer> OperationsMap; + typedef IDMap<ChromeFileSystemOperation, IDMapOwnPointer> OperationsMap; OperationsMap operations_; DISALLOW_COPY_AND_ASSIGN(FileSystemDispatcherHost); diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index f2b675f..81196b1 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -40,6 +40,7 @@ '../webkit/support/webkit_support.gyp:appcache', '../webkit/support/webkit_support.gyp:blob', '../webkit/support/webkit_support.gyp:database', + '../webkit/support/webkit_support.gyp:fileapi', '../webkit/support/webkit_support.gyp:glue', '../webkit/support/webkit_support.gyp:webkit_resources', ], @@ -1526,13 +1527,12 @@ 'browser/file_path_watcher_win.cc', 'browser/file_select_helper.cc', 'browser/file_select_helper.h', + 'browser/file_system/chrome_file_system_operation.cc', + 'browser/file_system/chrome_file_system_operation.h', 'browser/file_system/file_system_dispatcher_host.cc', 'browser/file_system/file_system_dispatcher_host.h', 'browser/file_system/file_system_host_context.cc', 'browser/file_system/file_system_host_context.h', - 'browser/file_system/file_system_operation.cc', - 'browser/file_system/file_system_operation.h', - 'browser/file_system/file_system_operation_client.h', 'browser/find_bar.h', 'browser/find_bar_controller.cc', 'browser/find_bar_controller.h', diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi index 114dcec..2e251e7 100644 --- a/chrome/chrome_tests.gypi +++ b/chrome/chrome_tests.gypi @@ -1070,7 +1070,7 @@ 'browser/extensions/user_script_listener_unittest.cc', 'browser/extensions/user_script_master_unittest.cc', 'browser/file_path_watcher_unittest.cc', - 'browser/file_system/file_system_operation_unittest.cc', + 'browser/file_system/chrome_file_system_operation_unittest.cc', 'browser/file_system/file_system_host_context_unittest.cc', 'browser/find_backend_unittest.cc', 'browser/first_run/first_run_unittest.cc', diff --git a/chrome/browser/file_system/file_system_operation.cc b/webkit/fileapi/file_system_operation.cc index bdd0fb3..90eabad 100644 --- a/chrome/browser/file_system/file_system_operation.cc +++ b/webkit/fileapi/file_system_operation.cc @@ -2,15 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/file_system/file_system_operation.h" +#include "webkit/fileapi/file_system_operation.h" -#include "chrome/browser/chrome_thread.h" -#include "chrome/browser/file_system/file_system_operation_client.h" +#include "webkit/fileapi/file_system_operation_client.h" #include "third_party/WebKit/WebKit/chromium/public/WebFileError.h" namespace { // Utility method for error conversions. -WebKit::WebFileError PlatformToWebkitError(base::PlatformFileError rv) { +WebKit::WebFileError PlatformFileErrorToWebFileError( + base::PlatformFileError rv) { switch (rv) { case base::PLATFORM_FILE_ERROR_NOT_FOUND: return WebKit::WebFileErrorNotFound; @@ -26,10 +26,13 @@ WebKit::WebFileError PlatformToWebkitError(base::PlatformFileError rv) { } } // namespace +namespace fileapi { + FileSystemOperation::FileSystemOperation( - int request_id, FileSystemOperationClient* client) - : client_(client), - request_id_(request_id), + FileSystemOperationClient* client, + scoped_refptr<base::MessageLoopProxy> proxy) + : proxy_(proxy), + client_(client), callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)), operation_pending_(false) { DCHECK(client_); @@ -40,8 +43,7 @@ void FileSystemOperation::CreateFile(const FilePath& path, DCHECK(!operation_pending_); operation_pending_ = true; base::FileUtilProxy::CreateOrOpen( - ChromeThread::GetMessageLoopProxyForThread(ChromeThread::FILE), - path, base::PLATFORM_FILE_CREATE | base::PLATFORM_FILE_READ, + proxy_, path, base::PLATFORM_FILE_CREATE | base::PLATFORM_FILE_READ, callback_factory_.NewCallback( exclusive ? &FileSystemOperation::DidCreateFileExclusive : &FileSystemOperation::DidCreateFileNonExclusive)); @@ -51,10 +53,8 @@ void FileSystemOperation::CreateDirectory(const FilePath& path, bool exclusive) { DCHECK(!operation_pending_); operation_pending_ = true; - base::FileUtilProxy::CreateDirectory( - ChromeThread::GetMessageLoopProxyForThread( - ChromeThread::FILE), path, exclusive, false, /* recursive */ - callback_factory_.NewCallback( + base::FileUtilProxy::CreateDirectory(proxy_, path, exclusive, + false /* recursive */, callback_factory_.NewCallback( &FileSystemOperation::DidFinishFileOperation)); } @@ -62,72 +62,54 @@ void FileSystemOperation::Copy(const FilePath& src_path, const FilePath& dest_path) { DCHECK(!operation_pending_); operation_pending_ = true; - base::FileUtilProxy::Copy( - ChromeThread::GetMessageLoopProxyForThread( - ChromeThread::FILE), src_path, dest_path, - callback_factory_.NewCallback( - &FileSystemOperation::DidFinishFileOperation)); + base::FileUtilProxy::Copy(proxy_, src_path, dest_path, + callback_factory_.NewCallback( + &FileSystemOperation::DidFinishFileOperation)); } void FileSystemOperation::Move(const FilePath& src_path, const FilePath& dest_path) { DCHECK(!operation_pending_); operation_pending_ = true; - base::FileUtilProxy::Move( - ChromeThread::GetMessageLoopProxyForThread( - ChromeThread::FILE), src_path, dest_path, - callback_factory_.NewCallback( - &FileSystemOperation::DidFinishFileOperation)); + base::FileUtilProxy::Move(proxy_, src_path, dest_path, + callback_factory_.NewCallback( + &FileSystemOperation::DidFinishFileOperation)); } void FileSystemOperation::DirectoryExists(const FilePath& path) { DCHECK(!operation_pending_); operation_pending_ = true; - base::FileUtilProxy::GetFileInfo( - ChromeThread::GetMessageLoopProxyForThread( - ChromeThread::FILE), - path, callback_factory_.NewCallback( - &FileSystemOperation::DidDirectoryExists)); + base::FileUtilProxy::GetFileInfo(proxy_, path, callback_factory_.NewCallback( + &FileSystemOperation::DidDirectoryExists)); } void FileSystemOperation::FileExists(const FilePath& path) { DCHECK(!operation_pending_); operation_pending_ = true; - base::FileUtilProxy::GetFileInfo( - ChromeThread::GetMessageLoopProxyForThread( - ChromeThread::FILE), path, - callback_factory_.NewCallback( - &FileSystemOperation::DidFileExists)); + base::FileUtilProxy::GetFileInfo(proxy_, path, callback_factory_.NewCallback( + &FileSystemOperation::DidFileExists)); } void FileSystemOperation::GetMetadata(const FilePath& path) { DCHECK(!operation_pending_); operation_pending_ = true; - base::FileUtilProxy::GetFileInfo( - ChromeThread::GetMessageLoopProxyForThread( - ChromeThread::FILE), path, - callback_factory_.NewCallback( - &FileSystemOperation::DidGetMetadata)); + base::FileUtilProxy::GetFileInfo(proxy_, path, callback_factory_.NewCallback( + &FileSystemOperation::DidGetMetadata)); } void FileSystemOperation::ReadDirectory(const FilePath& path) { DCHECK(!operation_pending_); operation_pending_ = true; - base::FileUtilProxy::ReadDirectory( - ChromeThread::GetMessageLoopProxyForThread( - ChromeThread::FILE), path, - callback_factory_.NewCallback( - &FileSystemOperation::DidReadDirectory)); + base::FileUtilProxy::ReadDirectory(proxy_, path, + callback_factory_.NewCallback( + &FileSystemOperation::DidReadDirectory)); } void FileSystemOperation::Remove(const FilePath& path) { DCHECK(!operation_pending_); operation_pending_ = true; - base::FileUtilProxy::Delete( - ChromeThread::GetMessageLoopProxyForThread( - ChromeThread::FILE), path, - callback_factory_.NewCallback( - &FileSystemOperation::DidFinishFileOperation)); + base::FileUtilProxy::Delete(proxy_, path, callback_factory_.NewCallback( + &FileSystemOperation::DidFinishFileOperation)); } void FileSystemOperation::DidCreateFileExclusive( @@ -141,20 +123,20 @@ void FileSystemOperation::DidCreateFileNonExclusive( base::PlatformFileError rv, base::PassPlatformFile file, bool created) { - // Supress the already exists error and report success. + // Suppress the already exists error and report success. if (rv == base::PLATFORM_FILE_OK || rv == base::PLATFORM_FILE_ERROR_EXISTS) - client_->DidSucceed(request_id_); + client_->DidSucceed(this); else - client_->DidFail(PlatformToWebkitError(rv), request_id_); + client_->DidFail(PlatformFileErrorToWebFileError(rv), this); } void FileSystemOperation::DidFinishFileOperation( base::PlatformFileError rv) { if (rv == base::PLATFORM_FILE_OK) - client_->DidSucceed(request_id_); + client_->DidSucceed(this); else - client_->DidFail(PlatformToWebkitError(rv), request_id_); + client_->DidFail(PlatformFileErrorToWebFileError(rv), this); } void FileSystemOperation::DidDirectoryExists( @@ -162,13 +144,13 @@ void FileSystemOperation::DidDirectoryExists( const base::PlatformFileInfo& file_info) { if (rv == base::PLATFORM_FILE_OK) { if (file_info.is_directory) - client_->DidSucceed(request_id_); + client_->DidSucceed(this); else client_->DidFail(WebKit::WebFileErrorInvalidState, - request_id_); + this); } else { // Something else went wrong. - client_->DidFail(PlatformToWebkitError(rv), request_id_); + client_->DidFail(PlatformFileErrorToWebFileError(rv), this); } } @@ -178,12 +160,12 @@ void FileSystemOperation::DidFileExists( if (rv == base::PLATFORM_FILE_OK) { if (file_info.is_directory) client_->DidFail(WebKit::WebFileErrorInvalidState, - request_id_); + this); else - client_->DidSucceed(request_id_); + client_->DidSucceed(this); } else { // Something else went wrong. - client_->DidFail(PlatformToWebkitError(rv), request_id_); + client_->DidFail(PlatformFileErrorToWebFileError(rv), this); } } @@ -191,9 +173,9 @@ void FileSystemOperation::DidGetMetadata( base::PlatformFileError rv, const base::PlatformFileInfo& file_info) { if (rv == base::PLATFORM_FILE_OK) - client_->DidReadMetadata(file_info, request_id_); + client_->DidReadMetadata(file_info, this); else - client_->DidFail(PlatformToWebkitError(rv), request_id_); + client_->DidFail(PlatformFileErrorToWebFileError(rv), this); } void FileSystemOperation::DidReadDirectory( @@ -201,7 +183,10 @@ void FileSystemOperation::DidReadDirectory( const std::vector<base::file_util_proxy::Entry>& entries) { if (rv == base::PLATFORM_FILE_OK) client_->DidReadDirectory( - entries, false /* has_more */ , request_id_); + entries, false /* has_more */ , this); else - client_->DidFail(PlatformToWebkitError(rv), request_id_); + client_->DidFail(PlatformFileErrorToWebFileError(rv), this); } + +} // namespace fileapi + diff --git a/chrome/browser/file_system/file_system_operation.h b/webkit/fileapi/file_system_operation.h index 0a901ee..f9431c9 100644 --- a/chrome/browser/file_system/file_system_operation.h +++ b/webkit/fileapi/file_system_operation.h @@ -2,25 +2,31 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_FILE_SYSTEM_FILE_SYSTEM_OPERATION_H_ -#define CHROME_BROWSER_FILE_SYSTEM_FILE_SYSTEM_OPERATION_H_ +#ifndef WEBKIT_FILEAPI_FILE_SYSTEM_OPERATION_H_ +#define WEBKIT_FILEAPI_FILE_SYSTEM_OPERATION_H_ #include <vector> #include "base/file_path.h" #include "base/file_util_proxy.h" +#include "base/message_loop_proxy.h" #include "base/platform_file.h" +#include "base/ref_counted.h" #include "base/scoped_callback_factory.h" +namespace fileapi { + class FileSystemOperationClient; // This class is designed to serve one-time file system operation per instance. // Each operation method (CreateFile, CreateDirectory, Copy, Move, -// DIrectoryExists, GetMetadata, ReadDirectory and Remove) must be called +// DirectoryExists, GetMetadata, ReadDirectory and Remove) must be called // only once in its lifetime. class FileSystemOperation { public: - FileSystemOperation(int request_id, FileSystemOperationClient* client); + FileSystemOperation( + FileSystemOperationClient* client, + scoped_refptr<base::MessageLoopProxy> proxy); void CreateFile(const FilePath& path, bool exclusive); @@ -32,8 +38,8 @@ class FileSystemOperation { const FilePath& dest_path); // If |dest_path| exists and is a directory, behavior is unspecified or - // varies for different platforms. - // TODO(kkanetkar): Add more checks. + // varies for different platforms. TODO(kkanetkar): Fix this as per spec + // when it is addressed in spec. void Move(const FilePath& src_path, const FilePath& dest_path); @@ -47,6 +53,10 @@ class FileSystemOperation { void Remove(const FilePath& path); + protected: + // Proxy for calling file_util_proxy methods. + scoped_refptr<base::MessageLoopProxy> proxy_; + private: // Callbacks for above methods. void DidCreateFileExclusive( @@ -75,9 +85,6 @@ class FileSystemOperation { // Not owned. FileSystemOperationClient* client_; - // Client's request id. - int request_id_; - base::ScopedCallbackFactory<FileSystemOperation> callback_factory_; // A flag to make sure we call operation only once per instance. @@ -86,4 +93,7 @@ class FileSystemOperation { DISALLOW_COPY_AND_ASSIGN(FileSystemOperation); }; -#endif // CHROME_BROWSER_FILE_SYSTEM_FILE_SYSTEM_OPERATION_H_ +} // namespace fileapi + +#endif // WEBKIT_FILEAPI_FILE_SYSTEM_OPERATION_H_ + diff --git a/chrome/browser/file_system/file_system_operation_client.h b/webkit/fileapi/file_system_operation_client.h index 3cd31c5..b126d4e 100644 --- a/chrome/browser/file_system/file_system_operation_client.h +++ b/webkit/fileapi/file_system_operation_client.h @@ -2,32 +2,38 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_FILE_SYSTEM_FILE_SYSTEM_OPERATION_CLIENT_H_ -#define CHROME_BROWSER_FILE_SYSTEM_FILE_SYSTEM_OPERATION_CLIENT_H_ +#ifndef WEBKIT_FILEAPI_FILE_SYSTEM_OPERATION_CLIENT_H_ +#define WEBKIT_FILEAPI_FILE_SYSTEM_OPERATION_CLIENT_H_ #include <vector> #include "base/file_util_proxy.h" #include "third_party/WebKit/WebKit/chromium/public/WebFileError.h" +namespace fileapi { + +class FileSystemOperation; + // Interface for client of FileSystemOperation. class FileSystemOperationClient { public: virtual ~FileSystemOperationClient() {} - virtual void DidFail(WebKit::WebFileError status, int request_id) = 0; + virtual void DidFail( + WebKit::WebFileError status, + FileSystemOperation* operation) = 0; - virtual void DidSucceed(int request_id) = 0; + virtual void DidSucceed(FileSystemOperation* operation) = 0; // Info about the file entry such as modification date and size. virtual void DidReadMetadata(const base::PlatformFileInfo& info, - int request_id) = 0; + FileSystemOperation* operation) = 0; virtual void DidReadDirectory( const std::vector<base::file_util_proxy::Entry>& entries, - bool has_more, - int request_id) = 0; + bool has_more, FileSystemOperation* operation) = 0; }; -#endif // CHROME_BROWSER_FILE_SYSTEM_FILE_SYSTEM_OPERATION_CLIENT_H_ +} // namespace fileapi +#endif // WEBKIT_FILEAPI_FILE_SYSTEM_OPERATION_CLIENT_H_ diff --git a/webkit/fileapi/webkit_fileapi.gypi b/webkit/fileapi/webkit_fileapi.gypi new file mode 100644 index 0000000..cce29cc --- /dev/null +++ b/webkit/fileapi/webkit_fileapi.gypi @@ -0,0 +1,31 @@ +# Copyright (c) 2010 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. + +{ + 'targets': [ + { + 'target_name': 'fileapi', + 'type': '<(library)', + 'msvs_guid': '40B53211-03ED-4932-8D53-52B172599DFE', + 'dependencies': [ + '<(DEPTH)/app/app.gyp:app_base', + '<(DEPTH)/base/base.gyp:base', + '<(DEPTH)/net/net.gyp:net', + ], + 'sources': [ + 'file_system_operation.cc', + 'file_system_operation.h', + 'file_system_operation_client.h', + ], + 'conditions': [ + ['inside_chromium_build==0', { + 'dependencies': [ + '<(DEPTH)/webkit/support/setup_third_party.gyp:third_party_headers', + ], + }], + ], + }, + ], +} + diff --git a/webkit/support/test_webkit_client.cc b/webkit/support/test_webkit_client.cc index cb176b1..9bc8692 100644 --- a/webkit/support/test_webkit_client.cc +++ b/webkit/support/test_webkit_client.cc @@ -14,6 +14,7 @@ #include "media/base/media.h" #include "third_party/WebKit/WebKit/chromium/public/WebData.h" #include "third_party/WebKit/WebKit/chromium/public/WebDatabase.h" +#include "third_party/WebKit/WebKit/chromium/public/WebFileSystem.h" #include "third_party/WebKit/WebKit/chromium/public/WebGraphicsContext3D.h" #include "third_party/WebKit/WebKit/chromium/public/WebIDBFactory.h" #include "third_party/WebKit/WebKit/chromium/public/WebRuntimeFeatures.h" @@ -39,6 +40,7 @@ #include "webkit/tools/test_shell/mock_webclipboard_impl.h" #include "webkit/tools/test_shell/simple_appcache_system.h" #include "webkit/tools/test_shell/simple_database_system.h" +#include "webkit/tools/test_shell/simple_file_system.h" #include "webkit/tools/test_shell/simple_resource_loader_bridge.h" #include "webkit/tools/test_shell/simple_webcookiejar_impl.h" #include "webkit/tools/test_shell/test_shell_request_context.h" @@ -158,6 +160,10 @@ WebKit::WebBlobRegistry* TestWebKitClient::blobRegistry() { return blob_registry_.get(); } +WebKit::WebFileSystem* TestWebKitClient::fileSystem() { + return &file_system_; +} + bool TestWebKitClient::sandboxEnabled() { return true; } diff --git a/webkit/support/test_webkit_client.h b/webkit/support/test_webkit_client.h index 8a0b3a4..e7b2805 100644 --- a/webkit/support/test_webkit_client.h +++ b/webkit/support/test_webkit_client.h @@ -11,6 +11,7 @@ #include "webkit/tools/test_shell/mock_webclipboard_impl.h" #include "webkit/tools/test_shell/simple_appcache_system.h" #include "webkit/tools/test_shell/simple_database_system.h" +#include "webkit/tools/test_shell/simple_file_system.h" #include "webkit/tools/test_shell/simple_webcookiejar_impl.h" #include "webkit/tools/test_shell/test_shell_webmimeregistry_impl.h" @@ -28,6 +29,7 @@ class TestWebKitClient : public webkit_glue::WebKitClientImpl { virtual WebKit::WebSandboxSupport* sandboxSupport(); virtual WebKit::WebCookieJar* cookieJar(); virtual WebKit::WebBlobRegistry* blobRegistry(); + virtual WebKit::WebFileSystem* fileSystem(); virtual bool sandboxEnabled(); virtual WebKit::WebKitClient::FileHandle databaseOpenFile( @@ -76,6 +78,7 @@ class TestWebKitClient : public webkit_glue::WebKitClientImpl { SimpleDatabaseSystem database_system_; SimpleWebCookieJarImpl cookie_jar_; scoped_refptr<TestShellWebBlobRegistryImpl> blob_registry_; + SimpleFileSystem file_system_; WebURLLoaderMockFactory url_loader_factory_; bool unit_test_mode_; diff --git a/webkit/support/webkit_support.gyp b/webkit/support/webkit_support.gyp index 0de6dcb..7fab468 100644 --- a/webkit/support/webkit_support.gyp +++ b/webkit/support/webkit_support.gyp @@ -6,6 +6,7 @@ 'includes': [ '../appcache/webkit_appcache.gypi', '../blob/webkit_blob.gypi', + '../fileapi/webkit_fileapi.gypi', '../database/webkit_database.gypi', '../glue/webkit_glue.gypi', # TODO(tkent): Merge npapi_layout_test_plugin into TestNetscapePlugIn diff --git a/webkit/support/webkit_support.gypi b/webkit/support/webkit_support.gypi index 2aa5d6a..99c8ae0 100644 --- a/webkit/support/webkit_support.gypi +++ b/webkit/support/webkit_support.gypi @@ -18,6 +18,7 @@ 'appcache', 'blob', 'database', + 'fileapi', 'glue', ], 'include_dirs': [ @@ -51,6 +52,8 @@ '<(DEPTH)/webkit/tools/test_shell/mock_webclipboard_impl.h', '<(DEPTH)/webkit/tools/test_shell/simple_appcache_system.cc', '<(DEPTH)/webkit/tools/test_shell/simple_appcache_system.h', + '<(DEPTH)/webkit/tools/test_shell/simple_file_system.cc', + '<(DEPTH)/webkit/tools/test_shell/simple_file_system.h', '<(DEPTH)/webkit/tools/test_shell/simple_clipboard_impl.cc', '<(DEPTH)/webkit/tools/test_shell/simple_database_system.cc', '<(DEPTH)/webkit/tools/test_shell/simple_database_system.h', diff --git a/webkit/tools/test_shell/simple_file_system.cc b/webkit/tools/test_shell/simple_file_system.cc new file mode 100644 index 0000000..11da52c --- /dev/null +++ b/webkit/tools/test_shell/simple_file_system.cc @@ -0,0 +1,160 @@ +// Copyright (c) 2010 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/tools/test_shell/simple_file_system.h" + +#include "base/file_path.h" +#include "base/message_loop_proxy.h" +#include "base/time.h" +#include "third_party/WebKit/WebKit/chromium/public/WebFileInfo.h" +#include "third_party/WebKit/WebKit/chromium/public/WebFileSystemEntry.h" +#include "third_party/WebKit/WebKit/chromium/public/WebVector.h" +#include "webkit/glue/webkit_glue.h" + +using WebKit::WebFileSystemCallbacks; +using WebKit::WebString; + +TestShellFileSystemOperation::TestShellFileSystemOperation( + fileapi::FileSystemOperationClient* client, + scoped_refptr<base::MessageLoopProxy> proxy, + WebFileSystemCallbacks* callbacks) + : fileapi::FileSystemOperation(client, proxy), callbacks_(callbacks) { } + +SimpleFileSystem::~SimpleFileSystem() { + // Drop all the operations. + for (OperationsMap::const_iterator iter(&operations_); + !iter.IsAtEnd(); iter.Advance()) { + operations_.Remove(iter.GetCurrentKey()); + } +} + +void SimpleFileSystem::move( + const WebString& src_path, + const WebString& dest_path, WebFileSystemCallbacks* callbacks) { + FilePath dest_filepath(webkit_glue::WebStringToFilePath(dest_path)); + FilePath src_filepath(webkit_glue::WebStringToFilePath(src_path)); + + GetNewOperation(callbacks)->Move(src_filepath, dest_filepath); +} + +void SimpleFileSystem::copy( + const WebString& src_path, const WebString& dest_path, + WebFileSystemCallbacks* callbacks) { + FilePath dest_filepath(webkit_glue::WebStringToFilePath(dest_path)); + FilePath src_filepath(webkit_glue::WebStringToFilePath(src_path)); + + GetNewOperation(callbacks)->Copy(src_filepath, dest_filepath); +} + +void SimpleFileSystem::remove( + const WebString& path, WebFileSystemCallbacks* callbacks) { + FilePath filepath(webkit_glue::WebStringToFilePath(path)); + + GetNewOperation(callbacks)->Remove(filepath); +} + +void SimpleFileSystem::getMetadata( + const WebString& path, WebFileSystemCallbacks* callbacks) { + FilePath filepath(webkit_glue::WebStringToFilePath(path)); + + GetNewOperation(callbacks)->GetMetadata(filepath); +} + +void SimpleFileSystem::createFile( + const WebString& path, bool exclusive, WebFileSystemCallbacks* callbacks) { + FilePath filepath(webkit_glue::WebStringToFilePath(path)); + + GetNewOperation(callbacks)->CreateFile(filepath, exclusive); +} + +void SimpleFileSystem::createDirectory( + const WebString& path, bool exclusive, WebFileSystemCallbacks* callbacks) { + FilePath filepath(webkit_glue::WebStringToFilePath(path)); + + GetNewOperation(callbacks)->CreateDirectory(filepath, exclusive); +} + +void SimpleFileSystem::fileExists( + const WebString& path, WebFileSystemCallbacks* callbacks) { + FilePath filepath(webkit_glue::WebStringToFilePath(path)); + + GetNewOperation(callbacks)->FileExists(filepath); +} + +void SimpleFileSystem::directoryExists( + const WebString& path, WebFileSystemCallbacks* callbacks) { + FilePath filepath(webkit_glue::WebStringToFilePath(path)); + + GetNewOperation(callbacks)->DirectoryExists(filepath); +} + +void SimpleFileSystem::readDirectory( + const WebString& path, WebFileSystemCallbacks* callbacks) { + FilePath filepath(webkit_glue::WebStringToFilePath(path)); + + GetNewOperation(callbacks)->ReadDirectory(filepath); +} + +void SimpleFileSystem::DidFail(WebKit::WebFileError status, + fileapi::FileSystemOperation* operation) { + WebFileSystemCallbacks* callbacks = + static_cast<TestShellFileSystemOperation*>(operation)->callbacks(); + callbacks->didFail(status); + RemoveOperation(operation); +} + +void SimpleFileSystem::DidSucceed(fileapi::FileSystemOperation* operation) { + WebFileSystemCallbacks* callbacks = + static_cast<TestShellFileSystemOperation*>(operation)->callbacks(); + callbacks->didSucceed(); + RemoveOperation(operation); +} + +void SimpleFileSystem::DidReadMetadata( + const base::PlatformFileInfo& info, + fileapi::FileSystemOperation* operation) { + WebFileSystemCallbacks* callbacks = + static_cast<TestShellFileSystemOperation*>(operation)->callbacks(); + WebKit::WebFileInfo web_file_info; + web_file_info.modificationTime = info.last_modified.ToDoubleT(); + callbacks->didReadMetadata(web_file_info); + RemoveOperation(operation); +} + +void SimpleFileSystem::DidReadDirectory( + const std::vector<base::file_util_proxy::Entry>& entries, + bool has_more, fileapi::FileSystemOperation* operation) { + WebFileSystemCallbacks* callbacks = + static_cast<TestShellFileSystemOperation*>(operation)->callbacks(); + std::vector<WebKit::WebFileSystemEntry> web_entries_vector; + for (std::vector<base::file_util_proxy::Entry>::const_iterator it = + entries.begin(); it != entries.end(); ++it) { + WebKit::WebFileSystemEntry entry; + entry.name = webkit_glue::FilePathStringToWebString(it->name); + entry.isDirectory = it->is_directory; + web_entries_vector.push_back(entry); + } + WebKit::WebVector<WebKit::WebFileSystemEntry> web_entries = + web_entries_vector; + callbacks->didReadDirectory(web_entries, false); + RemoveOperation(operation); +} + +TestShellFileSystemOperation* SimpleFileSystem::GetNewOperation( + WebFileSystemCallbacks* callbacks) { + scoped_ptr<TestShellFileSystemOperation> operation( + new TestShellFileSystemOperation( + this, + base::MessageLoopProxy::CreateForCurrentThread(), callbacks)); + int32 request_id = operations_.Add(operation.get()); + operation->set_request_id(request_id); + return operation.release(); +} + +void SimpleFileSystem::RemoveOperation( + fileapi::FileSystemOperation* operation) { + int request_id = static_cast<TestShellFileSystemOperation*>( + operation)->request_id(); + operations_.Remove(request_id); +} diff --git a/webkit/tools/test_shell/simple_file_system.h b/webkit/tools/test_shell/simple_file_system.h new file mode 100644 index 0000000..b3487c6 --- /dev/null +++ b/webkit/tools/test_shell/simple_file_system.h @@ -0,0 +1,95 @@ +// Copyright (c) 2010 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. + +#ifndef WEBKIT_TOOLS_TEST_SHELL_SIMPLE_FILE_SYSTEM_H_ +#define WEBKIT_TOOLS_TEST_SHELL_SIMPLE_FILE_SYSTEM_H_ + +#include <vector> +#include "base/file_util_proxy.h" +#include "base/id_map.h" +#include "base/message_loop_proxy.h" +#include "base/platform_file.h" +#include "third_party/WebKit/WebKit/chromium/public/WebFileSystem.h" +#include "third_party/WebKit/WebKit/chromium/public/WebFileSystemCallbacks.h" +#include "webkit/fileapi/file_system_operation.h" +#include "webkit/fileapi/file_system_operation_client.h" + +class TestShellFileSystemOperation : public fileapi::FileSystemOperation { + public: + TestShellFileSystemOperation( + fileapi::FileSystemOperationClient* client, + scoped_refptr<base::MessageLoopProxy> proxy, + WebKit::WebFileSystemCallbacks* callbacks); + + WebKit::WebFileSystemCallbacks* callbacks() { return callbacks_; } + + void set_request_id(int request_id) { request_id_ = request_id; } + int request_id() { return request_id_; } + + private: + // Not owned. + WebKit::WebFileSystemCallbacks* callbacks_; + + // Just for IDMap of operations. + int request_id_; + + DISALLOW_COPY_AND_ASSIGN(TestShellFileSystemOperation); +}; + +class SimpleFileSystem + : public WebKit::WebFileSystem, + public fileapi::FileSystemOperationClient { + public: + SimpleFileSystem() {} + virtual ~SimpleFileSystem(); + + // WebKit::WebFileSystem methods. + virtual void move(const WebKit::WebString& src_path, + const WebKit::WebString& dest_path, + WebKit::WebFileSystemCallbacks* callbacks); + virtual void copy(const WebKit::WebString& src_path, + const WebKit::WebString& dest_path, + WebKit::WebFileSystemCallbacks* callbacks); + virtual void remove(const WebKit::WebString& path, + WebKit::WebFileSystemCallbacks* callbacks); + virtual void getMetadata(const WebKit::WebString& path, + WebKit::WebFileSystemCallbacks* callbacks); + virtual void createFile(const WebKit::WebString& path, bool exclusive, + WebKit::WebFileSystemCallbacks* callbacks); + virtual void createDirectory(const WebKit::WebString& path, bool exclusive, + WebKit::WebFileSystemCallbacks* callbacks); + virtual void fileExists(const WebKit::WebString& path, + WebKit::WebFileSystemCallbacks* callbacks); + virtual void directoryExists(const WebKit::WebString& path, + WebKit::WebFileSystemCallbacks* callbacks); + virtual void readDirectory(const WebKit::WebString& path, + WebKit::WebFileSystemCallbacks* callbacks); + + // FileSystemOperationClient methods. + virtual void DidFail(WebKit::WebFileError status, + fileapi::FileSystemOperation* operation); + virtual void DidSucceed(fileapi::FileSystemOperation* operation); + virtual void DidReadMetadata( + const base::PlatformFileInfo& info, + fileapi::FileSystemOperation* operation); + virtual void DidReadDirectory( + const std::vector<base::file_util_proxy::Entry>& entries, + bool has_more, fileapi::FileSystemOperation* operation); + + private: + // Helpers. + TestShellFileSystemOperation* GetNewOperation( + WebKit::WebFileSystemCallbacks* callbacks); + + void RemoveOperation(fileapi::FileSystemOperation* operation); + + // Keeps ongoing file system operations. + typedef IDMap<TestShellFileSystemOperation, IDMapOwnPointer> OperationsMap; + OperationsMap operations_; + + DISALLOW_COPY_AND_ASSIGN(SimpleFileSystem); +}; + +#endif // WEBKIT_TOOLS_TEST_SHELL_SIMPLE_FILE_SYSTEM_H_ + diff --git a/webkit/tools/test_shell/test_shell_webkit_init.h b/webkit/tools/test_shell/test_shell_webkit_init.h index 459c253..08468c9 100644 --- a/webkit/tools/test_shell/test_shell_webkit_init.h +++ b/webkit/tools/test_shell/test_shell_webkit_init.h @@ -19,6 +19,7 @@ #include "webkit/tools/test_shell/mock_webclipboard_impl.h" #include "webkit/tools/test_shell/simple_appcache_system.h" #include "webkit/tools/test_shell/simple_database_system.h" +#include "webkit/tools/test_shell/simple_file_system.h" #include "webkit/tools/test_shell/simple_resource_loader_bridge.h" #include "webkit/tools/test_shell/simple_webcookiejar_impl.h" #include "webkit/tools/test_shell/test_shell_webblobregistry_impl.h" @@ -55,6 +56,10 @@ class TestShellWebKitInit : public webkit_glue::WebKitClientImpl { return blob_registry_.get(); } + virtual WebKit::WebFileSystem* fileSystem() { + return &file_system_; + } + virtual bool sandboxEnabled() { return true; } @@ -162,6 +167,7 @@ class TestShellWebKitInit : public webkit_glue::WebKitClientImpl { SimpleDatabaseSystem database_system_; SimpleWebCookieJarImpl cookie_jar_; scoped_refptr<TestShellWebBlobRegistryImpl> blob_registry_; + SimpleFileSystem file_system_; #if defined(OS_WIN) WebKit::WebThemeEngine* active_theme_engine_; |