diff options
author | tzik@chromium.org <tzik@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-05-11 07:35:13 +0000 |
---|---|---|
committer | tzik@chromium.org <tzik@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-05-11 07:35:13 +0000 |
commit | 294dd0316b3246c30e4558e8ec380479c9e82481 (patch) | |
tree | 0da556f3aa34918cd33ba14ab80e9acfbb8574f9 /webkit/fileapi | |
parent | 27d255b7a75a9a21fca70a90eae07c6cf22ae30b (diff) | |
download | chromium_src-294dd0316b3246c30e4558e8ec380479c9e82481.zip chromium_src-294dd0316b3246c30e4558e8ec380479c9e82481.tar.gz chromium_src-294dd0316b3246c30e4558e8ec380479c9e82481.tar.bz2 |
Merge QuotaFileUtil into ObfuscatedFileUtil
This change includes
- rename variable name of paths, (e.g. "filesystem:http://example.com/temporary/hoge/fuga")
--- path: FileSystemPath past by upper layer, ("http://example.com", kTemporary, "hoge/fuga")
--- virtual_path: path.internal_path(), ("hoge/fuga")
--- local_path: origin, type & absolute native path
--- local_file_path: absolute native path (e.g. "/home/tzik/.config/chromium/Default/File System/001/t/00/0000001")
--- data_path: native path, relative to origin directory (e.g. "00/0000001")
- use FilePath instead of FileSystemPath for source path in CopyInForeignFile.
- refactor CopyOrMoveFile and CopyInForeignFile of ObfuscatedFileUtil
- merge QuotaFileUtil into ObfuscatedFileUtil
- fixing tests
BUG=114732
TEST='ObfuscatedFileUtilTest.*'
Review URL: https://chromiumcodereview.appspot.com/10051004
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@136521 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit/fileapi')
22 files changed, 815 insertions, 1093 deletions
diff --git a/webkit/fileapi/file_system_dir_url_request_job_unittest.cc b/webkit/fileapi/file_system_dir_url_request_job_unittest.cc index 52b96cb..d5ba78d 100644 --- a/webkit/fileapi/file_system_dir_url_request_job_unittest.cc +++ b/webkit/fileapi/file_system_dir_url_request_job_unittest.cc @@ -257,10 +257,10 @@ TEST_F(FileSystemDirURLRequestJobTest, DirectoryListing) { #endif EXPECT_TRUE(std::getline(in, line)); - VerifyListingEntry(line, "baz", "baz", true, 0); + VerifyListingEntry(line, "hoge", "hoge", false, 10); EXPECT_TRUE(std::getline(in, line)); - VerifyListingEntry(line, "hoge", "hoge", false, 10); + VerifyListingEntry(line, "baz", "baz", true, 0); } TEST_F(FileSystemDirURLRequestJobTest, InvalidURL) { diff --git a/webkit/fileapi/file_system_file_util.cc b/webkit/fileapi/file_system_file_util.cc index 32b00d4..a8b5e66 100644 --- a/webkit/fileapi/file_system_file_util.cc +++ b/webkit/fileapi/file_system_file_util.cc @@ -189,11 +189,11 @@ PlatformFileError FileSystemFileUtil::CopyOrMoveFile( PlatformFileError FileSystemFileUtil::CopyInForeignFile( FileSystemOperationContext* context, - const FileSystemPath& underlying_src_path, + const FilePath& src_file_path, const FileSystemPath& dest_path) { if (underlying_file_util_.get()) { return underlying_file_util_->CopyInForeignFile( - context, underlying_src_path, dest_path); + context, src_file_path, dest_path); } NOTREACHED() << "Subclasses must provide implementation if they have no" << "underlying_file_util"; diff --git a/webkit/fileapi/file_system_file_util.h b/webkit/fileapi/file_system_file_util.h index 6a9584a..dfc2b25 100644 --- a/webkit/fileapi/file_system_file_util.h +++ b/webkit/fileapi/file_system_file_util.h @@ -158,7 +158,7 @@ class FileSystemFileUtil { // underlying filesystem. virtual PlatformFileError CopyInForeignFile( FileSystemOperationContext* context, - const FileSystemPath& underlying_src_path, + const FilePath& src_file_path, const FileSystemPath& dest_path); // Deletes a single file. diff --git a/webkit/fileapi/file_system_operation_write_unittest.cc b/webkit/fileapi/file_system_operation_write_unittest.cc index 6654e1a..47ade43 100644 --- a/webkit/fileapi/file_system_operation_write_unittest.cc +++ b/webkit/fileapi/file_system_operation_write_unittest.cc @@ -29,7 +29,6 @@ #include "webkit/fileapi/file_system_test_helper.h" #include "webkit/fileapi/file_system_util.h" #include "webkit/fileapi/local_file_util.h" -#include "webkit/fileapi/quota_file_util.h" #include "webkit/quota/quota_manager.h" using quota::QuotaManager; @@ -38,6 +37,11 @@ namespace fileapi { namespace { +void AssertStatusEq(base::PlatformFileError expected, + base::PlatformFileError actual) { + ASSERT_EQ(expected, actual); +} + class MockQuotaManager : public QuotaManager { public: MockQuotaManager(const FilePath& base_dir, int64 quota) @@ -72,8 +76,7 @@ class FileSystemOperationWriteTest public base::SupportsWeakPtr<FileSystemOperationWriteTest> { public: FileSystemOperationWriteTest() - : local_file_util_(new LocalFileUtil(QuotaFileUtil::CreateDefault())), - loop_(MessageLoop::TYPE_IO), + : loop_(MessageLoop::TYPE_IO), status_(base::PLATFORM_FILE_OK), cancel_status_(base::PLATFORM_FILE_ERROR_FAILED), bytes_written_(0), @@ -127,7 +130,10 @@ class FileSystemOperationWriteTest cancel_status_ = status; } - scoped_ptr<LocalFileUtil> local_file_util_; + FileSystemFileUtil* file_util() { + return test_helper_.file_util(); + } + scoped_refptr<MockQuotaManager> quota_manager_; FileSystemTestOriginHelper test_helper_; @@ -185,12 +191,16 @@ void FileSystemOperationWriteTest::SetUp() { test_helper_.SetUp(base_dir, false /* unlimited quota */, quota_manager_->proxy(), - local_file_util_.get()); + NULL); filesystem_dir_ = test_helper_.GetOriginRootPath(); ASSERT_TRUE(file_util::CreateTemporaryFileInDir(filesystem_dir_, &file_)); virtual_path_ = file_.BaseName(); + operation()->CreateFile( + URLForPath(virtual_path_), true, + base::Bind(&AssertStatusEq, base::PLATFORM_FILE_OK)); + net::URLRequest::Deprecated::RegisterProtocolFactory( "blob", &BlobURLRequestJobFactory); } @@ -285,6 +295,11 @@ TEST_F(FileSystemOperationWriteTest, TestWriteDir) { &subdir)); FilePath virtual_subdir_path = subdir.BaseName(); + operation()->CreateDirectory( + URLForPath(virtual_subdir_path), + true /* exclusive */, false /* recursive */, + base::Bind(&AssertStatusEq, base::PLATFORM_FILE_OK)); + GURL blob_url("blob:writedir"); scoped_refptr<webkit_blob::BlobData> blob_data(new webkit_blob::BlobData()); blob_data->AppendData("It\'ll not be written, too."); @@ -300,7 +315,7 @@ TEST_F(FileSystemOperationWriteTest, TestWriteDir) { url_request_context.blob_storage_controller()->RemoveBlob(blob_url); EXPECT_EQ(0, bytes_written()); - EXPECT_EQ(base::PLATFORM_FILE_ERROR_ACCESS_DENIED, status()); + EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_A_FILE, status()); EXPECT_TRUE(complete()); } diff --git a/webkit/fileapi/file_system_quota_client_unittest.cc b/webkit/fileapi/file_system_quota_client_unittest.cc index a3c3e9b..aa99ff3 100644 --- a/webkit/fileapi/file_system_quota_client_unittest.cc +++ b/webkit/fileapi/file_system_quota_client_unittest.cc @@ -19,7 +19,6 @@ #include "webkit/fileapi/file_system_util.h" #include "webkit/fileapi/mock_file_system_options.h" #include "webkit/fileapi/obfuscated_file_util.h" -#include "webkit/fileapi/quota_file_util.h" #include "webkit/fileapi/sandbox_mount_point_provider.h" #include "webkit/quota/quota_types.h" diff --git a/webkit/fileapi/file_util_helper.cc b/webkit/fileapi/file_util_helper.cc index 6914cea..2f7b780 100644 --- a/webkit/fileapi/file_util_helper.cc +++ b/webkit/fileapi/file_util_helper.cc @@ -227,7 +227,7 @@ PlatformFileError CrossFileUtilHelper::CopyOrMoveFile( // Call CopyInForeignFile() on the dest_util_ with the resolved source path // to perform limited cross-FileSystemFileUtil copy/move. error = dest_util_->CopyInForeignFile( - context_, src_path.WithInternalPath(platform_file_path), dest_path); + context_, platform_file_path, dest_path); if (operation_ == OPERATION_COPY || error != base::PLATFORM_FILE_OK) return error; diff --git a/webkit/fileapi/file_writer_delegate.cc b/webkit/fileapi/file_writer_delegate.cc index 31214ae..283cbe0 100644 --- a/webkit/fileapi/file_writer_delegate.cc +++ b/webkit/fileapi/file_writer_delegate.cc @@ -16,7 +16,6 @@ #include "webkit/fileapi/file_system_operation.h" #include "webkit/fileapi/file_system_operation_context.h" #include "webkit/fileapi/file_system_quota_util.h" -#include "webkit/fileapi/quota_file_util.h" namespace fileapi { diff --git a/webkit/fileapi/file_writer_delegate_unittest.cc b/webkit/fileapi/file_writer_delegate_unittest.cc index 574dd7d..ee4f1d7 100644 --- a/webkit/fileapi/file_writer_delegate_unittest.cc +++ b/webkit/fileapi/file_writer_delegate_unittest.cc @@ -28,7 +28,7 @@ #include "webkit/fileapi/file_system_test_helper.h" #include "webkit/fileapi/file_system_usage_cache.h" #include "webkit/fileapi/file_writer_delegate.h" -#include "webkit/fileapi/quota_file_util.h" +#include "webkit/quota/quota_manager.h" #include "webkit/fileapi/sandbox_mount_point_provider.h" namespace fileapi { @@ -88,8 +88,7 @@ class FileWriterDelegateTest : public PlatformTest { virtual void TearDown(); virtual void SetUpTestHelper(const FilePath& base_dir) { - quota_file_util_.reset(QuotaFileUtil::CreateDefault()); - test_helper_.SetUp(base_dir, quota_file_util_.get()); + test_helper_.SetUp(base_dir, NULL); } int64 ComputeCurrentOriginUsage() { @@ -126,7 +125,6 @@ class FileWriterDelegateTest : public PlatformTest { // This should be alive until the very end of this instance. MessageLoop loop_; - scoped_ptr<QuotaFileUtil> quota_file_util_; scoped_ptr<FileWriterDelegate> file_writer_delegate_; scoped_ptr<net::URLRequest> request_; scoped_ptr<Result> result_; @@ -228,7 +226,7 @@ TEST_F(FileWriterDelegateTest, WriteSuccessWithoutQuotaLimit) { const GURL kBlobURL("blob:nolimit"); content_ = kData; - PrepareForWrite(kBlobURL, 0, QuotaFileUtil::kNoLimit); + PrepareForWrite(kBlobURL, 0, quota::QuotaManager::kNoLimit); ASSERT_EQ(0, test_helper_.GetCachedOriginUsage()); file_writer_delegate_->Start(file_, request_.Pass()); @@ -322,12 +320,12 @@ TEST_F(FileWriterDelegateTest, WriteSuccessWithoutQuotaLimitConcurrent) { const GURL kBlobURL2("blob:nolimitconcurrent2"); content_ = kData; - PrepareForWrite(kBlobURL, 0, QuotaFileUtil::kNoLimit); + PrepareForWrite(kBlobURL, 0, quota::QuotaManager::kNoLimit); // Credate another FileWriterDelegate for concurrent write. result2.reset(new Result()); file_writer_delegate2.reset(new FileWriterDelegate( - CreateNewOperation(result2.get(), QuotaFileUtil::kNoLimit), + CreateNewOperation(result2.get(), quota::QuotaManager::kNoLimit), test_helper_.CreatePath(file_path2), 0)); request2.reset(new net::URLRequest(kBlobURL2, file_writer_delegate2.get())); diff --git a/webkit/fileapi/isolated_file_util.cc b/webkit/fileapi/isolated_file_util.cc index e23c006..a337b3a 100644 --- a/webkit/fileapi/isolated_file_util.cc +++ b/webkit/fileapi/isolated_file_util.cc @@ -359,7 +359,7 @@ PlatformFileError IsolatedFileUtil::CopyOrMoveFile( PlatformFileError IsolatedFileUtil::CopyInForeignFile( FileSystemOperationContext* context, - const FileSystemPath& src_path, + const FilePath& src_file_path, const FileSystemPath& dest_path) { return base::PLATFORM_FILE_ERROR_SECURITY; } diff --git a/webkit/fileapi/isolated_file_util.h b/webkit/fileapi/isolated_file_util.h index c784cdb..907398d 100644 --- a/webkit/fileapi/isolated_file_util.h +++ b/webkit/fileapi/isolated_file_util.h @@ -76,7 +76,7 @@ class IsolatedFileUtil : public FileSystemFileUtil { bool copy) OVERRIDE; virtual base::PlatformFileError CopyInForeignFile( FileSystemOperationContext* context, - const FileSystemPath& underlying_src_path, + const FilePath& src_file_path, const FileSystemPath& dest_path) OVERRIDE; virtual base::PlatformFileError DeleteFile( FileSystemOperationContext* context, diff --git a/webkit/fileapi/local_file_util.cc b/webkit/fileapi/local_file_util.cc index 5fdb75f..19c48e6 100644 --- a/webkit/fileapi/local_file_util.cc +++ b/webkit/fileapi/local_file_util.cc @@ -222,17 +222,15 @@ PlatformFileError LocalFileUtil::CopyOrMoveFile( // TODO(dmikurube): Make it independent from CopyOrMoveFile. PlatformFileError LocalFileUtil::CopyInForeignFile( FileSystemOperationContext* context, - const FileSystemPath& underlying_src_path, + const FilePath& src_file_path, const FileSystemPath& dest_path) { - if (underlying_src_path.internal_path().empty()) + if (src_file_path.empty()) return base::PLATFORM_FILE_ERROR_INVALID_OPERATION; FileSystemPath local_dest_path = GetLocalPath(context, dest_path); if (local_dest_path.internal_path().empty()) return base::PLATFORM_FILE_ERROR_INVALID_OPERATION; - return underlying_file_util()->CopyOrMoveFile( - context, - underlying_src_path, - local_dest_path, true); + return underlying_file_util()->CopyInForeignFile( + context, src_file_path, local_dest_path); } PlatformFileError LocalFileUtil::DeleteFile( diff --git a/webkit/fileapi/local_file_util.h b/webkit/fileapi/local_file_util.h index 34f91da..38b8b2b 100644 --- a/webkit/fileapi/local_file_util.h +++ b/webkit/fileapi/local_file_util.h @@ -93,7 +93,7 @@ class LocalFileUtil : public FileSystemFileUtil { bool copy) OVERRIDE; virtual PlatformFileError CopyInForeignFile( FileSystemOperationContext* context, - const FileSystemPath& underlying_src_path, + const FilePath& src_file_path, const FileSystemPath& dest_path) OVERRIDE; virtual PlatformFileError DeleteFile( FileSystemOperationContext* context, diff --git a/webkit/fileapi/native_file_util.cc b/webkit/fileapi/native_file_util.cc index f73c74a..26da7a1 100644 --- a/webkit/fileapi/native_file_util.cc +++ b/webkit/fileapi/native_file_util.cc @@ -262,12 +262,11 @@ PlatformFileError NativeFileUtil::CopyOrMoveFile( PlatformFileError NativeFileUtil::CopyInForeignFile( FileSystemOperationContext* context, - const FileSystemPath& underlying_src_path, + const FilePath& src_file_path, const FileSystemPath& dest_path) { - return CopyOrMoveFile(context, - underlying_src_path, - dest_path, - true); + if (file_util::CopyFile(src_file_path, dest_path.internal_path())) + return base::PLATFORM_FILE_OK; + return base::PLATFORM_FILE_ERROR_FAILED; } PlatformFileError NativeFileUtil::DeleteFile( diff --git a/webkit/fileapi/native_file_util.h b/webkit/fileapi/native_file_util.h index 481209d..da3a4cc 100644 --- a/webkit/fileapi/native_file_util.h +++ b/webkit/fileapi/native_file_util.h @@ -82,7 +82,7 @@ class NativeFileUtil : public FileSystemFileUtil { bool copy) OVERRIDE; virtual PlatformFileError CopyInForeignFile( FileSystemOperationContext* unused, - const FileSystemPath& underlying_src_path, + const FilePath& src_file_path, const FileSystemPath& dest_path) OVERRIDE; virtual PlatformFileError DeleteFile( FileSystemOperationContext* unused, diff --git a/webkit/fileapi/obfuscated_file_util.cc b/webkit/fileapi/obfuscated_file_util.cc index 85ff199..544fd2b 100644 --- a/webkit/fileapi/obfuscated_file_util.cc +++ b/webkit/fileapi/obfuscated_file_util.cc @@ -26,10 +26,28 @@ #include "webkit/fileapi/sandbox_mount_point_provider.h" #include "webkit/quota/quota_manager.h" +// Example of various paths: +// void ObfuscatedFileUtil::DoSomething(const FileSystemPath& path) { +// FilePath virtual_path = path.internal_path(); +// FileSystemPath underlying_path = GetUnderlyingPath(path); +// FilePath local_file_path = GetLocalFilePath(path); +// +// // |data_path| is native file path that is relative to the directory for +// // the origin and type. We store |data_path| in DirectoryDatabase. +// FilePath::StringType data_path = +// UnderlyingPathToDataPath(underlying_path); +// +// underlying_file_util()->DoSomething(underlying_path); +// file_util::DoAnother(local_file_path); +// } + namespace fileapi { namespace { +typedef FileSystemDirectoryDatabase::FileId FileId; +typedef FileSystemDirectoryDatabase::FileInfo FileInfo; + const int64 kFlushDelaySeconds = 10 * 60; // 10 minutes void InitFileInfo( @@ -41,9 +59,9 @@ void InitFileInfo( file_info->name = file_name; } -bool IsRootDirectory(const FileSystemPath& virtual_path) { - return (virtual_path.internal_path().empty() || - virtual_path.internal_path().value() == FILE_PATH_LITERAL("/")); +bool IsRootDirectory(const FileSystemPath& path) { + return (path.internal_path().empty() || + path.internal_path().value() == FILE_PATH_LITERAL("/")); } // Costs computed as per crbug.com/86114, based on the LevelDB implementation of @@ -60,6 +78,9 @@ int64 UsageForPath(size_t length) { } bool AllocateQuota(FileSystemOperationContext* context, int64 growth) { + if (context->allowed_bytes_growth() == quota::QuotaManager::kNoLimit) + return true; + int64 new_quota = context->allowed_bytes_growth() - growth; if (growth > 0 && new_quota < 0) return false; @@ -80,8 +101,7 @@ void UpdateUsage( quota_manager_proxy, origin, type, growth); } -void TouchDirectory(FileSystemDirectoryDatabase* db, - FileSystemDirectoryDatabase::FileId dir_id) { +void TouchDirectory(FileSystemDirectoryDatabase* db, FileId dir_id) { DCHECK(db); if (!db->UpdateModificationTime(dir_id, base::Time::Now())) NOTREACHED(); @@ -101,78 +121,65 @@ class ObfuscatedFileEnumerator : public FileSystemFileUtil::AbstractFileEnumerator { public: ObfuscatedFileEnumerator( - const FilePath& base_path, FileSystemDirectoryDatabase* db, FileSystemOperationContext* context, - FileSystemFileUtil* underlying_file_util, - const FileSystemPath& virtual_root_path, + ObfuscatedFileUtil* obfuscated_file_util, + const FileSystemPath& root_path, bool recursive) - : current_file_size_(0), - base_path_(base_path), - virtual_root_path_(virtual_root_path), - db_(db), + : db_(db), context_(context), - underlying_file_util_(underlying_file_util), + obfuscated_file_util_(obfuscated_file_util), + origin_(root_path.origin()), + type_(root_path.type()), recursive_(recursive) { - DCHECK(db_); - DCHECK(context_); - DCHECK(underlying_file_util_); - + FilePath root_virtual_path = root_path.internal_path(); FileId file_id; - FileInfo file_info; - if (!db_->GetFileWithPath(virtual_root_path.internal_path(), &file_id)) - return; - if (!db_->GetFileInfo(file_id, &file_info)) - return; - if (!file_info.is_directory()) + + if (!db_->GetFileWithPath(root_virtual_path, &file_id)) return; - FileRecord record = { file_id, file_info, - virtual_root_path.internal_path() }; + + FileRecord record = { file_id, root_virtual_path }; recurse_queue_.push(record); } - ~ObfuscatedFileEnumerator() {} + virtual ~ObfuscatedFileEnumerator() {} virtual FilePath Next() OVERRIDE { ProcessRecurseQueue(); - if (display_queue_.empty()) + if (display_stack_.empty()) return FilePath(); - current_ = display_queue_.front(); - display_queue_.pop(); - if (current_.file_info.is_directory()) { - current_file_size_ = 0; - } else { - base::PlatformFileInfo file_info; - FilePath platform_file_path; - FilePath local_path = base_path_.Append(current_.file_info.data_path); - - base::PlatformFileError error = underlying_file_util_->GetFileInfo( - context_, virtual_root_path_.WithInternalPath(local_path), - &file_info, &platform_file_path); - if (error != base::PLATFORM_FILE_OK) { - LOG(WARNING) << "Lost a backing file."; - return Next(); - } - current_.file_info.modification_time = file_info.last_modified; - current_file_size_ = file_info.size; - } + current_file_id_ = display_stack_.back(); + display_stack_.pop_back(); - if (recursive_ && current_.file_info.is_directory()) - recurse_queue_.push(current_); - return current_.file_path; + FileInfo file_info; + FilePath platform_file_path; + base::PlatformFileError error = + obfuscated_file_util_->GetFileInfoInternal( + db_, context_, origin_, type_, current_file_id_, + &file_info, ¤t_platform_file_info_, &platform_file_path); + if (error != base::PLATFORM_FILE_OK) + return Next(); + + FilePath virtual_path = + current_parent_virtual_path_.Append(file_info.name); + if (recursive_ && file_info.is_directory()) { + FileRecord record = { current_file_id_, virtual_path }; + recurse_queue_.push(record); + } + return virtual_path; } virtual int64 Size() OVERRIDE { - return current_file_size_; + return current_platform_file_info_.size; } virtual base::Time LastModifiedTime() OVERRIDE { - return current_.file_info.modification_time; + return current_platform_file_info_.last_modified; } virtual bool IsDirectory() OVERRIDE { - return current_.file_info.is_directory(); + return current_platform_file_info_.is_directory; } virtual bool IsLink() OVERRIDE { @@ -185,39 +192,34 @@ class ObfuscatedFileEnumerator struct FileRecord { FileId file_id; - FileInfo file_info; - FilePath file_path; + FilePath virtual_path; }; void ProcessRecurseQueue() { - while (display_queue_.empty() && !recurse_queue_.empty()) { - FileRecord directory = recurse_queue_.front(); - std::vector<FileId> children; + while (display_stack_.empty() && !recurse_queue_.empty()) { + FileRecord entry = recurse_queue_.front(); recurse_queue_.pop(); - if (!db_->ListChildren(directory.file_id, &children)) + if (!db_->ListChildren(entry.file_id, &display_stack_)) { + display_stack_.clear(); return; - std::vector<FileId>::iterator iter; - for (iter = children.begin(); iter != children.end(); ++iter) { - FileRecord child; - child.file_id = *iter; - if (!db_->GetFileInfo(child.file_id, &child.file_info)) - return; - child.file_path = directory.file_path.Append(child.file_info.name); - display_queue_.push(child); } + current_parent_virtual_path_ = entry.virtual_path; } } - std::queue<FileRecord> display_queue_; - std::queue<FileRecord> recurse_queue_; - FileRecord current_; - int64 current_file_size_; - FilePath base_path_; - FileSystemPath virtual_root_path_; FileSystemDirectoryDatabase* db_; FileSystemOperationContext* context_; - FileSystemFileUtil* underlying_file_util_; + ObfuscatedFileUtil* obfuscated_file_util_; + GURL origin_; + FileSystemType type_; bool recursive_; + + std::queue<FileRecord> recurse_queue_; + std::vector<FileId> display_stack_; + FilePath current_parent_virtual_path_; + + FileId current_file_id_; + base::PlatformFileInfo current_platform_file_info_; }; class ObfuscatedOriginEnumerator @@ -226,8 +228,8 @@ class ObfuscatedOriginEnumerator typedef FileSystemOriginDatabase::OriginRecord OriginRecord; ObfuscatedOriginEnumerator( FileSystemOriginDatabase* origin_database, - const FilePath& base_path) - : base_path_(base_path) { + const FilePath& base_file_path) + : base_file_path_(base_file_path) { if (origin_database) origin_database->ListAllOrigins(&origins_); } @@ -255,14 +257,14 @@ class ObfuscatedOriginEnumerator NOTREACHED(); return false; } - FilePath path = base_path_.Append(current_.path).Append(type_string); + FilePath path = base_file_path_.Append(current_.path).Append(type_string); return file_util::DirectoryExists(path); } private: std::vector<OriginRecord> origins_; OriginRecord current_; - FilePath base_path_; + FilePath base_file_path_; }; ObfuscatedFileUtil::ObfuscatedFileUtil( @@ -274,39 +276,39 @@ ObfuscatedFileUtil::ObfuscatedFileUtil( PlatformFileError ObfuscatedFileUtil::CreateOrOpen( FileSystemOperationContext* context, - const FileSystemPath& virtual_path, int file_flags, + const FileSystemPath& path, int file_flags, PlatformFile* file_handle, bool* created) { DCHECK(!(file_flags & (base::PLATFORM_FILE_DELETE_ON_CLOSE | base::PLATFORM_FILE_HIDDEN | base::PLATFORM_FILE_EXCLUSIVE_READ | base::PLATFORM_FILE_EXCLUSIVE_WRITE))); FileSystemDirectoryDatabase* db = GetDirectoryDatabase( - virtual_path.origin(), virtual_path.type(), true); + path.origin(), path.type(), true); if (!db) return base::PLATFORM_FILE_ERROR_FAILED; FileId file_id; - if (!db->GetFileWithPath(virtual_path.internal_path(), &file_id)) { + if (!db->GetFileWithPath(path.internal_path(), &file_id)) { // The file doesn't exist. if (!(file_flags & (base::PLATFORM_FILE_CREATE | base::PLATFORM_FILE_CREATE_ALWAYS | base::PLATFORM_FILE_OPEN_ALWAYS))) return base::PLATFORM_FILE_ERROR_NOT_FOUND; FileId parent_id; - if (!db->GetFileWithPath(virtual_path.internal_path().DirName(), + if (!db->GetFileWithPath(path.internal_path().DirName(), &parent_id)) return base::PLATFORM_FILE_ERROR_NOT_FOUND; FileInfo file_info; InitFileInfo(&file_info, parent_id, - VirtualPath::BaseName(virtual_path.internal_path()).value()); + VirtualPath::BaseName(path.internal_path()).value()); int64 growth = UsageForPath(file_info.name.size()); if (!AllocateQuota(context, growth)) return base::PLATFORM_FILE_ERROR_NO_SPACE; PlatformFileError error = CreateFile( - context, FileSystemPath(), - virtual_path.origin(), virtual_path.type(), &file_info, + context, FilePath(), + path.origin(), path.type(), &file_info, file_flags, file_handle); if (created && base::PLATFORM_FILE_OK == error) { *created = true; - UpdateUsage(context, virtual_path.origin(), virtual_path.type(), growth); + UpdateUsage(context, path.origin(), path.type(), growth); } return error; } @@ -320,15 +322,14 @@ PlatformFileError ObfuscatedFileUtil::CreateOrOpen( } if (file_info.is_directory()) return base::PLATFORM_FILE_ERROR_NOT_A_FILE; - FileSystemPath local_path = DataPathToLocalPath( - virtual_path.origin(), virtual_path.type(), file_info.data_path); + FileSystemPath underlying_path = DataPathToUnderlyingPath( + path.origin(), path.type(), file_info.data_path); base::PlatformFileError error = underlying_file_util()->CreateOrOpen( - context, local_path, file_flags, file_handle, created); + context, underlying_path, file_flags, file_handle, created); if (error == base::PLATFORM_FILE_ERROR_NOT_FOUND) { // TODO(tzik): Also invalidate on-memory usage cache in UsageTracker. // TODO(tzik): Delete database entry after ensuring the file lost. - context->file_system_context()->GetQuotaUtil(virtual_path.type())-> - InvalidateUsageCache(virtual_path.origin(), virtual_path.type()); + InvalidateUsageCache(context, path.origin(), path.type()); LOG(WARNING) << "Lost a backing file."; error = base::PLATFORM_FILE_ERROR_FAILED; } @@ -337,14 +338,15 @@ PlatformFileError ObfuscatedFileUtil::CreateOrOpen( PlatformFileError ObfuscatedFileUtil::EnsureFileExists( FileSystemOperationContext* context, - const FileSystemPath& virtual_path, + const FileSystemPath& path, bool* created) { FileSystemDirectoryDatabase* db = GetDirectoryDatabase( - virtual_path.origin(), virtual_path.type(), true); + path.origin(), path.type(), true); if (!db) return base::PLATFORM_FILE_ERROR_FAILED; + FileId file_id; - if (db->GetFileWithPath(virtual_path.internal_path(), &file_id)) { + if (db->GetFileWithPath(path.internal_path(), &file_id)) { FileInfo file_info; if (!db->GetFileInfo(file_id, &file_info)) { NOTREACHED(); @@ -357,38 +359,37 @@ PlatformFileError ObfuscatedFileUtil::EnsureFileExists( return base::PLATFORM_FILE_OK; } FileId parent_id; - if (!db->GetFileWithPath(virtual_path.internal_path().DirName(), &parent_id)) + if (!db->GetFileWithPath(path.internal_path().DirName(), &parent_id)) return base::PLATFORM_FILE_ERROR_NOT_FOUND; FileInfo file_info; InitFileInfo(&file_info, parent_id, - VirtualPath::BaseName(virtual_path.internal_path()).value()); + VirtualPath::BaseName(path.internal_path()).value()); int64 growth = UsageForPath(file_info.name.size()); if (!AllocateQuota(context, growth)) return base::PLATFORM_FILE_ERROR_NO_SPACE; - PlatformFileError error = CreateFile(context, - FileSystemPath(), - virtual_path.origin(), virtual_path.type(), &file_info, - 0, NULL); + PlatformFileError error = CreateFile( + context, FilePath(), path.origin(), path.type(), &file_info, 0, NULL); if (created && base::PLATFORM_FILE_OK == error) { *created = true; - UpdateUsage(context, virtual_path.origin(), virtual_path.type(), growth); + UpdateUsage(context, path.origin(), path.type(), growth); } return error; } PlatformFileError ObfuscatedFileUtil::CreateDirectory( FileSystemOperationContext* context, - const FileSystemPath& virtual_path, + const FileSystemPath& path, bool exclusive, bool recursive) { FileSystemDirectoryDatabase* db = GetDirectoryDatabase( - virtual_path.origin(), virtual_path.type(), true); + path.origin(), path.type(), true); if (!db) return base::PLATFORM_FILE_ERROR_FAILED; + FileId file_id; - if (db->GetFileWithPath(virtual_path.internal_path(), &file_id)) { + if (db->GetFileWithPath(path.internal_path(), &file_id)) { FileInfo file_info; if (exclusive) return base::PLATFORM_FILE_ERROR_EXISTS; @@ -402,7 +403,7 @@ PlatformFileError ObfuscatedFileUtil::CreateDirectory( } std::vector<FilePath::StringType> components; - VirtualPath::GetComponents(virtual_path.internal_path(), &components); + VirtualPath::GetComponents(path.internal_path(), &components); FileId parent_id = 0; size_t index; for (index = 0; index < components.size(); ++index) { @@ -429,7 +430,7 @@ PlatformFileError ObfuscatedFileUtil::CreateDirectory( NOTREACHED(); return base::PLATFORM_FILE_ERROR_FAILED; } - UpdateUsage(context, virtual_path.origin(), virtual_path.type(), growth); + UpdateUsage(context, path.origin(), path.type(), growth); if (first) { first = false; TouchDirectory(db, file_info.parent_id); @@ -440,19 +441,19 @@ PlatformFileError ObfuscatedFileUtil::CreateDirectory( PlatformFileError ObfuscatedFileUtil::GetFileInfo( FileSystemOperationContext* context, - const FileSystemPath& virtual_path, + const FileSystemPath& path, base::PlatformFileInfo* file_info, FilePath* platform_file_path) { FileSystemDirectoryDatabase* db = GetDirectoryDatabase( - virtual_path.origin(), virtual_path.type(), false); + path.origin(), path.type(), false); if (!db) return base::PLATFORM_FILE_ERROR_NOT_FOUND; FileId file_id; - if (!db->GetFileWithPath(virtual_path.internal_path(), &file_id)) + if (!db->GetFileWithPath(path.internal_path(), &file_id)) return base::PLATFORM_FILE_ERROR_NOT_FOUND; FileInfo local_info; return GetFileInfoInternal(db, context, - virtual_path.origin(), virtual_path.type(), + path.origin(), path.type(), file_id, &local_info, file_info, platform_file_path); } @@ -467,37 +468,32 @@ ObfuscatedFileUtil::CreateFileEnumerator( if (!db) return new FileSystemFileUtil::EmptyFileEnumerator(); return new ObfuscatedFileEnumerator( - GetDirectoryForOriginAndType(root_path.origin(), - root_path.type(), false), - db, - context, - underlying_file_util(), - root_path, recursive); + db, context, this, root_path, recursive); } PlatformFileError ObfuscatedFileUtil::GetLocalFilePath( FileSystemOperationContext* context, - const FileSystemPath& file_system_path, + const FileSystemPath& path, FilePath* local_file_path) { - FileSystemPath local_path = GetLocalPath(file_system_path); - if (local_path.internal_path().empty()) + FileSystemPath underlying_path = GetUnderlyingPath(path); + if (underlying_path.internal_path().empty()) return base::PLATFORM_FILE_ERROR_NOT_FOUND; - *local_file_path = local_path.internal_path(); + *local_file_path = underlying_path.internal_path(); return base::PLATFORM_FILE_OK; } PlatformFileError ObfuscatedFileUtil::Touch( FileSystemOperationContext* context, - const FileSystemPath& virtual_path, + const FileSystemPath& path, const base::Time& last_access_time, const base::Time& last_modified_time) { FileSystemDirectoryDatabase* db = GetDirectoryDatabase( - virtual_path.origin(), virtual_path.type(), false); + path.origin(), path.type(), false); if (!db) return base::PLATFORM_FILE_ERROR_NOT_FOUND; FileId file_id; - if (!db->GetFileWithPath(virtual_path.internal_path(), &file_id)) + if (!db->GetFileWithPath(path.internal_path(), &file_id)) return base::PLATFORM_FILE_ERROR_NOT_FOUND; FileInfo file_info; @@ -510,21 +506,21 @@ PlatformFileError ObfuscatedFileUtil::Touch( return base::PLATFORM_FILE_ERROR_FAILED; return base::PLATFORM_FILE_OK; } - FileSystemPath local_path = DataPathToLocalPath( - virtual_path.origin(), virtual_path.type(), file_info.data_path); + FileSystemPath underlying_path = DataPathToUnderlyingPath( + path.origin(), path.type(), file_info.data_path); return underlying_file_util()->Touch( - context, local_path, + context, underlying_path, last_access_time, last_modified_time); } PlatformFileError ObfuscatedFileUtil::Truncate( FileSystemOperationContext* context, - const FileSystemPath& virtual_path, + const FileSystemPath& path, int64 length) { base::PlatformFileInfo file_info; FilePath local_path; base::PlatformFileError error = - GetFileInfo(context, virtual_path, &file_info, &local_path); + GetFileInfo(context, path, &file_info, &local_path); if (error != base::PLATFORM_FILE_OK) return error; @@ -532,27 +528,27 @@ PlatformFileError ObfuscatedFileUtil::Truncate( if (!AllocateQuota(context, growth)) return base::PLATFORM_FILE_ERROR_NO_SPACE; error = underlying_file_util()->Truncate( - context, virtual_path.WithInternalPath(local_path), length); + context, path.WithInternalPath(local_path), length); if (error == base::PLATFORM_FILE_OK) - UpdateUsage(context, virtual_path.origin(), virtual_path.type(), growth); + UpdateUsage(context, path.origin(), path.type(), growth); return error; } bool ObfuscatedFileUtil::PathExists( FileSystemOperationContext* context, - const FileSystemPath& virtual_path) { + const FileSystemPath& path) { FileSystemDirectoryDatabase* db = GetDirectoryDatabase( - virtual_path.origin(), virtual_path.type(), false); + path.origin(), path.type(), false); if (!db) return false; FileId file_id; - return db->GetFileWithPath(virtual_path.internal_path(), &file_id); + return db->GetFileWithPath(path.internal_path(), &file_id); } bool ObfuscatedFileUtil::DirectoryExists( FileSystemOperationContext* context, - const FileSystemPath& virtual_path) { - if (IsRootDirectory(virtual_path)) { + const FileSystemPath& path) { + if (IsRootDirectory(path)) { // It's questionable whether we should return true or false for the // root directory of nonexistent origin, but here we return true // as the current implementation of ReadDirectory always returns an empty @@ -563,11 +559,11 @@ bool ObfuscatedFileUtil::DirectoryExists( return true; } FileSystemDirectoryDatabase* db = GetDirectoryDatabase( - virtual_path.origin(), virtual_path.type(), false); + path.origin(), path.type(), false); if (!db) return false; FileId file_id; - if (!db->GetFileWithPath(virtual_path.internal_path(), &file_id)) + if (!db->GetFileWithPath(path.internal_path(), &file_id)) return false; FileInfo file_info; if (!db->GetFileInfo(file_id, &file_info)) { @@ -579,13 +575,13 @@ bool ObfuscatedFileUtil::DirectoryExists( bool ObfuscatedFileUtil::IsDirectoryEmpty( FileSystemOperationContext* context, - const FileSystemPath& virtual_path) { + const FileSystemPath& path) { FileSystemDirectoryDatabase* db = GetDirectoryDatabase( - virtual_path.origin(), virtual_path.type(), false); + path.origin(), path.type(), false); if (!db) return true; // Not a great answer, but it's what others do. FileId file_id; - if (!db->GetFileWithPath(virtual_path.internal_path(), &file_id)) + if (!db->GetFileWithPath(path.internal_path(), &file_id)) return true; // Ditto. FileInfo file_info; if (!db->GetFileInfo(file_id, &file_info)) { @@ -615,26 +611,69 @@ PlatformFileError ObfuscatedFileUtil::CopyOrMoveFile( src_path.origin(), src_path.type(), true); if (!db) return base::PLATFORM_FILE_ERROR_FAILED; + FileId src_file_id; if (!db->GetFileWithPath(src_path.internal_path(), &src_file_id)) return base::PLATFORM_FILE_ERROR_NOT_FOUND; + FileId dest_file_id; bool overwrite = db->GetFileWithPath(dest_path.internal_path(), &dest_file_id); + FileInfo src_file_info; - FileInfo dest_file_info; - if (!db->GetFileInfo(src_file_id, &src_file_info) || - src_file_info.is_directory()) { - NOTREACHED(); + base::PlatformFileInfo src_platform_file_info; + FilePath src_local_file_path; + base::PlatformFileError error = GetFileInfoInternal( + db, context, src_path.origin(), src_path.type(), src_file_id, + &src_file_info, &src_platform_file_info, &src_local_file_path); + if (error != base::PLATFORM_FILE_OK) + return error; + if (src_file_info.is_directory()) return base::PLATFORM_FILE_ERROR_FAILED; - } + + FileInfo dest_file_info; + base::PlatformFileInfo dest_platform_file_info; // overwrite case only + FileSystemPath dest_underlying_path; if (overwrite) { - if (!db->GetFileInfo(dest_file_id, &dest_file_info) || - dest_file_info.is_directory()) { - NOTREACHED(); + FilePath dest_local_file_path; + base::PlatformFileError error = GetFileInfoInternal( + db, context, dest_path.origin(), dest_path.type(), dest_file_id, + &dest_file_info, &dest_platform_file_info, &dest_local_file_path); + if (error == base::PLATFORM_FILE_ERROR_NOT_FOUND) + overwrite = false; // fallback to non-overwrite case + else if (error != base::PLATFORM_FILE_OK) + return error; + else if (dest_file_info.is_directory()) return base::PLATFORM_FILE_ERROR_FAILED; + else + dest_underlying_path = dest_path.WithInternalPath(dest_local_file_path); + } + if (!overwrite) { + FileId dest_parent_id; + if (!db->GetFileWithPath(dest_path.internal_path().DirName(), + &dest_parent_id)) { + NOTREACHED(); // We shouldn't be called in this case. + return base::PLATFORM_FILE_ERROR_NOT_FOUND; } + + dest_file_info = src_file_info; + dest_file_info.parent_id = dest_parent_id; + dest_file_info.name = + VirtualPath::BaseName(dest_path.internal_path()).value(); } + + int64 growth = 0; + if (copy) + growth += src_platform_file_info.size; + else + growth -= UsageForPath(src_file_info.name.size()); + if (overwrite) + growth -= dest_platform_file_info.size; + else + growth += UsageForPath(dest_file_info.name.size()); + if (!AllocateQuota(context, growth)) + return base::PLATFORM_FILE_ERROR_NO_SPACE; + /* * Copy-with-overwrite * Just overwrite data file @@ -649,176 +688,174 @@ PlatformFileError ObfuscatedFileUtil::CopyOrMoveFile( * Move-without-overwrite * Just update metadata */ + error = base::PLATFORM_FILE_ERROR_FAILED; if (copy) { - FileSystemPath src_local_path = DataPathToLocalPath( - src_path.origin(), src_path.type(), src_file_info.data_path); - if (!underlying_file_util()->PathExists(context, src_local_path)) { - // TODO(tzik): Also invalidate on-memory usage cache in UsageTracker. - context->file_system_context()->GetQuotaUtil(src_path.type())-> - InvalidateUsageCache(src_path.origin(), src_path.type()); - LOG(WARNING) << "Lost a backing file."; - return base::PLATFORM_FILE_ERROR_FAILED; - } - if (overwrite) { - FileSystemPath dest_local_path = DataPathToLocalPath( - dest_path.origin(), dest_path.type(), dest_file_info.data_path); - PlatformFileError error = underlying_file_util()->CopyOrMoveFile(context, - src_local_path, dest_local_path, copy); - if (error == base::PLATFORM_FILE_OK) - TouchDirectory(db, dest_file_info.parent_id); - return error; - } else { - FileId dest_parent_id; - if (!db->GetFileWithPath(dest_path.internal_path().DirName(), - &dest_parent_id)) { - NOTREACHED(); // We shouldn't be called in this case. - return base::PLATFORM_FILE_ERROR_NOT_FOUND; - } - InitFileInfo(&dest_file_info, dest_parent_id, - VirtualPath::BaseName(dest_path.internal_path()).value()); - int64 growth = UsageForPath(dest_file_info.name.size()); - if (!AllocateQuota(context, growth)) - return base::PLATFORM_FILE_ERROR_NO_SPACE; - base::PlatformFileError error = CreateFile( - context, src_local_path, - dest_path.origin(), dest_path.type(), &dest_file_info, - 0, NULL); - if (error == base::PLATFORM_FILE_OK) - UpdateUsage(context, dest_path.origin(), dest_path.type(), growth); - return error; + error = underlying_file_util()->CopyOrMoveFile( + context, + src_path.WithInternalPath(src_local_file_path), + dest_underlying_path, + true /* copy */); + } else { // non-overwrite + error = CreateFile(context, src_local_file_path, + dest_path.origin(), dest_path.type(), + &dest_file_info, 0, NULL); } - } else { // It's a move. + } else { if (overwrite) { - int64 growth = -UsageForPath(src_file_info.name.size()); - AllocateQuota(context, growth); - if (!db->OverwritingMoveFile(src_file_id, dest_file_id)) - return base::PLATFORM_FILE_ERROR_FAILED; - FileSystemPath dest_local_path = DataPathToLocalPath( - dest_path.origin(), dest_path.type(), dest_file_info.data_path); - if (base::PLATFORM_FILE_OK != - underlying_file_util()->DeleteFile(context, dest_local_path)) - LOG(WARNING) << "Leaked a backing file."; - UpdateUsage(context, src_path.origin(), src_path.type(), growth); - TouchDirectory(db, src_file_info.parent_id); - TouchDirectory(db, dest_file_info.parent_id); - return base::PLATFORM_FILE_OK; - } else { - FileId dest_parent_id; - if (!db->GetFileWithPath(dest_path.internal_path().DirName(), - &dest_parent_id)) { - NOTREACHED(); - return base::PLATFORM_FILE_ERROR_FAILED; + if (db->OverwritingMoveFile(src_file_id, dest_file_id)) { + if (base::PLATFORM_FILE_OK != + underlying_file_util()->DeleteFile(context, dest_underlying_path)) + LOG(WARNING) << "Leaked a backing file."; + error = base::PLATFORM_FILE_OK; + } else { + error = base::PLATFORM_FILE_ERROR_FAILED; } - FilePath dest_internal_path = dest_path.internal_path(); - FilePath src_internal_path = src_path.internal_path(); - int64 growth = UsageForPath( - VirtualPath::BaseName(dest_internal_path).value().size()); - growth -= UsageForPath(src_file_info.name.size()); - if (!AllocateQuota(context, growth)) - return base::PLATFORM_FILE_ERROR_NO_SPACE; - FileId src_parent_id = src_file_info.parent_id; - src_file_info.parent_id = dest_parent_id; - src_file_info.name = - VirtualPath::BaseName(dest_path.internal_path()).value(); - if (!db->UpdateFileInfo(src_file_id, src_file_info)) - return base::PLATFORM_FILE_ERROR_FAILED; - UpdateUsage(context, src_path.origin(), src_path.type(), growth); - TouchDirectory(db, src_parent_id); - TouchDirectory(db, dest_parent_id); - return base::PLATFORM_FILE_OK; + } else { // non-overwrite + if (db->UpdateFileInfo(src_file_id, dest_file_info)) + error = base::PLATFORM_FILE_OK; + else + error = base::PLATFORM_FILE_ERROR_FAILED; } } - NOTREACHED(); - return base::PLATFORM_FILE_ERROR_FAILED; + + if (error != base::PLATFORM_FILE_OK) + return error; + + if (!copy) + TouchDirectory(db, src_file_info.parent_id); + TouchDirectory(db, dest_file_info.parent_id); + + UpdateUsage(context, dest_path.origin(), dest_path.type(), growth); + return error; } PlatformFileError ObfuscatedFileUtil::CopyInForeignFile( FileSystemOperationContext* context, - const FileSystemPath& underlying_src_path, + const FilePath& src_file_path, const FileSystemPath& dest_path) { FileSystemDirectoryDatabase* db = GetDirectoryDatabase( dest_path.origin(), dest_path.type(), true); if (!db) return base::PLATFORM_FILE_ERROR_FAILED; + + base::PlatformFileInfo src_platform_file_info; + if (!file_util::GetFileInfo(src_file_path, &src_platform_file_info)) + return base::PLATFORM_FILE_ERROR_NOT_FOUND; + FileId dest_file_id; bool overwrite = db->GetFileWithPath(dest_path.internal_path(), &dest_file_id); + FileInfo dest_file_info; + base::PlatformFileInfo dest_platform_file_info; // overwrite case only if (overwrite) { - if (!db->GetFileInfo(dest_file_id, &dest_file_info) || - dest_file_info.is_directory()) { - NOTREACHED(); + FilePath dest_local_file_path; + base::PlatformFileError error = GetFileInfoInternal( + db, context, dest_path.origin(), dest_path.type(), dest_file_id, + &dest_file_info, &dest_platform_file_info, &dest_local_file_path); + if (error == base::PLATFORM_FILE_ERROR_NOT_FOUND) + overwrite = false; // fallback to non-overwrite case + else if (error != base::PLATFORM_FILE_OK) + return error; + else if (dest_file_info.is_directory()) return base::PLATFORM_FILE_ERROR_FAILED; - } - FileSystemPath dest_local_path = DataPathToLocalPath( - dest_path.origin(), dest_path.type(), dest_file_info.data_path); - return underlying_file_util()->CopyOrMoveFile(context, - underlying_src_path, - dest_local_path, true /* copy */); - } else { + } + if (!overwrite) { FileId dest_parent_id; if (!db->GetFileWithPath(dest_path.internal_path().DirName(), - &dest_parent_id)) { - NOTREACHED(); // We shouldn't be called in this case. + &dest_parent_id) || + !dest_file_info.is_directory()) { + NOTREACHED(); return base::PLATFORM_FILE_ERROR_NOT_FOUND; } InitFileInfo(&dest_file_info, dest_parent_id, - VirtualPath::BaseName(dest_path.internal_path()).value()); - int64 growth = UsageForPath(dest_file_info.name.size()); - if (!AllocateQuota(context, growth)) - return base::PLATFORM_FILE_ERROR_NO_SPACE; - base::PlatformFileError error = - CreateFile(context, underlying_src_path, - dest_path.origin(), dest_path.type(), &dest_file_info, - 0, NULL); - if (error == base::PLATFORM_FILE_OK) - UpdateUsage(context, dest_path.origin(), dest_path.type(), growth); - return error; + VirtualPath::BaseName(dest_path.internal_path()).value()); + } + + int64 growth = src_platform_file_info.size; + if (overwrite) + growth -= dest_platform_file_info.size; + else + growth += UsageForPath(dest_file_info.name.size()); + if (!AllocateQuota(context, growth)) + return base::PLATFORM_FILE_ERROR_NO_SPACE; + + base::PlatformFileError error; + if (overwrite) { + FileSystemPath dest_underlying_path = DataPathToUnderlyingPath( + dest_path.origin(), dest_path.type(), dest_file_info.data_path); + error = underlying_file_util()->CopyInForeignFile( + context, src_file_path, dest_underlying_path); + } else { + error = CreateFile(context, src_file_path, + dest_path.origin(), dest_path.type(), + &dest_file_info, 0, NULL); } - return base::PLATFORM_FILE_ERROR_FAILED; + + if (error != base::PLATFORM_FILE_OK) + return error; + + UpdateUsage(context, dest_path.origin(), dest_path.type(), growth); + TouchDirectory(db, dest_file_info.parent_id); + return base::PLATFORM_FILE_OK; } PlatformFileError ObfuscatedFileUtil::DeleteFile( FileSystemOperationContext* context, - const FileSystemPath& virtual_path) { + const FileSystemPath& path) { FileSystemDirectoryDatabase* db = GetDirectoryDatabase( - virtual_path.origin(), virtual_path.type(), true); + path.origin(), path.type(), true); if (!db) return base::PLATFORM_FILE_ERROR_FAILED; FileId file_id; - if (!db->GetFileWithPath(virtual_path.internal_path(), &file_id)) + if (!db->GetFileWithPath(path.internal_path(), &file_id)) return base::PLATFORM_FILE_ERROR_NOT_FOUND; + FileInfo file_info; - if (!db->GetFileInfo(file_id, &file_info) || file_info.is_directory()) { + base::PlatformFileInfo platform_file_info; + FilePath local_file_path; + base::PlatformFileError error = GetFileInfoInternal( + db, context, path.origin(), path.type(), file_id, + &file_info, &platform_file_info, &local_file_path); + if (error != base::PLATFORM_FILE_ERROR_NOT_FOUND && + error != base::PLATFORM_FILE_OK) + return error; + + if (file_info.is_directory()) { NOTREACHED(); return base::PLATFORM_FILE_ERROR_FAILED; } + + int64 growth = -UsageForPath(file_info.name.size()) - platform_file_info.size; + AllocateQuota(context, growth); if (!db->RemoveFileInfo(file_id)) { NOTREACHED(); return base::PLATFORM_FILE_ERROR_FAILED; } - int64 growth = -UsageForPath(file_info.name.size()); - AllocateQuota(context, growth); - UpdateUsage(context, virtual_path.origin(), virtual_path.type(), growth); - FileSystemPath local_path = DataPathToLocalPath( - virtual_path.origin(), virtual_path.type(), file_info.data_path); - if (base::PLATFORM_FILE_OK != - underlying_file_util()->DeleteFile(context, local_path)) - LOG(WARNING) << "Leaked a backing file."; + UpdateUsage(context, path.origin(), path.type(), growth); TouchDirectory(db, file_info.parent_id); + + if (error == base::PLATFORM_FILE_ERROR_NOT_FOUND) + return base::PLATFORM_FILE_OK; + + error = underlying_file_util()->DeleteFile( + context, path.WithInternalPath(local_file_path)); + if (base::PLATFORM_FILE_OK != error) + LOG(WARNING) << "Leaked a backing file."; return base::PLATFORM_FILE_OK; } PlatformFileError ObfuscatedFileUtil::DeleteSingleDirectory( FileSystemOperationContext* context, - const FileSystemPath& virtual_path) { + const FileSystemPath& path) { FileSystemDirectoryDatabase* db = GetDirectoryDatabase( - virtual_path.origin(), virtual_path.type(), true); + path.origin(), path.type(), true); if (!db) return base::PLATFORM_FILE_ERROR_FAILED; + FileId file_id; - if (!db->GetFileWithPath(virtual_path.internal_path(), &file_id)) + if (!db->GetFileWithPath(path.internal_path(), &file_id)) return base::PLATFORM_FILE_ERROR_NOT_FOUND; FileInfo file_info; if (!db->GetFileInfo(file_id, &file_info) || !file_info.is_directory()) { @@ -829,7 +866,7 @@ PlatformFileError ObfuscatedFileUtil::DeleteSingleDirectory( return base::PLATFORM_FILE_ERROR_NOT_EMPTY; int64 growth = -UsageForPath(file_info.name.size()); AllocateQuota(context, growth); - UpdateUsage(context, virtual_path.origin(), virtual_path.type(), growth); + UpdateUsage(context, path.origin(), path.type(), growth); TouchDirectory(db, file_info.parent_id); return base::PLATFORM_FILE_OK; } @@ -1043,6 +1080,7 @@ PlatformFileError ObfuscatedFileUtil::GetFileInfoInternal( } if (local_info->is_directory()) { + file_info->size = 0; file_info->is_directory = true; file_info->is_symbolic_link = false; file_info->last_modified = local_info->modification_time; @@ -1052,15 +1090,22 @@ PlatformFileError ObfuscatedFileUtil::GetFileInfoInternal( } if (local_info->data_path.empty()) return base::PLATFORM_FILE_ERROR_INVALID_OPERATION; - FileSystemPath local_path = DataPathToLocalPath( + FileSystemPath underlying_path = DataPathToUnderlyingPath( origin, type, local_info->data_path); - return underlying_file_util()->GetFileInfo( - context, local_path, file_info, platform_file_path); + base::PlatformFileError error = underlying_file_util()->GetFileInfo( + context, underlying_path, file_info, platform_file_path); + if (error == base::PLATFORM_FILE_ERROR_NOT_FOUND) { + LOG(WARNING) << "Lost a backing file."; + InvalidateUsageCache(context, origin, type); + if (!db->RemoveFileInfo(file_id)) + return base::PLATFORM_FILE_ERROR_FAILED; + } + return error; } PlatformFileError ObfuscatedFileUtil::CreateFile( FileSystemOperationContext* context, - const FileSystemPath& source_path, + const FilePath& src_file_path, const GURL& dest_origin, FileSystemType dest_type, FileInfo* dest_file_info, int file_flags, PlatformFile* handle) { @@ -1068,44 +1113,23 @@ PlatformFileError ObfuscatedFileUtil::CreateFile( *handle = base::kInvalidPlatformFileValue; FileSystemDirectoryDatabase* db = GetDirectoryDatabase( dest_origin, dest_type, true); - int64 number; - if (!db || !db->GetNextInteger(&number)) - return base::PLATFORM_FILE_ERROR_FAILED; - // We use the third- and fourth-to-last digits as the directory. - int64 directory_number = number % 10000 / 100; - // TODO(ericu): dest_file_path is an OS path; - // underlying_file_util_ isn't guaranteed to understand OS paths. - FilePath dest_file_path = - GetDirectoryForOriginAndType(dest_origin, dest_type, false); - if (dest_file_path.empty()) - return base::PLATFORM_FILE_ERROR_FAILED; - - dest_file_path = dest_file_path.AppendASCII( - StringPrintf("%02" PRIu64, directory_number)); - FileSystemPath dest_path(dest_origin, dest_type, dest_file_path); - PlatformFileError error; - error = underlying_file_util()->CreateDirectory( - context, - dest_path, - false /* exclusive */, false /* recursive */); - if (base::PLATFORM_FILE_OK != error) + FileSystemPath dest_path; + PlatformFileError error = GenerateNewUnderlyingPath( + db, context, dest_origin, dest_type, &dest_path); + if (error != base::PLATFORM_FILE_OK) return error; - dest_file_path = dest_file_path.AppendASCII( - StringPrintf("%08" PRIu64, number)); - dest_path.set_internal_path(dest_file_path); - - FilePath data_path = LocalPathToDataPath(dest_path); + FilePath data_path = UnderlyingPathToDataPath(dest_path); if (data_path.empty()) return base::PLATFORM_FILE_ERROR_FAILED; bool created = false; - if (!source_path.internal_path().empty()) { + if (!src_file_path.empty()) { DCHECK(!file_flags); DCHECK(!handle); - error = underlying_file_util()->CopyOrMoveFile( - context, source_path, dest_path, true /* copy */); + error = underlying_file_util()->CopyInForeignFile( + context, src_file_path, dest_path); created = true; } else { FilePath path; @@ -1116,8 +1140,7 @@ PlatformFileError ObfuscatedFileUtil::CreateFile( return base::PLATFORM_FILE_ERROR_FAILED; } LOG(WARNING) << "A stray file detected"; - context->file_system_context()->GetQuotaUtil(dest_type)-> - InvalidateUsageCache(dest_origin, dest_type); + InvalidateUsageCache(context, dest_origin, dest_type); } if (handle) { @@ -1157,26 +1180,26 @@ PlatformFileError ObfuscatedFileUtil::CreateFile( return base::PLATFORM_FILE_OK; } -FileSystemPath ObfuscatedFileUtil::GetLocalPath( - const FileSystemPath& virtual_path) { +FileSystemPath ObfuscatedFileUtil::GetUnderlyingPath( + const FileSystemPath& path) { FileSystemDirectoryDatabase* db = GetDirectoryDatabase( - virtual_path.origin(), virtual_path.type(), false); + path.origin(), path.type(), false); if (!db) return FileSystemPath(); FileId file_id; - if (!db->GetFileWithPath(virtual_path.internal_path(), &file_id)) + if (!db->GetFileWithPath(path.internal_path(), &file_id)) return FileSystemPath(); FileInfo file_info; if (!db->GetFileInfo(file_id, &file_info) || file_info.is_directory()) { NOTREACHED(); - return FileSystemPath(); // Directories have no local path. + return FileSystemPath(); // Directories have no underlying path. } - return DataPathToLocalPath(virtual_path.origin(), - virtual_path.type(), - file_info.data_path); + return DataPathToUnderlyingPath(path.origin(), + path.type(), + file_info.data_path); } -FileSystemPath ObfuscatedFileUtil::DataPathToLocalPath( +FileSystemPath ObfuscatedFileUtil::DataPathToUnderlyingPath( const GURL& origin, FileSystemType type, const FilePath& data_path) { FilePath root = GetDirectoryForOriginAndType(origin, type, false); if (root.empty()) @@ -1184,16 +1207,16 @@ FileSystemPath ObfuscatedFileUtil::DataPathToLocalPath( return FileSystemPath(origin, type, root.Append(data_path)); } -FilePath ObfuscatedFileUtil::LocalPathToDataPath( - const FileSystemPath& local_path) { +FilePath ObfuscatedFileUtil::UnderlyingPathToDataPath( + const FileSystemPath& underlying_path) { FilePath root = GetDirectoryForOriginAndType( - local_path.origin(), local_path.type(), false); + underlying_path.origin(), underlying_path.type(), false); if (root.empty()) return root; // This removes the root, including the trailing slash, leaving a relative // path. - FilePath internal_path = local_path.internal_path(); - return FilePath(internal_path.value().substr(root.value().length() + 1)); + FilePath local_file_path = underlying_path.internal_path(); + return FilePath(local_file_path.value().substr(root.value().length() + 1)); } // TODO: How to do the whole validation-without-creation thing? We may not have @@ -1280,6 +1303,14 @@ FilePath ObfuscatedFileUtil::GetDirectoryForOrigin( return path; } +void ObfuscatedFileUtil::InvalidateUsageCache( + FileSystemOperationContext* context, + const GURL& origin, + FileSystemType type) { + context->file_system_context()->GetQuotaUtil(type)-> + InvalidateUsageCache(origin, type); +} + void ObfuscatedFileUtil::MarkUsed() { if (timer_.IsRunning()) timer_.Reset(); @@ -1310,4 +1341,39 @@ bool ObfuscatedFileUtil::InitOriginDatabase(bool create) { return true; } +PlatformFileError ObfuscatedFileUtil::GenerateNewUnderlyingPath( + FileSystemDirectoryDatabase* db, + FileSystemOperationContext* context, + const GURL& origin, + FileSystemType type, + FileSystemPath* underlying_path) { + DCHECK(underlying_path); + int64 number; + if (!db || !db->GetNextInteger(&number)) + return base::PLATFORM_FILE_ERROR_FAILED; + + // We use the third- and fourth-to-last digits as the directory. + int64 directory_number = number % 10000 / 100; + // TODO(ericu): local_file_path is an OS path; + // underlying_file_util_ isn't guaranteed to understand OS paths. + FilePath local_file_path = GetDirectoryForOriginAndType(origin, type, false); + if (local_file_path.empty()) + return base::PLATFORM_FILE_ERROR_FAILED; + + local_file_path = local_file_path.AppendASCII( + StringPrintf("%02" PRId64, directory_number)); + + PlatformFileError error = underlying_file_util()->CreateDirectory( + context, FileSystemPath(origin, type, local_file_path), + false /* exclusive */, false /* recursive */); + if (error != base::PLATFORM_FILE_OK) + return error; + + local_file_path = local_file_path.AppendASCII( + StringPrintf("%08" PRId64, number)); + + *underlying_path = FileSystemPath(origin, type, local_file_path); + return base::PLATFORM_FILE_OK; +} + } // namespace fileapi diff --git a/webkit/fileapi/obfuscated_file_util.h b/webkit/fileapi/obfuscated_file_util.h index d967ca8..4d9e461 100644 --- a/webkit/fileapi/obfuscated_file_util.h +++ b/webkit/fileapi/obfuscated_file_util.h @@ -131,7 +131,7 @@ class ObfuscatedFileUtil virtual PlatformFileError CopyInForeignFile( FileSystemOperationContext* context, - const FileSystemPath& underlying_src_path, + const FilePath& src_file_path, const FileSystemPath& dest_path) OVERRIDE; virtual base::PlatformFileError DeleteFile( @@ -202,6 +202,7 @@ class ObfuscatedFileUtil typedef FileSystemDirectoryDatabase::FileId FileId; typedef FileSystemDirectoryDatabase::FileInfo FileInfo; + friend class ObfuscatedFileEnumerator; virtual ~ObfuscatedFileUtil(); base::PlatformFileError GetFileInfoInternal( @@ -227,28 +228,28 @@ class ObfuscatedFileUtil // DCHECK and handle will hold base::kInvalidPlatformFileValue. base::PlatformFileError CreateFile( FileSystemOperationContext* context, - const FileSystemPath& source_path, + const FilePath& source_file_path, const GURL& dest_origin, FileSystemType dest_type, FileInfo* dest_file_info, int file_flags, base::PlatformFile* handle); - // Given a virtual path, produces a real, full local path to the + // Given a virtual path, produces a real, full underlying path to the // underlying data file. This does a database lookup (by - // calling DataPathToLocalPath()), and verifies that the file exists. - FileSystemPath GetLocalPath(const FileSystemPath& virtual_path); + // calling DataPathToUnderlyingPath()), and verifies that the file exists. + FileSystemPath GetUnderlyingPath(const FileSystemPath& virtual_path); // This converts from a relative path [as is stored in the FileInfo.data_path - // field] to an absolute local path that can be given to the underlying + // field] to an absolute underlying path that can be given to the underlying // filesystem (as of now the returned path is assumed to be a platform path). - FileSystemPath DataPathToLocalPath( + FileSystemPath DataPathToUnderlyingPath( const GURL& origin, FileSystemType type, const FilePath& data_file_path); - // This does the reverse of DataPathToLocalPath. - FilePath LocalPathToDataPath(const FileSystemPath& local_path); + // This does the reverse of DataPathToUnderlyingPath. + FilePath UnderlyingPathToDataPath(const FileSystemPath& underlying_path); // This returns NULL if |create| flag is false and a filesystem does not // exist for the given |origin_url| and |type|. @@ -262,10 +263,21 @@ class ObfuscatedFileUtil bool create, base::PlatformFileError* error_code); + void InvalidateUsageCache(FileSystemOperationContext* context, + const GURL& origin, + FileSystemType type); + void MarkUsed(); void DropDatabases(); bool InitOriginDatabase(bool create); + base::PlatformFileError GenerateNewUnderlyingPath( + FileSystemDirectoryDatabase* db, + FileSystemOperationContext* context, + const GURL& origin, + FileSystemType type, + FileSystemPath* underlying_path); + typedef std::map<std::string, FileSystemDirectoryDatabase*> DirectoryMap; DirectoryMap directories_; scoped_ptr<FileSystemOriginDatabase> origin_database_; diff --git a/webkit/fileapi/obfuscated_file_util_unittest.cc b/webkit/fileapi/obfuscated_file_util_unittest.cc index 95a62fb..beb0f19 100644 --- a/webkit/fileapi/obfuscated_file_util_unittest.cc +++ b/webkit/fileapi/obfuscated_file_util_unittest.cc @@ -140,6 +140,18 @@ class ObfuscatedFileUtilTest : public testing::Test { test_helper_.TearDown(); } + scoped_ptr<FileSystemOperationContext> LimitedContext( + int64 allowed_bytes_growth) { + scoped_ptr<FileSystemOperationContext> context( + test_helper_.NewOperationContext()); + context->set_allowed_bytes_growth(allowed_bytes_growth); + return context.Pass(); + } + + scoped_ptr<FileSystemOperationContext> UnlimitedContext() { + return LimitedContext(kint64max); + } + FileSystemOperationContext* NewContext(FileSystemTestOriginHelper* helper) { FileSystemOperationContext* context; if (helper) @@ -180,6 +192,11 @@ class ObfuscatedFileUtilTest : public testing::Test { return type_; } + int64 ComputeTotalFileSize() { + return test_helper_.ComputeCurrentOriginUsage() - + test_helper_.ComputeCurrentDirectoryDatabaseUsage(); + } + void GetUsageFromQuotaManager() { quota_manager_->GetUsageAndQuota( origin(), test_helper_.storage_type(), @@ -204,6 +221,10 @@ class ObfuscatedFileUtilTest : public testing::Test { return test_helper_.CreatePathFromUTF8(path); } + int64 PathCost(const FileSystemPath& path) { + return ObfuscatedFileUtil::ComputeFilePathCost(path.internal_path()); + } + FileSystemPath CreatePath(const FilePath& path) { return test_helper_.CreatePath(path); } @@ -295,6 +316,48 @@ class ObfuscatedFileUtilTest : public testing::Test { } } + class UsageVerifyHelper { + public: + UsageVerifyHelper(scoped_ptr<FileSystemOperationContext> context, + FileSystemTestOriginHelper* test_helper, + int64 expected_usage) + : context_(context.Pass()), + test_helper_(test_helper), + expected_usage_(expected_usage) {} + + ~UsageVerifyHelper() { + Check(); + } + + FileSystemOperationContext* context() { + return context_.get(); + } + + private: + void Check() { + ASSERT_EQ(expected_usage_, + test_helper_->GetCachedOriginUsage()); + } + + scoped_ptr<FileSystemOperationContext> context_; + FileSystemTestOriginHelper* test_helper_; + int64 growth_; + int64 expected_usage_; + }; + + scoped_ptr<UsageVerifyHelper> AllowUsageIncrease(int64 requested_growth) { + int64 usage = test_helper_.GetCachedOriginUsage(); + return scoped_ptr<UsageVerifyHelper>(new UsageVerifyHelper( + LimitedContext(requested_growth), + &test_helper_, usage + requested_growth)); + } + + scoped_ptr<UsageVerifyHelper> DisallowUsageIncrease(int64 requested_growth) { + int64 usage = test_helper_.GetCachedOriginUsage(); + return scoped_ptr<UsageVerifyHelper>(new UsageVerifyHelper( + LimitedContext(requested_growth - 1), &test_helper_, usage)); + } + void FillTestDirectory( const FileSystemPath& root_path, std::set<FilePath::StringType>* files, @@ -404,7 +467,6 @@ class ObfuscatedFileUtilTest : public testing::Test { FilePath root_file_path = source_dir.path(); FilePath src_file_path = root_file_path.AppendASCII("file_name"); FileSystemPath dest_path = CreatePathFromUTF8("new file"); - FileSystemPath src_path = CreatePath(src_file_path); int64 src_file_length = 87; base::PlatformFileError error_code; @@ -435,13 +497,15 @@ class ObfuscatedFileUtilTest : public testing::Test { context.reset(NewContext(NULL)); context->set_allowed_bytes_growth(path_cost + src_file_length - 1); EXPECT_EQ(base::PLATFORM_FILE_ERROR_NO_SPACE, - ofu()->CopyInForeignFile(context.get(), src_path, dest_path)); + ofu()->CopyInForeignFile(context.get(), + src_file_path, dest_path)); } context.reset(NewContext(NULL)); context->set_allowed_bytes_growth(path_cost + src_file_length); EXPECT_EQ(base::PLATFORM_FILE_OK, - ofu()->CopyInForeignFile(context.get(), src_path, dest_path)); + ofu()->CopyInForeignFile(context.get(), + src_file_path, dest_path)); context.reset(NewContext(NULL)); EXPECT_TRUE(ofu()->PathExists(context.get(), dest_path)); @@ -663,75 +727,68 @@ TEST_F(ObfuscatedFileUtilTest, TestTruncate) { TEST_F(ObfuscatedFileUtilTest, TestQuotaOnTruncation) { bool created = false; FileSystemPath path = CreatePathFromUTF8("file"); - scoped_ptr<FileSystemOperationContext> context(NewContext(NULL)); ASSERT_EQ(base::PLATFORM_FILE_OK, - ofu()->EnsureFileExists(context.get(), path, &created)); + ofu()->EnsureFileExists( + AllowUsageIncrease(PathCost(path))->context(), + path, &created)); ASSERT_TRUE(created); + ASSERT_EQ(0, ComputeTotalFileSize()); - int64 path_cost = test_helper().GetCachedOriginUsage(); - - context.reset(NewContext(NULL)); - context->set_allowed_bytes_growth(1020); ASSERT_EQ(base::PLATFORM_FILE_OK, - ofu()->Truncate(context.get(), path, 1020)); - ASSERT_EQ(path_cost + 1020, test_helper().GetCachedOriginUsage()); - ASSERT_EQ(path_cost + ComputeCurrentUsage(), - test_helper().GetCachedOriginUsage()); + ofu()->Truncate( + AllowUsageIncrease(1020)->context(), + path, 1020)); + ASSERT_EQ(1020, ComputeTotalFileSize()); - context.reset(NewContext(NULL)); - context->set_allowed_bytes_growth(0); ASSERT_EQ(base::PLATFORM_FILE_OK, - ofu()->Truncate(context.get(), path, 0)); - ASSERT_EQ(path_cost + 0, test_helper().GetCachedOriginUsage()); - ASSERT_EQ(path_cost + ComputeCurrentUsage(), - test_helper().GetCachedOriginUsage()); + ofu()->Truncate( + AllowUsageIncrease(-1020)->context(), + path, 0)); + ASSERT_EQ(0, ComputeTotalFileSize()); - context.reset(NewContext(NULL)); - context->set_allowed_bytes_growth(1020); EXPECT_EQ(base::PLATFORM_FILE_ERROR_NO_SPACE, - ofu()->Truncate(context.get(), path, 1021)); - ASSERT_EQ(path_cost + 0, test_helper().GetCachedOriginUsage()); - ASSERT_EQ(path_cost + ComputeCurrentUsage(), - test_helper().GetCachedOriginUsage()); - - context.reset(NewContext(NULL)); - context->set_allowed_bytes_growth(1020); - EXPECT_EQ(base::PLATFORM_FILE_OK, - ofu()->Truncate(context.get(), path, 1020)); - ASSERT_EQ(path_cost + 1020, test_helper().GetCachedOriginUsage()); - ASSERT_EQ(path_cost + ComputeCurrentUsage(), - test_helper().GetCachedOriginUsage()); + ofu()->Truncate( + DisallowUsageIncrease(1021)->context(), + path, 1021)); + ASSERT_EQ(0, ComputeTotalFileSize()); - context.reset(NewContext(NULL)); - context->set_allowed_bytes_growth(0); EXPECT_EQ(base::PLATFORM_FILE_OK, - ofu()->Truncate(context.get(), path, 1020)); - ASSERT_EQ(path_cost + 1020, test_helper().GetCachedOriginUsage()); - ASSERT_EQ(path_cost + ComputeCurrentUsage(), - test_helper().GetCachedOriginUsage()); + ofu()->Truncate( + AllowUsageIncrease(1020)->context(), + path, 1020)); + ASSERT_EQ(1020, ComputeTotalFileSize()); - context.reset(NewContext(NULL)); - context->set_allowed_bytes_growth(-2); // quota exceeded EXPECT_EQ(base::PLATFORM_FILE_OK, - ofu()->Truncate(context.get(), path, 1019)); - ASSERT_EQ(path_cost + 1019, test_helper().GetCachedOriginUsage()); - ASSERT_EQ(path_cost + ComputeCurrentUsage(), - test_helper().GetCachedOriginUsage()); + ofu()->Truncate( + AllowUsageIncrease(0)->context(), + path, 1020)); + ASSERT_EQ(1020, ComputeTotalFileSize()); + + // quota exceeded + { + scoped_ptr<UsageVerifyHelper> helper = AllowUsageIncrease(-1); + helper->context()->set_allowed_bytes_growth( + helper->context()->allowed_bytes_growth() - 1); + EXPECT_EQ(base::PLATFORM_FILE_OK, + ofu()->Truncate(helper->context(), path, 1019)); + ASSERT_EQ(1019, ComputeTotalFileSize()); + } // Delete backing file to make following truncation fail. - context.reset(NewContext(NULL)); FilePath local_path; ASSERT_EQ(base::PLATFORM_FILE_OK, - ofu()->GetLocalFilePath(context.get(), path, &local_path)); + ofu()->GetLocalFilePath( + UnlimitedContext().get(), + path, &local_path)); ASSERT_FALSE(local_path.empty()); ASSERT_TRUE(file_util::Delete(local_path, false)); - context.reset(NewContext(NULL)); - context->set_allowed_bytes_growth(1234); EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, - ofu()->Truncate(context.get(), path, 1234)); - ASSERT_EQ(path_cost + 1019, test_helper().GetCachedOriginUsage()); + ofu()->Truncate( + LimitedContext(1234).get(), + path, 1234)); + ASSERT_EQ(0, ComputeTotalFileSize()); } TEST_F(ObfuscatedFileUtilTest, TestEnsureFileExists) { @@ -1683,7 +1740,7 @@ TEST_F(ObfuscatedFileUtilTest, TestDirectoryTimestampForCreation) { context.reset(NewContext(NULL)); EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->CopyInForeignFile(context.get(), - CreatePath(src_local_path), + src_local_path, path)); EXPECT_NE(base::Time(), GetModifiedTime(dir_path)); } @@ -1810,3 +1867,264 @@ TEST_F(ObfuscatedFileUtilTest, TestFileEnumeratorTimestamp) { } EXPECT_EQ(2, count); } + +TEST_F(ObfuscatedFileUtilTest, TestQuotaOnCopyFile) { + FileSystemPath from_file(CreatePathFromUTF8("fromfile")); + FileSystemPath obstacle_file(CreatePathFromUTF8("obstaclefile")); + FileSystemPath to_file1(CreatePathFromUTF8("tofile1")); + FileSystemPath to_file2(CreatePathFromUTF8("tofile2")); + bool created; + + int64 expected_total_file_size = 0; + ASSERT_EQ(base::PLATFORM_FILE_OK, + ofu()->EnsureFileExists( + AllowUsageIncrease(PathCost(from_file))->context(), + from_file, &created)); + ASSERT_TRUE(created); + ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize()); + + ASSERT_EQ(base::PLATFORM_FILE_OK, + ofu()->EnsureFileExists( + AllowUsageIncrease(PathCost(obstacle_file))->context(), + obstacle_file, &created)); + ASSERT_TRUE(created); + ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize()); + + int64 from_file_size = 1020; + expected_total_file_size += from_file_size; + ASSERT_EQ(base::PLATFORM_FILE_OK, + ofu()->Truncate( + AllowUsageIncrease(from_file_size)->context(), + from_file, from_file_size)); + ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize()); + + int64 obstacle_file_size = 1; + expected_total_file_size += obstacle_file_size; + ASSERT_EQ(base::PLATFORM_FILE_OK, + ofu()->Truncate( + AllowUsageIncrease(obstacle_file_size)->context(), + obstacle_file, obstacle_file_size)); + ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize()); + + int64 to_file1_size = from_file_size; + expected_total_file_size += to_file1_size; + ASSERT_EQ(base::PLATFORM_FILE_OK, + ofu()->CopyOrMoveFile( + AllowUsageIncrease( + PathCost(to_file1) + to_file1_size)->context(), + from_file, to_file1, true /* copy */)); + ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize()); + + ASSERT_EQ(base::PLATFORM_FILE_ERROR_NO_SPACE, + ofu()->CopyOrMoveFile( + DisallowUsageIncrease( + PathCost(to_file2) + from_file_size)->context(), + from_file, to_file2, true /* copy */)); + ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize()); + + int64 old_obstacle_file_size = obstacle_file_size; + obstacle_file_size = from_file_size; + expected_total_file_size += obstacle_file_size - old_obstacle_file_size; + ASSERT_EQ(base::PLATFORM_FILE_OK, + ofu()->CopyOrMoveFile( + AllowUsageIncrease( + obstacle_file_size - old_obstacle_file_size)->context(), + from_file, obstacle_file, true /* copy */)); + ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize()); + + int64 old_from_file_size = from_file_size; + from_file_size = old_from_file_size - 1; + expected_total_file_size += from_file_size - old_from_file_size; + ASSERT_EQ(base::PLATFORM_FILE_OK, + ofu()->Truncate( + AllowUsageIncrease( + from_file_size - old_from_file_size)->context(), + from_file, from_file_size)); + ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize()); + + // quota exceeded + { + old_obstacle_file_size = obstacle_file_size; + obstacle_file_size = from_file_size; + expected_total_file_size += obstacle_file_size - old_obstacle_file_size; + scoped_ptr<UsageVerifyHelper> helper = AllowUsageIncrease( + obstacle_file_size - old_obstacle_file_size); + helper->context()->set_allowed_bytes_growth( + helper->context()->allowed_bytes_growth() - 1); + ASSERT_EQ(base::PLATFORM_FILE_OK, + ofu()->CopyOrMoveFile( + helper->context(), + from_file, obstacle_file, true /* copy */)); + ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize()); + } +} + +TEST_F(ObfuscatedFileUtilTest, TestQuotaOnMoveFile) { + FileSystemPath from_file(CreatePathFromUTF8("fromfile")); + FileSystemPath obstacle_file(CreatePathFromUTF8("obstaclefile")); + FileSystemPath to_file(CreatePathFromUTF8("tofile")); + bool created; + + int64 expected_total_file_size = 0; + ASSERT_EQ(base::PLATFORM_FILE_OK, + ofu()->EnsureFileExists( + AllowUsageIncrease(PathCost(from_file))->context(), + from_file, &created)); + ASSERT_TRUE(created); + ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize()); + + int64 from_file_size = 1020; + expected_total_file_size += from_file_size; + ASSERT_EQ(base::PLATFORM_FILE_OK, + ofu()->Truncate( + AllowUsageIncrease(from_file_size)->context(), + from_file, from_file_size)); + ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize()); + + int64 to_file_size ALLOW_UNUSED = from_file_size; + from_file_size = 0; + ASSERT_EQ(base::PLATFORM_FILE_OK, + ofu()->CopyOrMoveFile( + AllowUsageIncrease(-PathCost(from_file) + + PathCost(to_file))->context(), + from_file, to_file, false /* move */)); + ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize()); + + ASSERT_EQ(base::PLATFORM_FILE_OK, + ofu()->EnsureFileExists( + AllowUsageIncrease(PathCost(from_file))->context(), + from_file, &created)); + ASSERT_TRUE(created); + ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize()); + + ASSERT_EQ(base::PLATFORM_FILE_OK, + ofu()->EnsureFileExists( + AllowUsageIncrease(PathCost(obstacle_file))->context(), + obstacle_file, &created)); + ASSERT_TRUE(created); + ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize()); + + from_file_size = 1020; + expected_total_file_size += from_file_size; + ASSERT_EQ(base::PLATFORM_FILE_OK, + ofu()->Truncate( + AllowUsageIncrease(from_file_size)->context(), + from_file, from_file_size)); + ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize()); + + int64 obstacle_file_size = 1; + expected_total_file_size += obstacle_file_size; + ASSERT_EQ(base::PLATFORM_FILE_OK, + ofu()->Truncate( + AllowUsageIncrease(1)->context(), + obstacle_file, obstacle_file_size)); + ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize()); + + int64 old_obstacle_file_size = obstacle_file_size; + obstacle_file_size = from_file_size; + from_file_size = 0; + expected_total_file_size -= old_obstacle_file_size; + ASSERT_EQ(base::PLATFORM_FILE_OK, + ofu()->CopyOrMoveFile( + AllowUsageIncrease( + -old_obstacle_file_size - PathCost(from_file))->context(), + from_file, obstacle_file, + false /* move */)); + ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize()); + + ASSERT_EQ(base::PLATFORM_FILE_OK, + ofu()->EnsureFileExists( + AllowUsageIncrease(PathCost(from_file))->context(), + from_file, &created)); + ASSERT_TRUE(created); + ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize()); + + from_file_size = 10; + expected_total_file_size += from_file_size; + ASSERT_EQ(base::PLATFORM_FILE_OK, + ofu()->Truncate( + AllowUsageIncrease(from_file_size)->context(), + from_file, from_file_size)); + ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize()); + + // quota exceeded even after operation + old_obstacle_file_size = obstacle_file_size; + obstacle_file_size = from_file_size; + from_file_size = 0; + expected_total_file_size -= old_obstacle_file_size; + scoped_ptr<FileSystemOperationContext> context = + LimitedContext(-old_obstacle_file_size - PathCost(from_file) - 1); + ASSERT_EQ(base::PLATFORM_FILE_OK, + ofu()->CopyOrMoveFile( + context.get(), from_file, obstacle_file, false /* move */)); + ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize()); + context.reset(); +} + +TEST_F(ObfuscatedFileUtilTest, TestQuotaOnRemove) { + FileSystemPath dir(CreatePathFromUTF8("dir")); + FileSystemPath file(CreatePathFromUTF8("file")); + FileSystemPath dfile1(CreatePathFromUTF8("dir/dfile1")); + FileSystemPath dfile2(CreatePathFromUTF8("dir/dfile2")); + bool created; + + ASSERT_EQ(base::PLATFORM_FILE_OK, + ofu()->EnsureFileExists( + AllowUsageIncrease(PathCost(file))->context(), + file, &created)); + ASSERT_TRUE(created); + ASSERT_EQ(0, ComputeTotalFileSize()); + + ASSERT_EQ(base::PLATFORM_FILE_OK, + ofu()->CreateDirectory( + AllowUsageIncrease(PathCost(dir))->context(), + dir, false, false)); + ASSERT_EQ(0, ComputeTotalFileSize()); + + ASSERT_EQ(base::PLATFORM_FILE_OK, + ofu()->EnsureFileExists( + AllowUsageIncrease(PathCost(dfile1))->context(), + dfile1, &created)); + ASSERT_TRUE(created); + ASSERT_EQ(0, ComputeTotalFileSize()); + + ASSERT_EQ(base::PLATFORM_FILE_OK, + ofu()->EnsureFileExists( + AllowUsageIncrease(PathCost(dfile2))->context(), + dfile2, &created)); + ASSERT_TRUE(created); + ASSERT_EQ(0, ComputeTotalFileSize()); + + ASSERT_EQ(base::PLATFORM_FILE_OK, + ofu()->Truncate( + AllowUsageIncrease(340)->context(), + file, 340)); + ASSERT_EQ(340, ComputeTotalFileSize()); + + ASSERT_EQ(base::PLATFORM_FILE_OK, + ofu()->Truncate( + AllowUsageIncrease(1020)->context(), + dfile1, 1020)); + ASSERT_EQ(1360, ComputeTotalFileSize()); + + ASSERT_EQ(base::PLATFORM_FILE_OK, + ofu()->Truncate( + AllowUsageIncrease(120)->context(), + dfile2, 120)); + ASSERT_EQ(1480, ComputeTotalFileSize()); + + ASSERT_EQ(base::PLATFORM_FILE_OK, + ofu()->DeleteFile( + AllowUsageIncrease(-PathCost(file) - 340)->context(), + file)); + ASSERT_EQ(1140, ComputeTotalFileSize()); + + ASSERT_EQ(base::PLATFORM_FILE_OK, + FileUtilHelper::Delete( + AllowUsageIncrease(-PathCost(dir) - + PathCost(dfile1) - + PathCost(dfile2) - + 1020 - 120)->context(), + ofu(), dir, true)); + ASSERT_EQ(0, ComputeTotalFileSize()); +} diff --git a/webkit/fileapi/quota_file_util.cc b/webkit/fileapi/quota_file_util.cc deleted file mode 100644 index 3f3462f..0000000 --- a/webkit/fileapi/quota_file_util.cc +++ /dev/null @@ -1,168 +0,0 @@ -// Copyright (c) 2012 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/fileapi/quota_file_util.h" - -#include "base/file_util.h" -#include "base/logging.h" -#include "webkit/fileapi/file_system_context.h" -#include "webkit/fileapi/file_system_operation_context.h" -#include "webkit/fileapi/file_system_quota_util.h" -#include "webkit/fileapi/native_file_util.h" -#include "webkit/quota/quota_manager.h" - -using quota::QuotaManagerProxy; - -namespace fileapi { - -const int64 QuotaFileUtil::kNoLimit = kint64max; - -namespace { - -// Checks if copying in the same filesystem can be performed. -// This method is not called for moving within a single filesystem. -// Note: this method assumes the underlying file system uses platform -// file paths. -bool CanCopy( - const FilePath& src_file_path, - const FilePath& dest_file_path, - int64 allowed_bytes_growth, - int64* growth) { - base::PlatformFileInfo src_file_info; - if (!file_util::GetFileInfo(src_file_path, &src_file_info)) { - // Falling through to the actual copy/move operation. - return true; - } - base::PlatformFileInfo dest_file_info; - if (!file_util::GetFileInfo(dest_file_path, &dest_file_info)) - dest_file_info.size = 0; - int64 growth_local = src_file_info.size - dest_file_info.size; - if (allowed_bytes_growth != QuotaFileUtil::kNoLimit && - growth_local > 0 && growth_local > allowed_bytes_growth) - return false; - if (growth != NULL) - *growth = growth_local; - - return true; -} - -void NotifyUpdate(FileSystemOperationContext* operation_context, - const GURL& origin, - FileSystemType type, - int64 growth) { - DCHECK(operation_context); - DCHECK(operation_context->file_system_context()); - DCHECK(type != kFileSystemTypeUnknown); - - FileSystemQuotaUtil* quota_util = - operation_context->file_system_context()->GetQuotaUtil(type); - QuotaManagerProxy* quota_manager_proxy = - operation_context->file_system_context()->quota_manager_proxy(); - - operation_context->set_allowed_bytes_growth( - operation_context->allowed_bytes_growth() - growth); - if (quota_util) - quota_util->UpdateOriginUsageOnFileThread( - quota_manager_proxy, origin, type, growth); -} - -} // namespace (anonymous) - -QuotaFileUtil::QuotaFileUtil(FileSystemFileUtil* underlying_file_util) - : FileSystemFileUtil(underlying_file_util) { -} - -QuotaFileUtil::~QuotaFileUtil() { -} - -// static -QuotaFileUtil* QuotaFileUtil::CreateDefault() { - return new QuotaFileUtil(new NativeFileUtil()); -} - -base::PlatformFileError QuotaFileUtil::TruncateInternal( - FileSystemOperationContext* fs_context, - const FileSystemPath& path, - int64 length) { - int64 allowed_bytes_growth = fs_context->allowed_bytes_growth(); - - int64 growth = 0; - base::PlatformFileInfo file_info; - if (!file_util::GetFileInfo(path.internal_path(), &file_info)) - return base::PLATFORM_FILE_ERROR_FAILED; - - growth = length - file_info.size; - if (allowed_bytes_growth != kNoLimit && - growth > 0 && growth > allowed_bytes_growth) - return base::PLATFORM_FILE_ERROR_NO_SPACE; - - base::PlatformFileError error = underlying_file_util()->Truncate( - fs_context, path, length); - - if (error == base::PLATFORM_FILE_OK) - NotifyUpdate(fs_context, path.origin(), path.type(), - growth); - - return error; -} - -base::PlatformFileError QuotaFileUtil::CopyOrMoveFile( - FileSystemOperationContext* fs_context, - const FileSystemPath& src_path, - const FileSystemPath& dest_path, - bool copy) { - DCHECK(fs_context); - - int64 growth = 0; - - // It assumes copy/move operations are always in the same fs currently. - // TODO(dmikurube): Do quota check if moving between different fs. - // TODO(kinuko,kinaba): FileSystemFileUtil shouldn't support cross-filesystem - // operations from the beginning. - if (copy) { - int64 allowed_bytes_growth = fs_context->allowed_bytes_growth(); - // The third argument (growth) is not used for now. - if (!CanCopy(src_path.internal_path(), dest_path.internal_path(), - allowed_bytes_growth, &growth)) - return base::PLATFORM_FILE_ERROR_NO_SPACE; - } else { - base::PlatformFileInfo dest_file_info; - if (!file_util::GetFileInfo(dest_path.internal_path(), &dest_file_info)) - dest_file_info.size = 0; - growth = -dest_file_info.size; - } - - base::PlatformFileError error = underlying_file_util()->CopyOrMoveFile( - fs_context, src_path, dest_path, copy); - - if (error == base::PLATFORM_FILE_OK) { - // TODO(kinuko): For cross-filesystem move case, call this with -growth - // for source and growth for dest. - NotifyUpdate(fs_context, dest_path.origin(), dest_path.type(), growth); - } - - return error; -} - -base::PlatformFileError QuotaFileUtil::DeleteFile( - FileSystemOperationContext* fs_context, - const FileSystemPath& path) { - DCHECK(fs_context); - - int64 growth = 0; - base::PlatformFileInfo file_info; - if (!file_util::GetFileInfo(path.internal_path(), &file_info)) - file_info.size = 0; - growth = -file_info.size; - - base::PlatformFileError error = underlying_file_util()->DeleteFile( - fs_context, path); - - if (error == base::PLATFORM_FILE_OK) - NotifyUpdate(fs_context, path.origin(), path.type(), growth); - - return error; -} - -} // namespace fileapi diff --git a/webkit/fileapi/quota_file_util.h b/webkit/fileapi/quota_file_util.h deleted file mode 100644 index 87fedc5..0000000 --- a/webkit/fileapi/quota_file_util.h +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright (c) 2012 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_FILEAPI_QUOTA_FILE_UTIL_H_ -#define WEBKIT_FILEAPI_QUOTA_FILE_UTIL_H_ - -#include "base/memory/scoped_ptr.h" -#include "webkit/fileapi/file_system_file_util.h" -#include "webkit/fileapi/file_system_operation_context.h" -#pragma once - -namespace fileapi { - -class QuotaFileUtil : public FileSystemFileUtil { - public: - static const int64 kNoLimit; - - // |underlying_file_util| is owned by the instance. It will be deleted by - // the owner instance. For example, it can be instanciated as follows: - // FileSystemFileUtil* file_util = new QuotaFileUtil(new SomeFileUtil()); - // - // To instanciate an object whose underlying file_util is FileSystemFileUtil, - // QuotaFileUtil::CreateDefault() can be used. - explicit QuotaFileUtil(FileSystemFileUtil* underlying_file_util); - virtual ~QuotaFileUtil(); - - // Creates a QuotaFileUtil instance with an underlying NativeFileUtil - // instance. - static QuotaFileUtil* CreateDefault(); - - virtual base::PlatformFileError CopyOrMoveFile( - FileSystemOperationContext* fs_context, - const FileSystemPath& src_path, - const FileSystemPath& dest_path, - bool copy) OVERRIDE; - virtual base::PlatformFileError DeleteFile( - FileSystemOperationContext* fs_context, - const FileSystemPath& path) OVERRIDE; - - // TODO(tzik): Remove this after we complete merging QuotaFileUtil - // into ObfuscatedFileUtil. TruncateInternal should be used in test and - // other methods of QuotaFileUtil. - base::PlatformFileError TruncateInternal( - FileSystemOperationContext* fs_context, - const FileSystemPath& path, - int64 length); - - private: - DISALLOW_COPY_AND_ASSIGN(QuotaFileUtil); -}; - -} // namespace fileapi - -#endif // WEBKIT_FILEAPI_QUOTA_FILE_UTIL_H_ diff --git a/webkit/fileapi/quota_file_util_unittest.cc b/webkit/fileapi/quota_file_util_unittest.cc deleted file mode 100644 index 16e99a1..0000000 --- a/webkit/fileapi/quota_file_util_unittest.cc +++ /dev/null @@ -1,457 +0,0 @@ -// Copyright (c) 2012 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/fileapi/quota_file_util.h" - -#include <string> - -#include "base/file_path.h" -#include "base/message_loop_proxy.h" -#include "base/platform_file.h" -#include "base/scoped_temp_dir.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "webkit/fileapi/file_system_context.h" -#include "webkit/fileapi/file_system_operation_context.h" -#include "webkit/fileapi/file_system_test_helper.h" -#include "webkit/fileapi/file_system_types.h" -#include "webkit/fileapi/file_system_usage_cache.h" -#include "webkit/fileapi/file_util_helper.h" - -namespace fileapi { - -class QuotaFileUtilTest : public testing::Test { - public: - QuotaFileUtilTest() {} - - void SetUp() { - ASSERT_TRUE(data_dir_.CreateUniqueTempDir()); - quota_file_util_.reset(QuotaFileUtil::CreateDefault()); - quota_test_helper_.SetUp(data_dir_.path(), quota_file_util_.get()); - base_dir_ = quota_test_helper_.GetOriginRootPath(); - } - - void TearDown() { - quota_test_helper_.TearDown(); - } - - protected: - FileSystemOperationContext* NewContext() { - return quota_test_helper_.NewOperationContext(); - } - - FileSystemPath Path(const std::string& file_name) { - return quota_test_helper_.CreatePath(base_dir_.AppendASCII(file_name)); - } - - base::PlatformFileError CreateFile(const char* file_name, - base::PlatformFile* file_handle, bool* created) { - int file_flags = base::PLATFORM_FILE_CREATE | - base::PLATFORM_FILE_WRITE | base::PLATFORM_FILE_ASYNC; - - scoped_ptr<FileSystemOperationContext> context(NewContext()); - return quota_file_util()->CreateOrOpen( - context.get(), Path(file_name), file_flags, file_handle, created); - } - - base::PlatformFileError EnsureFileExists( - const char* file_name, bool* created) { - scoped_ptr<FileSystemOperationContext> context(NewContext()); - return quota_file_util_->EnsureFileExists( - context.get(), Path(file_name), created); - } - - QuotaFileUtil* quota_file_util() const { - return quota_file_util_.get(); - } - - const FileSystemTestOriginHelper& quota_test_helper() const { - return quota_test_helper_; - } - - private: - ScopedTempDir data_dir_; - FilePath base_dir_; - FileSystemTestOriginHelper quota_test_helper_; - scoped_ptr<QuotaFileUtil> quota_file_util_; - - DISALLOW_COPY_AND_ASSIGN(QuotaFileUtilTest); -}; - -TEST_F(QuotaFileUtilTest, CreateAndClose) { - const char *file_name = "test_file"; - base::PlatformFile file_handle; - bool created; - ASSERT_EQ(base::PLATFORM_FILE_OK, - CreateFile(file_name, &file_handle, &created)); - ASSERT_TRUE(created); - - scoped_ptr<FileSystemOperationContext> context(NewContext()); - EXPECT_EQ(base::PLATFORM_FILE_OK, - quota_file_util()->Close(context.get(), file_handle)); -} - -TEST_F(QuotaFileUtilTest, CopyFile) { - const char *from_file = "fromfile"; - const char *obstacle_file = "obstaclefile"; - const char *to_file1 = "tofile1"; - const char *to_file2 = "tofile2"; - bool created; - ASSERT_EQ(base::PLATFORM_FILE_OK, EnsureFileExists(from_file, &created)); - ASSERT_TRUE(created); - ASSERT_EQ(base::PLATFORM_FILE_OK, EnsureFileExists(obstacle_file, &created)); - ASSERT_TRUE(created); - scoped_ptr<FileSystemOperationContext> context; - - context.reset(NewContext()); - context->set_allowed_bytes_growth(QuotaFileUtil::kNoLimit); - ASSERT_EQ(base::PLATFORM_FILE_OK, - quota_file_util()->TruncateInternal( - context.get(), Path(from_file), 1020)); - ASSERT_EQ(1020, quota_test_helper().GetCachedOriginUsage()); - ASSERT_EQ(quota_test_helper().ComputeCurrentOriginUsage(), - quota_test_helper().GetCachedOriginUsage()); - - context.reset(NewContext()); - context->set_allowed_bytes_growth(QuotaFileUtil::kNoLimit); - ASSERT_EQ(base::PLATFORM_FILE_OK, - quota_file_util()->TruncateInternal( - context.get(), Path(obstacle_file), 1)); - ASSERT_EQ(1021, quota_test_helper().GetCachedOriginUsage()); - ASSERT_EQ(quota_test_helper().ComputeCurrentOriginUsage(), - quota_test_helper().GetCachedOriginUsage()); - - context.reset(NewContext()); - context->set_allowed_bytes_growth(1020); - ASSERT_EQ(base::PLATFORM_FILE_OK, - quota_test_helper().SameFileUtilCopy( - context.get(), - Path(from_file), - Path(to_file1))); - ASSERT_EQ(2041, quota_test_helper().GetCachedOriginUsage()); - ASSERT_EQ(quota_test_helper().ComputeCurrentOriginUsage(), - quota_test_helper().GetCachedOriginUsage()); - - context.reset(NewContext()); - context->set_allowed_bytes_growth(1019); - ASSERT_EQ(base::PLATFORM_FILE_ERROR_NO_SPACE, - quota_test_helper().SameFileUtilCopy( - context.get(), - Path(from_file), - Path(to_file2))); - ASSERT_EQ(2041, quota_test_helper().GetCachedOriginUsage()); - ASSERT_EQ(quota_test_helper().ComputeCurrentOriginUsage(), - quota_test_helper().GetCachedOriginUsage()); - - context.reset(NewContext()); - context->set_allowed_bytes_growth(1019); - ASSERT_EQ(base::PLATFORM_FILE_OK, - quota_test_helper().SameFileUtilCopy( - context.get(), - Path(from_file), - Path(obstacle_file))); - ASSERT_EQ(3060, quota_test_helper().GetCachedOriginUsage()); - ASSERT_EQ(quota_test_helper().ComputeCurrentOriginUsage(), - quota_test_helper().GetCachedOriginUsage()); - - context.reset(NewContext()); - context->set_allowed_bytes_growth(QuotaFileUtil::kNoLimit); - ASSERT_EQ(base::PLATFORM_FILE_OK, - quota_file_util()->TruncateInternal( - context.get(), Path(from_file), 1019)); - ASSERT_EQ(3059, quota_test_helper().GetCachedOriginUsage()); - ASSERT_EQ(quota_test_helper().ComputeCurrentOriginUsage(), - quota_test_helper().GetCachedOriginUsage()); - - context.reset(NewContext()); - context->set_allowed_bytes_growth(-2); // quota exceeded - ASSERT_EQ(base::PLATFORM_FILE_OK, - quota_test_helper().SameFileUtilCopy( - context.get(), - Path(from_file), - Path(obstacle_file))); - ASSERT_EQ(3058, quota_test_helper().GetCachedOriginUsage()); - ASSERT_EQ(quota_test_helper().ComputeCurrentOriginUsage(), - quota_test_helper().GetCachedOriginUsage()); -} - -TEST_F(QuotaFileUtilTest, CopyDirectory) { - const char *from_dir = "fromdir"; - const char *from_file1 = "fromdir/fromfile1"; - const char *from_file2 = "fromdir/fromfile2"; - const char *to_dir1 = "todir1"; - const char *to_dir2 = "todir2"; - bool created; - scoped_ptr<FileSystemOperationContext> context; - - context.reset(NewContext()); - ASSERT_EQ(base::PLATFORM_FILE_OK, - quota_file_util()->CreateDirectory(context.get(), - Path(from_dir), - false, false)); - ASSERT_EQ(base::PLATFORM_FILE_OK, EnsureFileExists(from_file1, &created)); - ASSERT_TRUE(created); - ASSERT_EQ(base::PLATFORM_FILE_OK, EnsureFileExists(from_file2, &created)); - ASSERT_TRUE(created); - - context.reset(NewContext()); - context->set_allowed_bytes_growth(QuotaFileUtil::kNoLimit); - ASSERT_EQ(base::PLATFORM_FILE_OK, - quota_file_util()->TruncateInternal( - context.get(), Path(from_file1), 520)); - ASSERT_EQ(520, quota_test_helper().GetCachedOriginUsage()); - ASSERT_EQ(quota_test_helper().ComputeCurrentOriginUsage(), - quota_test_helper().GetCachedOriginUsage()); - - context.reset(NewContext()); - context->set_allowed_bytes_growth(QuotaFileUtil::kNoLimit); - ASSERT_EQ(base::PLATFORM_FILE_OK, - quota_file_util()->TruncateInternal( - context.get(), Path(from_file2), 500)); - ASSERT_EQ(1020, quota_test_helper().GetCachedOriginUsage()); - ASSERT_EQ(quota_test_helper().ComputeCurrentOriginUsage(), - quota_test_helper().GetCachedOriginUsage()); - - context.reset(NewContext()); - context->set_allowed_bytes_growth(1020); - ASSERT_EQ(base::PLATFORM_FILE_OK, - quota_test_helper().SameFileUtilCopy( - context.get(), - Path(from_dir), - Path(to_dir1))); - ASSERT_EQ(2040, quota_test_helper().GetCachedOriginUsage()); - ASSERT_EQ(quota_test_helper().ComputeCurrentOriginUsage(), - quota_test_helper().GetCachedOriginUsage()); - - context.reset(NewContext()); - context->set_allowed_bytes_growth(1019); - EXPECT_EQ(base::PLATFORM_FILE_ERROR_NO_SPACE, - quota_test_helper().SameFileUtilCopy( - context.get(), - Path(from_dir), - Path(to_dir2))); - ASSERT_TRUE(2540 == quota_test_helper().GetCachedOriginUsage() || - 2560 == quota_test_helper().GetCachedOriginUsage()); - ASSERT_EQ(quota_test_helper().ComputeCurrentOriginUsage(), - quota_test_helper().GetCachedOriginUsage()); -} - -TEST_F(QuotaFileUtilTest, MoveFile) { - const char *from_file = "fromfile"; - const char *obstacle_file = "obstaclefile"; - const char *to_file = "tofile"; - bool created; - ASSERT_EQ(base::PLATFORM_FILE_OK, EnsureFileExists(from_file, &created)); - ASSERT_TRUE(created); - scoped_ptr<FileSystemOperationContext> context; - - context.reset(NewContext()); - context->set_allowed_bytes_growth(QuotaFileUtil::kNoLimit); - ASSERT_EQ(base::PLATFORM_FILE_OK, - quota_file_util()->TruncateInternal( - context.get(), Path(from_file), 1020)); - ASSERT_EQ(1020, quota_test_helper().GetCachedOriginUsage()); - ASSERT_EQ(quota_test_helper().ComputeCurrentOriginUsage(), - quota_test_helper().GetCachedOriginUsage()); - - context.reset(NewContext()); - context->set_allowed_bytes_growth(0); - ASSERT_EQ(base::PLATFORM_FILE_OK, - quota_test_helper().SameFileUtilMove( - context.get(), - Path(from_file), - Path(to_file))); - ASSERT_EQ(1020, quota_test_helper().GetCachedOriginUsage()); - ASSERT_EQ(quota_test_helper().ComputeCurrentOriginUsage(), - quota_test_helper().GetCachedOriginUsage()); - - ASSERT_EQ(base::PLATFORM_FILE_OK, EnsureFileExists(from_file, &created)); - ASSERT_TRUE(created); - ASSERT_EQ(base::PLATFORM_FILE_OK, EnsureFileExists(obstacle_file, &created)); - ASSERT_TRUE(created); - - context.reset(NewContext()); - context->set_allowed_bytes_growth(QuotaFileUtil::kNoLimit); - ASSERT_EQ(base::PLATFORM_FILE_OK, - quota_file_util()->TruncateInternal( - context.get(), Path(from_file), 1020)); - ASSERT_EQ(2040, quota_test_helper().GetCachedOriginUsage()); - ASSERT_EQ(quota_test_helper().ComputeCurrentOriginUsage(), - quota_test_helper().GetCachedOriginUsage()); - - context.reset(NewContext()); - context->set_allowed_bytes_growth(QuotaFileUtil::kNoLimit); - ASSERT_EQ(base::PLATFORM_FILE_OK, - quota_file_util()->TruncateInternal( - context.get(), Path(obstacle_file), 1)); - ASSERT_EQ(2041, quota_test_helper().GetCachedOriginUsage()); - ASSERT_EQ(quota_test_helper().ComputeCurrentOriginUsage(), - quota_test_helper().GetCachedOriginUsage()); - - context.reset(NewContext()); - context->set_allowed_bytes_growth(0); - ASSERT_EQ(base::PLATFORM_FILE_OK, - quota_test_helper().SameFileUtilMove( - context.get(), - Path(from_file), - Path(obstacle_file))); - ASSERT_EQ(2040, quota_test_helper().GetCachedOriginUsage()); - ASSERT_EQ(quota_test_helper().ComputeCurrentOriginUsage(), - quota_test_helper().GetCachedOriginUsage()); - - ASSERT_EQ(base::PLATFORM_FILE_OK, EnsureFileExists(from_file, &created)); - ASSERT_TRUE(created); - - context.reset(NewContext()); - context->set_allowed_bytes_growth(QuotaFileUtil::kNoLimit); - ASSERT_EQ(base::PLATFORM_FILE_OK, - quota_file_util()->TruncateInternal( - context.get(), Path(from_file), 10)); - ASSERT_EQ(2050, quota_test_helper().GetCachedOriginUsage()); - ASSERT_EQ(quota_test_helper().ComputeCurrentOriginUsage(), - quota_test_helper().GetCachedOriginUsage()); - - context.reset(NewContext()); - context->set_allowed_bytes_growth(-1020 - 1); // quota exceeded, after - ASSERT_EQ(base::PLATFORM_FILE_OK, - quota_test_helper().SameFileUtilMove( - context.get(), - Path(from_file), - Path(obstacle_file))); - ASSERT_EQ(1030, quota_test_helper().GetCachedOriginUsage()); - ASSERT_EQ(quota_test_helper().ComputeCurrentOriginUsage(), - quota_test_helper().GetCachedOriginUsage()); -} - -TEST_F(QuotaFileUtilTest, MoveDirectory) { - const char *from_dir = "fromdir"; - const char *from_file = "fromdir/fromfile"; - const char *to_dir1 = "todir1"; - const char *to_dir2 = "todir2"; - bool created; - scoped_ptr<FileSystemOperationContext> context; - - context.reset(NewContext()); - ASSERT_EQ(base::PLATFORM_FILE_OK, - quota_file_util()->CreateDirectory(context.get(), - Path(from_dir), - false, false)); - ASSERT_EQ(base::PLATFORM_FILE_OK, EnsureFileExists(from_file, &created)); - ASSERT_TRUE(created); - - context.reset(NewContext()); - context->set_allowed_bytes_growth(QuotaFileUtil::kNoLimit); - ASSERT_EQ(base::PLATFORM_FILE_OK, - quota_file_util()->TruncateInternal( - context.get(), Path(from_file), 1020)); - ASSERT_EQ(1020, quota_test_helper().GetCachedOriginUsage()); - ASSERT_EQ(quota_test_helper().ComputeCurrentOriginUsage(), - quota_test_helper().GetCachedOriginUsage()); - - context.reset(NewContext()); - context->set_allowed_bytes_growth(1020); - ASSERT_EQ(base::PLATFORM_FILE_OK, - quota_test_helper().SameFileUtilMove( - context.get(), - Path(from_dir), - Path(to_dir1))); - ASSERT_EQ(1020, quota_test_helper().GetCachedOriginUsage()); - ASSERT_EQ(quota_test_helper().ComputeCurrentOriginUsage(), - quota_test_helper().GetCachedOriginUsage()); - - context.reset(NewContext()); - ASSERT_EQ(base::PLATFORM_FILE_OK, - quota_file_util()->CreateDirectory(context.get(), - Path(from_dir), - false, false)); - ASSERT_EQ(base::PLATFORM_FILE_OK, EnsureFileExists(from_file, &created)); - ASSERT_TRUE(created); - - context.reset(NewContext()); - context->set_allowed_bytes_growth(QuotaFileUtil::kNoLimit); - ASSERT_EQ(base::PLATFORM_FILE_OK, - quota_file_util()->TruncateInternal( - context.get(), Path(from_file), 1020)); - ASSERT_EQ(2040, quota_test_helper().GetCachedOriginUsage()); - ASSERT_EQ(quota_test_helper().ComputeCurrentOriginUsage(), - quota_test_helper().GetCachedOriginUsage()); - - context.reset(NewContext()); - context->set_allowed_bytes_growth(1019); - EXPECT_EQ(base::PLATFORM_FILE_OK, - quota_test_helper().SameFileUtilMove( - context.get(), - Path(from_dir), - Path(to_dir2))); - ASSERT_EQ(2040, quota_test_helper().GetCachedOriginUsage()); - ASSERT_EQ(quota_test_helper().ComputeCurrentOriginUsage(), - quota_test_helper().GetCachedOriginUsage()); -} - -TEST_F(QuotaFileUtilTest, Remove) { - const char *dir = "dir"; - const char *file = "file"; - const char *dfile1 = "dir/dfile1"; - const char *dfile2 = "dir/dfile2"; - bool created; - scoped_ptr<FileSystemOperationContext> context; - - ASSERT_EQ(base::PLATFORM_FILE_OK, EnsureFileExists(file, &created)); - ASSERT_TRUE(created); - context.reset(NewContext()); - ASSERT_EQ(base::PLATFORM_FILE_OK, - quota_file_util()->CreateDirectory(context.get(), - Path(dir), - false, false)); - ASSERT_EQ(base::PLATFORM_FILE_OK, EnsureFileExists(dfile1, &created)); - ASSERT_TRUE(created); - ASSERT_EQ(base::PLATFORM_FILE_OK, EnsureFileExists(dfile2, &created)); - ASSERT_TRUE(created); - - context.reset(NewContext()); - context->set_allowed_bytes_growth(QuotaFileUtil::kNoLimit); - ASSERT_EQ(base::PLATFORM_FILE_OK, - quota_file_util()->TruncateInternal( - context.get(), Path(file), 340)); - ASSERT_EQ(340, quota_test_helper().GetCachedOriginUsage()); - ASSERT_EQ(quota_test_helper().ComputeCurrentOriginUsage(), - quota_test_helper().GetCachedOriginUsage()); - - context.reset(NewContext()); - context->set_allowed_bytes_growth(QuotaFileUtil::kNoLimit); - ASSERT_EQ(base::PLATFORM_FILE_OK, - quota_file_util()->TruncateInternal( - context.get(), Path(dfile1), 1020)); - ASSERT_EQ(1360, quota_test_helper().GetCachedOriginUsage()); - ASSERT_EQ(quota_test_helper().ComputeCurrentOriginUsage(), - quota_test_helper().GetCachedOriginUsage()); - - context.reset(NewContext()); - context->set_allowed_bytes_growth(QuotaFileUtil::kNoLimit); - ASSERT_EQ(base::PLATFORM_FILE_OK, - quota_file_util()->TruncateInternal( - context.get(), Path(dfile2), 120)); - ASSERT_EQ(1480, quota_test_helper().GetCachedOriginUsage()); - ASSERT_EQ(quota_test_helper().ComputeCurrentOriginUsage(), - quota_test_helper().GetCachedOriginUsage()); - - context.reset(NewContext()); - context->set_allowed_bytes_growth(QuotaFileUtil::kNoLimit); - ASSERT_EQ(base::PLATFORM_FILE_OK, - FileUtilHelper::Delete(context.get(), quota_file_util(), - Path(file), false)); - ASSERT_EQ(1140, quota_test_helper().GetCachedOriginUsage()); - ASSERT_EQ(quota_test_helper().ComputeCurrentOriginUsage(), - quota_test_helper().GetCachedOriginUsage()); - - context.reset(NewContext()); - context->set_allowed_bytes_growth(QuotaFileUtil::kNoLimit); - ASSERT_EQ(base::PLATFORM_FILE_OK, - FileUtilHelper::Delete(context.get(), quota_file_util(), - Path(dir), true)); - ASSERT_EQ(0, quota_test_helper().GetCachedOriginUsage()); - ASSERT_EQ(quota_test_helper().ComputeCurrentOriginUsage(), - quota_test_helper().GetCachedOriginUsage()); -} - -} // namespace fileapi diff --git a/webkit/fileapi/sandbox_mount_point_provider.cc b/webkit/fileapi/sandbox_mount_point_provider.cc index 7fdeb8a..28b7a1f 100644 --- a/webkit/fileapi/sandbox_mount_point_provider.cc +++ b/webkit/fileapi/sandbox_mount_point_provider.cc @@ -22,8 +22,8 @@ #include "webkit/fileapi/file_system_types.h" #include "webkit/fileapi/file_system_usage_cache.h" #include "webkit/fileapi/file_system_util.h" +#include "webkit/fileapi/native_file_util.h" #include "webkit/fileapi/obfuscated_file_util.h" -#include "webkit/fileapi/quota_file_util.h" #include "webkit/glue/webkit_glue.h" #include "webkit/quota/quota_manager.h" @@ -331,7 +331,7 @@ SandboxMountPointProvider::SandboxMountPointProvider( sandbox_file_util_( new ObfuscatedFileUtil( profile_path.Append(kNewFileSystemDirectory), - QuotaFileUtil::CreateDefault())), + new NativeFileUtil())), weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { } diff --git a/webkit/fileapi/webkit_fileapi.gypi b/webkit/fileapi/webkit_fileapi.gypi index d51db6b..d880854 100644 --- a/webkit/fileapi/webkit_fileapi.gypi +++ b/webkit/fileapi/webkit_fileapi.gypi @@ -74,8 +74,6 @@ 'native_file_util.h', 'obfuscated_file_util.cc', 'obfuscated_file_util.h', - 'quota_file_util.cc', - 'quota_file_util.h', 'sandbox_mount_point_provider.cc', 'sandbox_mount_point_provider.h', 'webfilewriter_base.cc', |