summaryrefslogtreecommitdiff
path: root/chromium/webkit/browser/fileapi
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/webkit/browser/fileapi')
-rw-r--r--chromium/webkit/browser/fileapi/OWNERS1
-rw-r--r--chromium/webkit/browser/fileapi/async_file_test_helper.cc5
-rw-r--r--chromium/webkit/browser/fileapi/async_file_util.h15
-rw-r--r--chromium/webkit/browser/fileapi/async_file_util_adapter.cc44
-rw-r--r--chromium/webkit/browser/fileapi/async_file_util_adapter.h2
-rw-r--r--chromium/webkit/browser/fileapi/copy_or_move_file_validator_unittest.cc326
-rw-r--r--chromium/webkit/browser/fileapi/copy_or_move_operation_delegate.cc492
-rw-r--r--chromium/webkit/browser/fileapi/copy_or_move_operation_delegate.h73
-rw-r--r--chromium/webkit/browser/fileapi/copy_or_move_operation_delegate_unittest.cc665
-rw-r--r--chromium/webkit/browser/fileapi/dragged_file_util.cc2
-rw-r--r--chromium/webkit/browser/fileapi/dragged_file_util_unittest.cc545
-rw-r--r--chromium/webkit/browser/fileapi/dump_file_system.cc11
-rw-r--r--chromium/webkit/browser/fileapi/external_mount_points.cc65
-rw-r--r--chromium/webkit/browser/fileapi/external_mount_points.h29
-rw-r--r--chromium/webkit/browser/fileapi/external_mount_points_unittest.cc57
-rw-r--r--chromium/webkit/browser/fileapi/file_permission_policy.cc37
-rw-r--r--chromium/webkit/browser/fileapi/file_permission_policy.h5
-rw-r--r--chromium/webkit/browser/fileapi/file_system_backend.h8
-rw-r--r--chromium/webkit/browser/fileapi/file_system_context.cc91
-rw-r--r--chromium/webkit/browser/fileapi/file_system_context.h45
-rw-r--r--chromium/webkit/browser/fileapi/file_system_context_unittest.cc328
-rw-r--r--chromium/webkit/browser/fileapi/file_system_dir_url_request_job.cc3
-rw-r--r--chromium/webkit/browser/fileapi/file_system_dir_url_request_job_unittest.cc320
-rw-r--r--chromium/webkit/browser/fileapi/file_system_file_stream_reader.cc2
-rw-r--r--chromium/webkit/browser/fileapi/file_system_file_stream_reader_unittest.cc267
-rw-r--r--chromium/webkit/browser/fileapi/file_system_file_util.h9
-rw-r--r--chromium/webkit/browser/fileapi/file_system_operation.h31
-rw-r--r--chromium/webkit/browser/fileapi/file_system_operation_impl.cc35
-rw-r--r--chromium/webkit/browser/fileapi/file_system_operation_impl.h11
-rw-r--r--chromium/webkit/browser/fileapi/file_system_operation_impl_unittest.cc1210
-rw-r--r--chromium/webkit/browser/fileapi/file_system_operation_impl_write_unittest.cc329
-rw-r--r--chromium/webkit/browser/fileapi/file_system_operation_runner.cc30
-rw-r--r--chromium/webkit/browser/fileapi/file_system_operation_runner.h19
-rw-r--r--chromium/webkit/browser/fileapi/file_system_operation_runner_unittest.cc162
-rw-r--r--chromium/webkit/browser/fileapi/file_system_quota_client_unittest.cc561
-rw-r--r--chromium/webkit/browser/fileapi/file_system_quota_util.h7
-rw-r--r--chromium/webkit/browser/fileapi/file_system_url.cc15
-rw-r--r--chromium/webkit/browser/fileapi/file_system_url.h7
-rw-r--r--chromium/webkit/browser/fileapi/file_system_url_request_job.cc4
-rw-r--r--chromium/webkit/browser/fileapi/file_system_url_request_job.h2
-rw-r--r--chromium/webkit/browser/fileapi/file_system_url_request_job_unittest.cc365
-rw-r--r--chromium/webkit/browser/fileapi/file_system_usage_cache.cc4
-rw-r--r--chromium/webkit/browser/fileapi/file_system_usage_cache.h3
-rw-r--r--chromium/webkit/browser/fileapi/file_writer_delegate.cc21
-rw-r--r--chromium/webkit/browser/fileapi/file_writer_delegate.h2
-rw-r--r--chromium/webkit/browser/fileapi/file_writer_delegate_unittest.cc454
-rw-r--r--chromium/webkit/browser/fileapi/isolated_context.cc30
-rw-r--r--chromium/webkit/browser/fileapi/isolated_context.h10
-rw-r--r--chromium/webkit/browser/fileapi/isolated_context_unittest.cc29
-rw-r--r--chromium/webkit/browser/fileapi/local_file_stream_writer.cc4
-rw-r--r--chromium/webkit/browser/fileapi/local_file_stream_writer_unittest.cc5
-rw-r--r--chromium/webkit/browser/fileapi/local_file_util.cc16
-rw-r--r--chromium/webkit/browser/fileapi/local_file_util.h1
-rw-r--r--chromium/webkit/browser/fileapi/local_file_util_unittest.cc388
-rw-r--r--chromium/webkit/browser/fileapi/mock_file_system_context.cc57
-rw-r--r--chromium/webkit/browser/fileapi/mock_file_system_context.h38
-rw-r--r--chromium/webkit/browser/fileapi/mock_file_system_options.cc40
-rw-r--r--chromium/webkit/browser/fileapi/mock_file_system_options.h23
-rw-r--r--chromium/webkit/browser/fileapi/mount_points.h4
-rw-r--r--chromium/webkit/browser/fileapi/native_file_util.cc95
-rw-r--r--chromium/webkit/browser/fileapi/native_file_util.h16
-rw-r--r--chromium/webkit/browser/fileapi/native_file_util_unittest.cc127
-rw-r--r--chromium/webkit/browser/fileapi/obfuscated_file_util.cc390
-rw-r--r--chromium/webkit/browser/fileapi/obfuscated_file_util.h127
-rw-r--r--chromium/webkit/browser/fileapi/obfuscated_file_util_unittest.cc2403
-rw-r--r--chromium/webkit/browser/fileapi/plugin_private_file_system_backend.cc297
-rw-r--r--chromium/webkit/browser/fileapi/plugin_private_file_system_backend.h142
-rw-r--r--chromium/webkit/browser/fileapi/quota/open_file_handle.cc40
-rw-r--r--chromium/webkit/browser/fileapi/quota/open_file_handle.h51
-rw-r--r--chromium/webkit/browser/fileapi/quota/open_file_handle_context.cc60
-rw-r--r--chromium/webkit/browser/fileapi/quota/open_file_handle_context.h59
-rw-r--r--chromium/webkit/browser/fileapi/quota/quota_backend_impl.cc156
-rw-r--r--chromium/webkit/browser/fileapi/quota/quota_backend_impl.h103
-rw-r--r--chromium/webkit/browser/fileapi/quota/quota_backend_impl_unittest.cc248
-rw-r--r--chromium/webkit/browser/fileapi/quota/quota_reservation.cc113
-rw-r--r--chromium/webkit/browser/fileapi/quota/quota_reservation.h89
-rw-r--r--chromium/webkit/browser/fileapi/quota/quota_reservation_buffer.cc105
-rw-r--r--chromium/webkit/browser/fileapi/quota/quota_reservation_buffer.h86
-rw-r--r--chromium/webkit/browser/fileapi/quota/quota_reservation_manager.cc91
-rw-r--r--chromium/webkit/browser/fileapi/quota/quota_reservation_manager.h123
-rw-r--r--chromium/webkit/browser/fileapi/quota/quota_reservation_manager_unittest.cc358
-rw-r--r--chromium/webkit/browser/fileapi/recursive_operation_delegate.cc4
-rw-r--r--chromium/webkit/browser/fileapi/recursive_operation_delegate.h4
-rw-r--r--chromium/webkit/browser/fileapi/recursive_operation_delegate_unittest.cc280
-rw-r--r--chromium/webkit/browser/fileapi/sandbox_database_test_helper.cc1
-rw-r--r--chromium/webkit/browser/fileapi/sandbox_directory_database.cc34
-rw-r--r--chromium/webkit/browser/fileapi/sandbox_directory_database.h3
-rw-r--r--chromium/webkit/browser/fileapi/sandbox_directory_database_unittest.cc5
-rw-r--r--chromium/webkit/browser/fileapi/sandbox_file_system_backend.cc10
-rw-r--r--chromium/webkit/browser/fileapi/sandbox_file_system_backend_delegate.cc233
-rw-r--r--chromium/webkit/browser/fileapi/sandbox_file_system_backend_delegate.h31
-rw-r--r--chromium/webkit/browser/fileapi/sandbox_file_system_backend_delegate_unittest.cc82
-rw-r--r--chromium/webkit/browser/fileapi/sandbox_file_system_backend_unittest.cc325
-rw-r--r--chromium/webkit/browser/fileapi/sandbox_file_system_test_helper.cc152
-rw-r--r--chromium/webkit/browser/fileapi/sandbox_file_system_test_helper.h103
-rw-r--r--chromium/webkit/browser/fileapi/sandbox_isolated_origin_database.cc45
-rw-r--r--chromium/webkit/browser/fileapi/sandbox_isolated_origin_database.h20
-rw-r--r--chromium/webkit/browser/fileapi/sandbox_isolated_origin_database_unittest.cc58
-rw-r--r--chromium/webkit/browser/fileapi/sandbox_origin_database.cc2
-rw-r--r--chromium/webkit/browser/fileapi/sandbox_origin_database.h3
-rw-r--r--chromium/webkit/browser/fileapi/sandbox_origin_database_unittest.cc21
-rw-r--r--chromium/webkit/browser/fileapi/sandbox_prioritized_origin_database.cc229
-rw-r--r--chromium/webkit/browser/fileapi/sandbox_prioritized_origin_database.h67
-rw-r--r--chromium/webkit/browser/fileapi/sandbox_prioritized_origin_database_unittest.cc215
-rw-r--r--chromium/webkit/browser/fileapi/test_file_set.cc2
-rw-r--r--chromium/webkit/browser/fileapi/test_file_set.h3
-rw-r--r--chromium/webkit/browser/fileapi/test_file_system_backend.cc247
-rw-r--r--chromium/webkit/browser/fileapi/test_file_system_backend.h95
-rw-r--r--chromium/webkit/browser/fileapi/transient_file_util_unittest.cc122
-rw-r--r--chromium/webkit/browser/fileapi/upload_file_system_file_element_reader.cc2
-rw-r--r--chromium/webkit/browser/fileapi/upload_file_system_file_element_reader_unittest.cc278
111 files changed, 4358 insertions, 10961 deletions
diff --git a/chromium/webkit/browser/fileapi/OWNERS b/chromium/webkit/browser/fileapi/OWNERS
index 6ca58a9dbe5..8338b2a1442 100644
--- a/chromium/webkit/browser/fileapi/OWNERS
+++ b/chromium/webkit/browser/fileapi/OWNERS
@@ -1,2 +1,3 @@
ericu@chromium.org
tzik@chromium.org
+nhiroki@chromium.org
diff --git a/chromium/webkit/browser/fileapi/async_file_test_helper.cc b/chromium/webkit/browser/fileapi/async_file_test_helper.cc
index e3343d51935..50fd7cda34c 100644
--- a/chromium/webkit/browser/fileapi/async_file_test_helper.cc
+++ b/chromium/webkit/browser/fileapi/async_file_test_helper.cc
@@ -105,7 +105,7 @@ base::PlatformFileError AsyncFileTestHelper::CopyWithProgress(
base::PlatformFileError result = base::PLATFORM_FILE_ERROR_FAILED;
base::RunLoop run_loop;
context->operation_runner()->Copy(
- src, dest, progress_callback,
+ src, dest, FileSystemOperation::OPTION_NONE, progress_callback,
AssignAndQuitCallback(&run_loop, &result));
run_loop.Run();
return result;
@@ -118,7 +118,8 @@ base::PlatformFileError AsyncFileTestHelper::Move(
base::PlatformFileError result = base::PLATFORM_FILE_ERROR_FAILED;
base::RunLoop run_loop;
context->operation_runner()->Move(
- src, dest, AssignAndQuitCallback(&run_loop, &result));
+ src, dest, FileSystemOperation::OPTION_NONE,
+ AssignAndQuitCallback(&run_loop, &result));
run_loop.Run();
return result;
}
diff --git a/chromium/webkit/browser/fileapi/async_file_util.h b/chromium/webkit/browser/fileapi/async_file_util.h
index 84a033b7a4e..c1e6d1e4725 100644
--- a/chromium/webkit/browser/fileapi/async_file_util.h
+++ b/chromium/webkit/browser/fileapi/async_file_util.h
@@ -5,11 +5,14 @@
#ifndef WEBKIT_BROWSER_FILEAPI_ASYNC_FILE_UTIL_H_
#define WEBKIT_BROWSER_FILEAPI_ASYNC_FILE_UTIL_H_
+#include <vector>
+
#include "base/basictypes.h"
#include "base/callback_forward.h"
#include "base/files/file_util_proxy.h"
#include "base/memory/scoped_ptr.h"
#include "base/platform_file.h"
+#include "webkit/browser/fileapi/file_system_operation.h"
#include "webkit/browser/webkit_storage_browser_export.h"
#include "webkit/common/fileapi/directory_entry.h"
@@ -73,12 +76,14 @@ class AsyncFileUtil {
void(base::PlatformFileError result,
const base::PlatformFileInfo& file_info,
const base::FilePath& platform_path,
- const scoped_refptr<webkit_blob::ShareableFileReference>& file_ref
- )> CreateSnapshotFileCallback;
+ const scoped_refptr<webkit_blob::ShareableFileReference>& file_ref)>
+ CreateSnapshotFileCallback;
typedef base::Callback<void(int64 size)> CopyFileProgressCallback;
+ typedef FileSystemOperation::CopyOrMoveOption CopyOrMoveOption;
+
// Creates an AsyncFileUtil instance which performs file operations on
// local native file system. The created instance assumes
// FileSystemURL::path() has the target platform path.
@@ -94,7 +99,7 @@ class AsyncFileUtil {
// PLATFORM_FILE_ERROR_FILE_EXISTS if the |url| already exists.
//
// FileSystemOperationImpl::OpenFile calls this.
- // This is used only by Pepper/NaCL File API.
+ // This is used only by Pepper/NaCl File API.
//
virtual void CreateOrOpen(
scoped_ptr<FileSystemOperationContext> context,
@@ -180,7 +185,7 @@ class AsyncFileUtil {
// create a file unlike 'touch' command on Linux.
//
// FileSystemOperationImpl::TouchFile calls this.
- // This is used only by Pepper/NaCL File API.
+ // This is used only by Pepper/NaCl File API.
//
virtual void Touch(
scoped_ptr<FileSystemOperationContext> context,
@@ -229,6 +234,7 @@ class AsyncFileUtil {
scoped_ptr<FileSystemOperationContext> context,
const FileSystemURL& src_url,
const FileSystemURL& dest_url,
+ CopyOrMoveOption option,
const CopyFileProgressCallback& progress_callback,
const StatusCallback& callback) = 0;
@@ -251,6 +257,7 @@ class AsyncFileUtil {
scoped_ptr<FileSystemOperationContext> context,
const FileSystemURL& src_url,
const FileSystemURL& dest_url,
+ CopyOrMoveOption option,
const StatusCallback& callback) = 0;
// Copies in a single file from a different filesystem.
diff --git a/chromium/webkit/browser/fileapi/async_file_util_adapter.cc b/chromium/webkit/browser/fileapi/async_file_util_adapter.cc
index 54d67976dc7..b25ddf24967 100644
--- a/chromium/webkit/browser/fileapi/async_file_util_adapter.cc
+++ b/chromium/webkit/browser/fileapi/async_file_util_adapter.cc
@@ -4,6 +4,8 @@
#include "webkit/browser/fileapi/async_file_util_adapter.h"
+#include <vector>
+
#include "base/bind.h"
#include "base/sequenced_task_runner.h"
#include "base/task_runner_util.h"
@@ -168,10 +170,10 @@ void AsyncFileUtilAdapter::EnsureFileExists(
EnsureFileExistsHelper* helper = new EnsureFileExistsHelper;
FileSystemOperationContext* context_ptr = context.release();
const bool success = context_ptr->task_runner()->PostTaskAndReply(
- FROM_HERE,
- Bind(&EnsureFileExistsHelper::RunWork, Unretained(helper),
- sync_file_util_.get(), base::Owned(context_ptr), url),
- Bind(&EnsureFileExistsHelper::Reply, Owned(helper), callback));
+ FROM_HERE,
+ Bind(&EnsureFileExistsHelper::RunWork, Unretained(helper),
+ sync_file_util_.get(), base::Owned(context_ptr), url),
+ Bind(&EnsureFileExistsHelper::Reply, Owned(helper), callback));
DCHECK(success);
}
@@ -198,10 +200,10 @@ void AsyncFileUtilAdapter::GetFileInfo(
FileSystemOperationContext* context_ptr = context.release();
GetFileInfoHelper* helper = new GetFileInfoHelper;
const bool success = context_ptr->task_runner()->PostTaskAndReply(
- FROM_HERE,
- Bind(&GetFileInfoHelper::GetFileInfo, Unretained(helper),
- sync_file_util_.get(), base::Owned(context_ptr), url),
- Bind(&GetFileInfoHelper::ReplyFileInfo, Owned(helper), callback));
+ FROM_HERE,
+ Bind(&GetFileInfoHelper::GetFileInfo, Unretained(helper),
+ sync_file_util_.get(), base::Owned(context_ptr), url),
+ Bind(&GetFileInfoHelper::ReplyFileInfo, Owned(helper), callback));
DCHECK(success);
}
@@ -212,10 +214,10 @@ void AsyncFileUtilAdapter::ReadDirectory(
FileSystemOperationContext* context_ptr = context.release();
ReadDirectoryHelper* helper = new ReadDirectoryHelper;
const bool success = context_ptr->task_runner()->PostTaskAndReply(
- FROM_HERE,
- Bind(&ReadDirectoryHelper::RunWork, Unretained(helper),
- sync_file_util_.get(), base::Owned(context_ptr), url),
- Bind(&ReadDirectoryHelper::Reply, Owned(helper), callback));
+ FROM_HERE,
+ Bind(&ReadDirectoryHelper::RunWork, Unretained(helper),
+ sync_file_util_.get(), base::Owned(context_ptr), url),
+ Bind(&ReadDirectoryHelper::Reply, Owned(helper), callback));
DCHECK(success);
}
@@ -253,6 +255,7 @@ void AsyncFileUtilAdapter::CopyFileLocal(
scoped_ptr<FileSystemOperationContext> context,
const FileSystemURL& src_url,
const FileSystemURL& dest_url,
+ CopyOrMoveOption option,
const CopyFileProgressCallback& progress_callback,
const StatusCallback& callback) {
// TODO(hidehiko): Support progress_callback.
@@ -260,8 +263,8 @@ void AsyncFileUtilAdapter::CopyFileLocal(
const bool success = base::PostTaskAndReplyWithResult(
context_ptr->task_runner(), FROM_HERE,
Bind(&FileSystemFileUtil::CopyOrMoveFile,
- Unretained(sync_file_util_.get()),
- base::Owned(context_ptr), src_url, dest_url, true /* copy */),
+ Unretained(sync_file_util_.get()), base::Owned(context_ptr),
+ src_url, dest_url, option, true /* copy */),
callback);
DCHECK(success);
}
@@ -270,13 +273,14 @@ void AsyncFileUtilAdapter::MoveFileLocal(
scoped_ptr<FileSystemOperationContext> context,
const FileSystemURL& src_url,
const FileSystemURL& dest_url,
+ CopyOrMoveOption option,
const StatusCallback& callback) {
FileSystemOperationContext* context_ptr = context.release();
const bool success = base::PostTaskAndReplyWithResult(
context_ptr->task_runner(), FROM_HERE,
Bind(&FileSystemFileUtil::CopyOrMoveFile,
- Unretained(sync_file_util_.get()),
- base::Owned(context_ptr), src_url, dest_url, false /* copy */),
+ Unretained(sync_file_util_.get()), base::Owned(context_ptr),
+ src_url, dest_url, option, false /* copy */),
callback);
DCHECK(success);
}
@@ -338,10 +342,10 @@ void AsyncFileUtilAdapter::CreateSnapshotFile(
FileSystemOperationContext* context_ptr = context.release();
GetFileInfoHelper* helper = new GetFileInfoHelper;
const bool success = context_ptr->task_runner()->PostTaskAndReply(
- FROM_HERE,
- Bind(&GetFileInfoHelper::CreateSnapshotFile, Unretained(helper),
- sync_file_util_.get(), base::Owned(context_ptr), url),
- Bind(&GetFileInfoHelper::ReplySnapshotFile, Owned(helper), callback));
+ FROM_HERE,
+ Bind(&GetFileInfoHelper::CreateSnapshotFile, Unretained(helper),
+ sync_file_util_.get(), base::Owned(context_ptr), url),
+ Bind(&GetFileInfoHelper::ReplySnapshotFile, Owned(helper), callback));
DCHECK(success);
}
diff --git a/chromium/webkit/browser/fileapi/async_file_util_adapter.h b/chromium/webkit/browser/fileapi/async_file_util_adapter.h
index 0122b11b9d5..8e90e5d1409 100644
--- a/chromium/webkit/browser/fileapi/async_file_util_adapter.h
+++ b/chromium/webkit/browser/fileapi/async_file_util_adapter.h
@@ -76,12 +76,14 @@ class WEBKIT_STORAGE_BROWSER_EXPORT AsyncFileUtilAdapter
scoped_ptr<FileSystemOperationContext> context,
const FileSystemURL& src_url,
const FileSystemURL& dest_url,
+ CopyOrMoveOption option,
const CopyFileProgressCallback& progress_callback,
const StatusCallback& callback) OVERRIDE;
virtual void MoveFileLocal(
scoped_ptr<FileSystemOperationContext> context,
const FileSystemURL& src_url,
const FileSystemURL& dest_url,
+ CopyOrMoveOption option,
const StatusCallback& callback) OVERRIDE;
virtual void CopyInForeignFile(
scoped_ptr<FileSystemOperationContext> context,
diff --git a/chromium/webkit/browser/fileapi/copy_or_move_file_validator_unittest.cc b/chromium/webkit/browser/fileapi/copy_or_move_file_validator_unittest.cc
deleted file mode 100644
index 366efa3dad5..00000000000
--- a/chromium/webkit/browser/fileapi/copy_or_move_file_validator_unittest.cc
+++ /dev/null
@@ -1,326 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/basictypes.h"
-#include "base/bind.h"
-#include "base/files/file_path.h"
-#include "base/files/scoped_temp_dir.h"
-#include "base/run_loop.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "webkit/browser/fileapi/async_file_test_helper.h"
-#include "webkit/browser/fileapi/copy_or_move_file_validator.h"
-#include "webkit/browser/fileapi/external_mount_points.h"
-#include "webkit/browser/fileapi/file_system_backend.h"
-#include "webkit/browser/fileapi/file_system_context.h"
-#include "webkit/browser/fileapi/file_system_url.h"
-#include "webkit/browser/fileapi/isolated_context.h"
-#include "webkit/browser/fileapi/mock_file_system_context.h"
-#include "webkit/browser/fileapi/test_file_system_backend.h"
-#include "webkit/browser/quota/mock_special_storage_policy.h"
-#include "webkit/common/blob/shareable_file_reference.h"
-#include "webkit/common/fileapi/file_system_util.h"
-
-namespace fileapi {
-
-namespace {
-
-const FileSystemType kNoValidatorType = kFileSystemTypeTemporary;
-const FileSystemType kWithValidatorType = kFileSystemTypeTest;
-
-void ExpectOk(const GURL& origin_url,
- const std::string& name,
- base::PlatformFileError error) {
- ASSERT_EQ(base::PLATFORM_FILE_OK, error);
-}
-
-class CopyOrMoveFileValidatorTestHelper {
- public:
- CopyOrMoveFileValidatorTestHelper(
- const GURL& origin,
- FileSystemType src_type,
- FileSystemType dest_type)
- : origin_(origin),
- src_type_(src_type),
- dest_type_(dest_type) {}
-
- ~CopyOrMoveFileValidatorTestHelper() {
- file_system_context_ = NULL;
- base::RunLoop().RunUntilIdle();
- }
-
- void SetUp() {
- ASSERT_TRUE(base_.CreateUniqueTempDir());
- base::FilePath base_dir = base_.path();
-
- file_system_context_ = CreateFileSystemContextForTesting(NULL, base_dir);
-
- // Set up TestFileSystemBackend to require CopyOrMoveFileValidator.
- FileSystemBackend* test_file_system_backend =
- file_system_context_->GetFileSystemBackend(kWithValidatorType);
- static_cast<TestFileSystemBackend*>(test_file_system_backend)->
- set_require_copy_or_move_validator(true);
-
- // Sets up source.
- FileSystemBackend* src_file_system_backend =
- file_system_context_->GetFileSystemBackend(src_type_);
- src_file_system_backend->OpenFileSystem(
- origin_, src_type_,
- OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
- base::Bind(&ExpectOk));
- base::RunLoop().RunUntilIdle();
- ASSERT_EQ(base::PLATFORM_FILE_OK, CreateDirectory(SourceURL("")));
-
- // Sets up dest.
- DCHECK_EQ(kWithValidatorType, dest_type_);
- ASSERT_EQ(base::PLATFORM_FILE_OK, CreateDirectory(DestURL("")));
-
- copy_src_ = SourceURL("copy_src.jpg");
- move_src_ = SourceURL("move_src.jpg");
- copy_dest_ = DestURL("copy_dest.jpg");
- move_dest_ = DestURL("move_dest.jpg");
-
- ASSERT_EQ(base::PLATFORM_FILE_OK, CreateFile(copy_src_, 10));
- ASSERT_EQ(base::PLATFORM_FILE_OK, CreateFile(move_src_, 10));
-
- ASSERT_TRUE(FileExists(copy_src_, 10));
- ASSERT_TRUE(FileExists(move_src_, 10));
- ASSERT_FALSE(FileExists(copy_dest_, 10));
- ASSERT_FALSE(FileExists(move_dest_, 10));
- }
-
- void SetMediaCopyOrMoveFileValidatorFactory(
- scoped_ptr<CopyOrMoveFileValidatorFactory> factory) {
- TestFileSystemBackend* backend = static_cast<TestFileSystemBackend*>(
- file_system_context_->GetFileSystemBackend(kWithValidatorType));
- backend->InitializeCopyOrMoveFileValidatorFactory(factory.Pass());
- }
-
- void CopyTest(base::PlatformFileError expected) {
- ASSERT_TRUE(FileExists(copy_src_, 10));
- ASSERT_FALSE(FileExists(copy_dest_, 10));
-
- EXPECT_EQ(expected,
- AsyncFileTestHelper::Copy(
- file_system_context_.get(), copy_src_, copy_dest_));
-
- EXPECT_TRUE(FileExists(copy_src_, 10));
- if (expected == base::PLATFORM_FILE_OK)
- EXPECT_TRUE(FileExists(copy_dest_, 10));
- else
- EXPECT_FALSE(FileExists(copy_dest_, 10));
- };
-
- void MoveTest(base::PlatformFileError expected) {
- ASSERT_TRUE(FileExists(move_src_, 10));
- ASSERT_FALSE(FileExists(move_dest_, 10));
-
- EXPECT_EQ(expected,
- AsyncFileTestHelper::Move(
- file_system_context_.get(), move_src_, move_dest_));
-
- if (expected == base::PLATFORM_FILE_OK) {
- EXPECT_FALSE(FileExists(move_src_, 10));
- EXPECT_TRUE(FileExists(move_dest_, 10));
- } else {
- EXPECT_TRUE(FileExists(move_src_, 10));
- EXPECT_FALSE(FileExists(move_dest_, 10));
- }
- };
-
- private:
- FileSystemURL SourceURL(const std::string& path) {
- return file_system_context_->CreateCrackedFileSystemURL(
- origin_, src_type_,
- base::FilePath().AppendASCII("src").AppendASCII(path));
- }
-
- FileSystemURL DestURL(const std::string& path) {
- return file_system_context_->CreateCrackedFileSystemURL(
- origin_, dest_type_,
- base::FilePath().AppendASCII("dest").AppendASCII(path));
- }
-
- base::PlatformFileError CreateFile(const FileSystemURL& url, size_t size) {
- base::PlatformFileError result =
- AsyncFileTestHelper::CreateFile(file_system_context_.get(), url);
- if (result != base::PLATFORM_FILE_OK)
- return result;
- return AsyncFileTestHelper::TruncateFile(
- file_system_context_.get(), url, size);
- }
-
- base::PlatformFileError CreateDirectory(const FileSystemURL& url) {
- return AsyncFileTestHelper::CreateDirectory(file_system_context_.get(),
- url);
- }
-
- bool FileExists(const FileSystemURL& url, int64 expected_size) {
- return AsyncFileTestHelper::FileExists(
- file_system_context_.get(), url, expected_size);
- }
-
- base::ScopedTempDir base_;
-
- const GURL origin_;
-
- const FileSystemType src_type_;
- const FileSystemType dest_type_;
- std::string src_fsid_;
- std::string dest_fsid_;
-
- base::MessageLoop message_loop_;
- scoped_refptr<FileSystemContext> file_system_context_;
-
- FileSystemURL copy_src_;
- FileSystemURL copy_dest_;
- FileSystemURL move_src_;
- FileSystemURL move_dest_;
-
- DISALLOW_COPY_AND_ASSIGN(CopyOrMoveFileValidatorTestHelper);
-};
-
-// For TestCopyOrMoveFileValidatorFactory
-enum Validity {
- VALID,
- PRE_WRITE_INVALID,
- POST_WRITE_INVALID
-};
-
-class TestCopyOrMoveFileValidatorFactory
- : public CopyOrMoveFileValidatorFactory {
- public:
- // A factory that creates validators that accept everything or nothing.
- // TODO(gbillock): switch args to enum or something
- explicit TestCopyOrMoveFileValidatorFactory(Validity validity)
- : validity_(validity) {}
- virtual ~TestCopyOrMoveFileValidatorFactory() {}
-
- virtual CopyOrMoveFileValidator* CreateCopyOrMoveFileValidator(
- const FileSystemURL& /*src_url*/,
- const base::FilePath& /*platform_path*/) OVERRIDE {
- return new TestCopyOrMoveFileValidator(validity_);
- }
-
- private:
- class TestCopyOrMoveFileValidator : public CopyOrMoveFileValidator {
- public:
- explicit TestCopyOrMoveFileValidator(Validity validity)
- : result_(validity == VALID || validity == POST_WRITE_INVALID
- ? base::PLATFORM_FILE_OK
- : base::PLATFORM_FILE_ERROR_SECURITY),
- write_result_(validity == VALID || validity == PRE_WRITE_INVALID
- ? base::PLATFORM_FILE_OK
- : base::PLATFORM_FILE_ERROR_SECURITY) {
- }
- virtual ~TestCopyOrMoveFileValidator() {}
-
- virtual void StartPreWriteValidation(
- const ResultCallback& result_callback) OVERRIDE {
- // Post the result since a real validator must do work asynchronously.
- base::MessageLoop::current()->PostTask(
- FROM_HERE, base::Bind(result_callback, result_));
- }
-
- virtual void StartPostWriteValidation(
- const base::FilePath& dest_platform_path,
- const ResultCallback& result_callback) OVERRIDE {
- // Post the result since a real validator must do work asynchronously.
- base::MessageLoop::current()->PostTask(
- FROM_HERE, base::Bind(result_callback, write_result_));
- }
-
- private:
- base::PlatformFileError result_;
- base::PlatformFileError write_result_;
-
- DISALLOW_COPY_AND_ASSIGN(TestCopyOrMoveFileValidator);
- };
-
- Validity validity_;
-
- DISALLOW_COPY_AND_ASSIGN(TestCopyOrMoveFileValidatorFactory);
-};
-
-} // namespace
-
-TEST(CopyOrMoveFileValidatorTest, NoValidatorWithinSameFSType) {
- // Within a file system type, validation is not expected, so it should
- // work for kWithValidatorType without a validator set.
- CopyOrMoveFileValidatorTestHelper helper(GURL("http://foo"),
- kWithValidatorType,
- kWithValidatorType);
- helper.SetUp();
- helper.CopyTest(base::PLATFORM_FILE_OK);
- helper.MoveTest(base::PLATFORM_FILE_OK);
-}
-
-TEST(CopyOrMoveFileValidatorTest, MissingValidator) {
- // Copying or moving into a kWithValidatorType requires a file
- // validator. An error is expected if copy is attempted without a validator.
- CopyOrMoveFileValidatorTestHelper helper(GURL("http://foo"),
- kNoValidatorType,
- kWithValidatorType);
- helper.SetUp();
- helper.CopyTest(base::PLATFORM_FILE_ERROR_SECURITY);
- helper.MoveTest(base::PLATFORM_FILE_ERROR_SECURITY);
-}
-
-TEST(CopyOrMoveFileValidatorTest, AcceptAll) {
- CopyOrMoveFileValidatorTestHelper helper(GURL("http://foo"),
- kNoValidatorType,
- kWithValidatorType);
- helper.SetUp();
- scoped_ptr<CopyOrMoveFileValidatorFactory> factory(
- new TestCopyOrMoveFileValidatorFactory(VALID));
- helper.SetMediaCopyOrMoveFileValidatorFactory(factory.Pass());
-
- helper.CopyTest(base::PLATFORM_FILE_OK);
- helper.MoveTest(base::PLATFORM_FILE_OK);
-}
-
-TEST(CopyOrMoveFileValidatorTest, AcceptNone) {
- CopyOrMoveFileValidatorTestHelper helper(GURL("http://foo"),
- kNoValidatorType,
- kWithValidatorType);
- helper.SetUp();
- scoped_ptr<CopyOrMoveFileValidatorFactory> factory(
- new TestCopyOrMoveFileValidatorFactory(PRE_WRITE_INVALID));
- helper.SetMediaCopyOrMoveFileValidatorFactory(factory.Pass());
-
- helper.CopyTest(base::PLATFORM_FILE_ERROR_SECURITY);
- helper.MoveTest(base::PLATFORM_FILE_ERROR_SECURITY);
-}
-
-TEST(CopyOrMoveFileValidatorTest, OverrideValidator) {
- // Once set, you can not override the validator.
- CopyOrMoveFileValidatorTestHelper helper(GURL("http://foo"),
- kNoValidatorType,
- kWithValidatorType);
- helper.SetUp();
- scoped_ptr<CopyOrMoveFileValidatorFactory> reject_factory(
- new TestCopyOrMoveFileValidatorFactory(PRE_WRITE_INVALID));
- helper.SetMediaCopyOrMoveFileValidatorFactory(reject_factory.Pass());
-
- scoped_ptr<CopyOrMoveFileValidatorFactory> accept_factory(
- new TestCopyOrMoveFileValidatorFactory(VALID));
- helper.SetMediaCopyOrMoveFileValidatorFactory(accept_factory.Pass());
-
- helper.CopyTest(base::PLATFORM_FILE_ERROR_SECURITY);
- helper.MoveTest(base::PLATFORM_FILE_ERROR_SECURITY);
-}
-
-TEST(CopyOrMoveFileValidatorTest, RejectPostWrite) {
- CopyOrMoveFileValidatorTestHelper helper(GURL("http://foo"),
- kNoValidatorType,
- kWithValidatorType);
- helper.SetUp();
- scoped_ptr<CopyOrMoveFileValidatorFactory> factory(
- new TestCopyOrMoveFileValidatorFactory(POST_WRITE_INVALID));
- helper.SetMediaCopyOrMoveFileValidatorFactory(factory.Pass());
-
- helper.CopyTest(base::PLATFORM_FILE_ERROR_SECURITY);
- helper.MoveTest(base::PLATFORM_FILE_ERROR_SECURITY);
-}
-
-} // namespace fileapi
diff --git a/chromium/webkit/browser/fileapi/copy_or_move_operation_delegate.cc b/chromium/webkit/browser/fileapi/copy_or_move_operation_delegate.cc
index aba17b55d75..967b5c28f0d 100644
--- a/chromium/webkit/browser/fileapi/copy_or_move_operation_delegate.cc
+++ b/chromium/webkit/browser/fileapi/copy_or_move_operation_delegate.cc
@@ -6,7 +6,11 @@
#include "base/bind.h"
#include "base/files/file_path.h"
+#include "net/base/io_buffer.h"
+#include "net/base/net_errors.h"
+#include "webkit/browser/blob/file_stream_reader.h"
#include "webkit/browser/fileapi/copy_or_move_file_validator.h"
+#include "webkit/browser/fileapi/file_stream_writer.h"
#include "webkit/browser/fileapi/file_system_context.h"
#include "webkit/browser/fileapi/file_system_operation_runner.h"
#include "webkit/browser/fileapi/file_system_url.h"
@@ -16,13 +20,19 @@
namespace fileapi {
+const int64 kFlushIntervalInBytes = 10 << 20; // 10MB.
+
class CopyOrMoveOperationDelegate::CopyOrMoveImpl {
public:
virtual ~CopyOrMoveImpl() {}
virtual void Run(
const CopyOrMoveOperationDelegate::StatusCallback& callback) = 0;
+ virtual void Cancel() = 0;
+
protected:
CopyOrMoveImpl() {}
+
+ private:
DISALLOW_COPY_AND_ASSIGN(CopyOrMoveImpl);
};
@@ -38,30 +48,39 @@ class CopyOrMoveOnSameFileSystemImpl
CopyOrMoveOperationDelegate::OperationType operation_type,
const FileSystemURL& src_url,
const FileSystemURL& dest_url,
+ CopyOrMoveOperationDelegate::CopyOrMoveOption option,
const FileSystemOperation::CopyFileProgressCallback&
file_progress_callback)
: operation_runner_(operation_runner),
operation_type_(operation_type),
src_url_(src_url),
dest_url_(dest_url),
+ option_(option),
file_progress_callback_(file_progress_callback) {
}
virtual void Run(
const CopyOrMoveOperationDelegate::StatusCallback& callback) OVERRIDE {
if (operation_type_ == CopyOrMoveOperationDelegate::OPERATION_MOVE) {
- operation_runner_->MoveFileLocal(src_url_, dest_url_, callback);
+ operation_runner_->MoveFileLocal(src_url_, dest_url_, option_, callback);
} else {
operation_runner_->CopyFileLocal(
- src_url_, dest_url_, file_progress_callback_, callback);
+ src_url_, dest_url_, option_, file_progress_callback_, callback);
}
}
+ virtual void Cancel() OVERRIDE {
+ // We can do nothing for the copy/move operation on a local file system.
+ // Assuming the operation is quickly done, it should be ok to just wait
+ // for the completion.
+ }
+
private:
FileSystemOperationRunner* operation_runner_;
CopyOrMoveOperationDelegate::OperationType operation_type_;
FileSystemURL src_url_;
FileSystemURL dest_url_;
+ CopyOrMoveOperationDelegate::CopyOrMoveOption option_;
FileSystemOperation::CopyFileProgressCallback file_progress_callback_;
DISALLOW_COPY_AND_ASSIGN(CopyOrMoveOnSameFileSystemImpl);
};
@@ -78,6 +97,7 @@ class SnapshotCopyOrMoveImpl
CopyOrMoveOperationDelegate::OperationType operation_type,
const FileSystemURL& src_url,
const FileSystemURL& dest_url,
+ CopyOrMoveOperationDelegate::CopyOrMoveOption option,
CopyOrMoveFileValidatorFactory* validator_factory,
const FileSystemOperation::CopyFileProgressCallback&
file_progress_callback)
@@ -85,8 +105,10 @@ class SnapshotCopyOrMoveImpl
operation_type_(operation_type),
src_url_(src_url),
dest_url_(dest_url),
+ option_(option),
validator_factory_(validator_factory),
file_progress_callback_(file_progress_callback),
+ cancel_requested_(false),
weak_factory_(this) {
}
@@ -99,6 +121,10 @@ class SnapshotCopyOrMoveImpl
weak_factory_.GetWeakPtr(), callback));
}
+ virtual void Cancel() OVERRIDE {
+ cancel_requested_ = true;
+ }
+
private:
void RunAfterCreateSnapshot(
const CopyOrMoveOperationDelegate::StatusCallback& callback,
@@ -106,6 +132,9 @@ class SnapshotCopyOrMoveImpl
const base::PlatformFileInfo& file_info,
const base::FilePath& platform_path,
const scoped_refptr<webkit_blob::ShareableFileReference>& file_ref) {
+ if (cancel_requested_)
+ error = base::PLATFORM_FILE_ERROR_ABORT;
+
if (error != base::PLATFORM_FILE_OK) {
callback.Run(error);
return;
@@ -136,6 +165,9 @@ class SnapshotCopyOrMoveImpl
const scoped_refptr<webkit_blob::ShareableFileReference>& file_ref,
const CopyOrMoveOperationDelegate::StatusCallback& callback,
base::PlatformFileError error) {
+ if (cancel_requested_)
+ error = base::PLATFORM_FILE_ERROR_ABORT;
+
if (error != base::PLATFORM_FILE_OK) {
callback.Run(error);
return;
@@ -154,6 +186,9 @@ class SnapshotCopyOrMoveImpl
const scoped_refptr<webkit_blob::ShareableFileReference>& file_ref,
const CopyOrMoveOperationDelegate::StatusCallback& callback,
base::PlatformFileError error) {
+ if (cancel_requested_)
+ error = base::PLATFORM_FILE_ERROR_ABORT;
+
if (error != base::PLATFORM_FILE_OK) {
callback.Run(error);
return;
@@ -161,6 +196,28 @@ class SnapshotCopyOrMoveImpl
file_progress_callback_.Run(file_info.size);
+ if (option_ == FileSystemOperation::OPTION_NONE) {
+ RunAfterTouchFile(callback, base::PLATFORM_FILE_OK);
+ return;
+ }
+
+ operation_runner_->TouchFile(
+ dest_url_, base::Time::Now() /* last_access */,
+ file_info.last_modified,
+ base::Bind(&SnapshotCopyOrMoveImpl::RunAfterTouchFile,
+ weak_factory_.GetWeakPtr(), callback));
+ }
+
+ void RunAfterTouchFile(
+ const CopyOrMoveOperationDelegate::StatusCallback& callback,
+ base::PlatformFileError error) {
+ // Even if TouchFile is failed, just ignore it.
+
+ if (cancel_requested_) {
+ callback.Run(base::PLATFORM_FILE_ERROR_ABORT);
+ return;
+ }
+
// |validator_| is NULL when the destination filesystem does not do
// validation.
if (!validator_) {
@@ -177,6 +234,11 @@ class SnapshotCopyOrMoveImpl
void RunAfterPostWriteValidation(
const CopyOrMoveOperationDelegate::StatusCallback& callback,
base::PlatformFileError error) {
+ if (cancel_requested_) {
+ callback.Run(base::PLATFORM_FILE_ERROR_ABORT);
+ return;
+ }
+
if (error != base::PLATFORM_FILE_OK) {
// Failed to validate. Remove the destination file.
operation_runner_->Remove(
@@ -203,6 +265,9 @@ class SnapshotCopyOrMoveImpl
void RunAfterRemoveSourceForMove(
const CopyOrMoveOperationDelegate::StatusCallback& callback,
base::PlatformFileError error) {
+ if (cancel_requested_)
+ error = base::PLATFORM_FILE_ERROR_ABORT;
+
if (error == base::PLATFORM_FILE_ERROR_NOT_FOUND)
error = base::PLATFORM_FILE_OK;
callback.Run(error);
@@ -246,6 +311,9 @@ class SnapshotCopyOrMoveImpl
const base::PlatformFileInfo& file_info,
const base::FilePath& platform_path,
const scoped_refptr<webkit_blob::ShareableFileReference>& file_ref) {
+ if (cancel_requested_)
+ error = base::PLATFORM_FILE_ERROR_ABORT;
+
if (error != base::PLATFORM_FILE_OK) {
callback.Run(error);
return;
@@ -273,28 +341,352 @@ class SnapshotCopyOrMoveImpl
CopyOrMoveOperationDelegate::OperationType operation_type_;
FileSystemURL src_url_;
FileSystemURL dest_url_;
+
+ CopyOrMoveOperationDelegate::CopyOrMoveOption option_;
CopyOrMoveFileValidatorFactory* validator_factory_;
scoped_ptr<CopyOrMoveFileValidator> validator_;
FileSystemOperation::CopyFileProgressCallback file_progress_callback_;
-
+ bool cancel_requested_;
base::WeakPtrFactory<SnapshotCopyOrMoveImpl> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(SnapshotCopyOrMoveImpl);
};
+// The size of buffer for StreamCopyHelper.
+const int kReadBufferSize = 32768;
+
+// To avoid too many progress callbacks, it should be called less
+// frequently than 50ms.
+const int kMinProgressCallbackInvocationSpanInMilliseconds = 50;
+
+// Specifically for cross file system copy/move operation, this class uses
+// stream reader and writer for copying. Validator is not supported, so if
+// necessary SnapshotCopyOrMoveImpl should be used.
+class StreamCopyOrMoveImpl
+ : public CopyOrMoveOperationDelegate::CopyOrMoveImpl {
+ public:
+ StreamCopyOrMoveImpl(
+ FileSystemOperationRunner* operation_runner,
+ CopyOrMoveOperationDelegate::OperationType operation_type,
+ const FileSystemURL& src_url,
+ const FileSystemURL& dest_url,
+ CopyOrMoveOperationDelegate::CopyOrMoveOption option,
+ scoped_ptr<webkit_blob::FileStreamReader> reader,
+ scoped_ptr<FileStreamWriter> writer,
+ const FileSystemOperation::CopyFileProgressCallback&
+ file_progress_callback)
+ : operation_runner_(operation_runner),
+ operation_type_(operation_type),
+ src_url_(src_url),
+ dest_url_(dest_url),
+ option_(option),
+ reader_(reader.Pass()),
+ writer_(writer.Pass()),
+ file_progress_callback_(file_progress_callback),
+ cancel_requested_(false),
+ weak_factory_(this) {
+ }
+
+ virtual void Run(
+ const CopyOrMoveOperationDelegate::StatusCallback& callback) OVERRIDE {
+ // Reader can be created even if the entry does not exist or the entry is
+ // a directory. To check errors before destination file creation,
+ // check metadata first.
+ operation_runner_->GetMetadata(
+ src_url_,
+ base::Bind(&StreamCopyOrMoveImpl::RunAfterGetMetadataForSource,
+ weak_factory_.GetWeakPtr(), callback));
+ }
+
+ virtual void Cancel() OVERRIDE {
+ cancel_requested_ = true;
+ if (copy_helper_)
+ copy_helper_->Cancel();
+ }
+
+ private:
+ void RunAfterGetMetadataForSource(
+ const CopyOrMoveOperationDelegate::StatusCallback& callback,
+ base::PlatformFileError error,
+ const base::PlatformFileInfo& file_info) {
+ if (cancel_requested_)
+ error = base::PLATFORM_FILE_ERROR_ABORT;
+
+ if (error != base::PLATFORM_FILE_OK) {
+ callback.Run(error);
+ return;
+ }
+
+ if (file_info.is_directory) {
+ // If not a directory, failed with appropriate error code.
+ callback.Run(base::PLATFORM_FILE_ERROR_NOT_A_FILE);
+ return;
+ }
+
+ // To use FileStreamWriter, we need to ensure the destination file exists.
+ operation_runner_->CreateFile(
+ dest_url_, false /* exclusive */,
+ base::Bind(&StreamCopyOrMoveImpl::RunAfterCreateFileForDestination,
+ weak_factory_.GetWeakPtr(),
+ callback, file_info.last_modified));
+ }
+
+ void RunAfterCreateFileForDestination(
+ const CopyOrMoveOperationDelegate::StatusCallback& callback,
+ const base::Time& last_modified,
+ base::PlatformFileError error) {
+ if (cancel_requested_)
+ error = base::PLATFORM_FILE_ERROR_ABORT;
+
+ if (error != base::PLATFORM_FILE_OK) {
+ callback.Run(error);
+ return;
+ }
+
+ const bool need_flush = dest_url_.mount_option().copy_sync_option() ==
+ fileapi::COPY_SYNC_OPTION_SYNC;
+
+ DCHECK(!copy_helper_);
+ copy_helper_.reset(
+ new CopyOrMoveOperationDelegate::StreamCopyHelper(
+ reader_.Pass(), writer_.Pass(),
+ need_flush,
+ kReadBufferSize,
+ file_progress_callback_,
+ base::TimeDelta::FromMilliseconds(
+ kMinProgressCallbackInvocationSpanInMilliseconds)));
+ copy_helper_->Run(
+ base::Bind(&StreamCopyOrMoveImpl::RunAfterStreamCopy,
+ weak_factory_.GetWeakPtr(), callback, last_modified));
+ }
+
+ void RunAfterStreamCopy(
+ const CopyOrMoveOperationDelegate::StatusCallback& callback,
+ const base::Time& last_modified,
+ base::PlatformFileError error) {
+ if (cancel_requested_)
+ error = base::PLATFORM_FILE_ERROR_ABORT;
+
+ if (error != base::PLATFORM_FILE_OK) {
+ callback.Run(error);
+ return;
+ }
+
+ if (option_ == FileSystemOperation::OPTION_NONE) {
+ RunAfterTouchFile(callback, base::PLATFORM_FILE_OK);
+ return;
+ }
+
+ operation_runner_->TouchFile(
+ dest_url_, base::Time::Now() /* last_access */, last_modified,
+ base::Bind(&StreamCopyOrMoveImpl::RunAfterTouchFile,
+ weak_factory_.GetWeakPtr(), callback));
+ }
+
+ void RunAfterTouchFile(
+ const CopyOrMoveOperationDelegate::StatusCallback& callback,
+ base::PlatformFileError error) {
+ // Even if TouchFile is failed, just ignore it.
+ if (cancel_requested_) {
+ callback.Run(base::PLATFORM_FILE_ERROR_ABORT);
+ return;
+ }
+
+ if (operation_type_ == CopyOrMoveOperationDelegate::OPERATION_COPY) {
+ callback.Run(base::PLATFORM_FILE_OK);
+ return;
+ }
+
+ DCHECK_EQ(CopyOrMoveOperationDelegate::OPERATION_MOVE, operation_type_);
+
+ // Remove the source for finalizing move operation.
+ operation_runner_->Remove(
+ src_url_, false /* recursive */,
+ base::Bind(&StreamCopyOrMoveImpl::RunAfterRemoveForMove,
+ weak_factory_.GetWeakPtr(), callback));
+ }
+
+ void RunAfterRemoveForMove(
+ const CopyOrMoveOperationDelegate::StatusCallback& callback,
+ base::PlatformFileError error) {
+ if (cancel_requested_)
+ error = base::PLATFORM_FILE_ERROR_ABORT;
+ if (error == base::PLATFORM_FILE_ERROR_NOT_FOUND)
+ error = base::PLATFORM_FILE_OK;
+ callback.Run(error);
+ }
+
+ FileSystemOperationRunner* operation_runner_;
+ CopyOrMoveOperationDelegate::OperationType operation_type_;
+ FileSystemURL src_url_;
+ FileSystemURL dest_url_;
+ CopyOrMoveOperationDelegate::CopyOrMoveOption option_;
+ scoped_ptr<webkit_blob::FileStreamReader> reader_;
+ scoped_ptr<FileStreamWriter> writer_;
+ FileSystemOperation::CopyFileProgressCallback file_progress_callback_;
+ scoped_ptr<CopyOrMoveOperationDelegate::StreamCopyHelper> copy_helper_;
+ bool cancel_requested_;
+ base::WeakPtrFactory<StreamCopyOrMoveImpl> weak_factory_;
+ DISALLOW_COPY_AND_ASSIGN(StreamCopyOrMoveImpl);
+};
+
} // namespace
+CopyOrMoveOperationDelegate::StreamCopyHelper::StreamCopyHelper(
+ scoped_ptr<webkit_blob::FileStreamReader> reader,
+ scoped_ptr<FileStreamWriter> writer,
+ bool need_flush,
+ int buffer_size,
+ const FileSystemOperation::CopyFileProgressCallback&
+ file_progress_callback,
+ const base::TimeDelta& min_progress_callback_invocation_span)
+ : reader_(reader.Pass()),
+ writer_(writer.Pass()),
+ need_flush_(need_flush),
+ file_progress_callback_(file_progress_callback),
+ io_buffer_(new net::IOBufferWithSize(buffer_size)),
+ num_copied_bytes_(0),
+ previous_flush_offset_(0),
+ min_progress_callback_invocation_span_(
+ min_progress_callback_invocation_span),
+ cancel_requested_(false),
+ weak_factory_(this) {
+}
+
+CopyOrMoveOperationDelegate::StreamCopyHelper::~StreamCopyHelper() {
+}
+
+void CopyOrMoveOperationDelegate::StreamCopyHelper::Run(
+ const StatusCallback& callback) {
+ file_progress_callback_.Run(0);
+ last_progress_callback_invocation_time_ = base::Time::Now();
+ Read(callback);
+}
+
+void CopyOrMoveOperationDelegate::StreamCopyHelper::Cancel() {
+ cancel_requested_ = true;
+}
+
+void CopyOrMoveOperationDelegate::StreamCopyHelper::Read(
+ const StatusCallback& callback) {
+ int result = reader_->Read(
+ io_buffer_.get(), io_buffer_->size(),
+ base::Bind(&StreamCopyHelper::DidRead,
+ weak_factory_.GetWeakPtr(), callback));
+ if (result != net::ERR_IO_PENDING)
+ DidRead(callback, result);
+}
+
+void CopyOrMoveOperationDelegate::StreamCopyHelper::DidRead(
+ const StatusCallback& callback, int result) {
+ if (cancel_requested_) {
+ callback.Run(base::PLATFORM_FILE_ERROR_ABORT);
+ return;
+ }
+
+ if (result < 0) {
+ callback.Run(NetErrorToPlatformFileError(result));
+ return;
+ }
+
+ if (result == 0) {
+ // Here is the EOF.
+ if (need_flush_)
+ Flush(callback, true /* is_eof */);
+ else
+ callback.Run(base::PLATFORM_FILE_OK);
+ return;
+ }
+
+ Write(callback, new net::DrainableIOBuffer(io_buffer_.get(), result));
+}
+
+void CopyOrMoveOperationDelegate::StreamCopyHelper::Write(
+ const StatusCallback& callback,
+ scoped_refptr<net::DrainableIOBuffer> buffer) {
+ DCHECK_GT(buffer->BytesRemaining(), 0);
+
+ int result = writer_->Write(
+ buffer.get(), buffer->BytesRemaining(),
+ base::Bind(&StreamCopyHelper::DidWrite,
+ weak_factory_.GetWeakPtr(), callback, buffer));
+ if (result != net::ERR_IO_PENDING)
+ DidWrite(callback, buffer, result);
+}
+
+void CopyOrMoveOperationDelegate::StreamCopyHelper::DidWrite(
+ const StatusCallback& callback,
+ scoped_refptr<net::DrainableIOBuffer> buffer,
+ int result) {
+ if (cancel_requested_) {
+ callback.Run(base::PLATFORM_FILE_ERROR_ABORT);
+ return;
+ }
+
+ if (result < 0) {
+ callback.Run(NetErrorToPlatformFileError(result));
+ return;
+ }
+
+ buffer->DidConsume(result);
+ num_copied_bytes_ += result;
+
+ // Check the elapsed time since last |file_progress_callback_| invocation.
+ base::Time now = base::Time::Now();
+ if (now - last_progress_callback_invocation_time_ >=
+ min_progress_callback_invocation_span_) {
+ file_progress_callback_.Run(num_copied_bytes_);
+ last_progress_callback_invocation_time_ = now;
+ }
+
+ if (buffer->BytesRemaining() > 0) {
+ Write(callback, buffer);
+ return;
+ }
+
+ if (need_flush_ &&
+ (num_copied_bytes_ - previous_flush_offset_) > kFlushIntervalInBytes) {
+ Flush(callback, false /* not is_eof */);
+ } else {
+ Read(callback);
+ }
+}
+
+void CopyOrMoveOperationDelegate::StreamCopyHelper::Flush(
+ const StatusCallback& callback, bool is_eof) {
+ int result = writer_->Flush(
+ base::Bind(&StreamCopyHelper::DidFlush,
+ weak_factory_.GetWeakPtr(), callback, is_eof));
+ if (result != net::ERR_IO_PENDING)
+ DidFlush(callback, is_eof, result);
+}
+
+void CopyOrMoveOperationDelegate::StreamCopyHelper::DidFlush(
+ const StatusCallback& callback, bool is_eof, int result) {
+ if (cancel_requested_) {
+ callback.Run(base::PLATFORM_FILE_ERROR_ABORT);
+ return;
+ }
+
+ previous_flush_offset_ = num_copied_bytes_;
+ if (is_eof)
+ callback.Run(NetErrorToPlatformFileError(result));
+ else
+ Read(callback);
+}
CopyOrMoveOperationDelegate::CopyOrMoveOperationDelegate(
FileSystemContext* file_system_context,
const FileSystemURL& src_root,
const FileSystemURL& dest_root,
OperationType operation_type,
+ CopyOrMoveOption option,
const CopyProgressCallback& progress_callback,
const StatusCallback& callback)
: RecursiveOperationDelegate(file_system_context),
src_root_(src_root),
dest_root_(dest_root),
operation_type_(operation_type),
+ option_(option),
progress_callback_(progress_callback),
callback_(callback),
weak_factory_(this) {
@@ -344,12 +736,11 @@ void CopyOrMoveOperationDelegate::ProcessFile(
CopyOrMoveImpl* impl = NULL;
if (same_file_system_) {
impl = new CopyOrMoveOnSameFileSystemImpl(
- operation_runner(), operation_type_, src_url, dest_url,
+ operation_runner(), operation_type_, src_url, dest_url, option_,
base::Bind(&CopyOrMoveOperationDelegate::OnCopyFileProgress,
weak_factory_.GetWeakPtr(), src_url));
} else {
// Cross filesystem case.
- // TODO(hidehiko): Support stream based copy. crbug.com/279287.
base::PlatformFileError error = base::PLATFORM_FILE_ERROR_FAILED;
CopyOrMoveFileValidatorFactory* validator_factory =
file_system_context()->GetCopyOrMoveFileValidatorFactory(
@@ -359,11 +750,28 @@ void CopyOrMoveOperationDelegate::ProcessFile(
return;
}
- impl = new SnapshotCopyOrMoveImpl(
- operation_runner(), operation_type_, src_url, dest_url,
- validator_factory,
- base::Bind(&CopyOrMoveOperationDelegate::OnCopyFileProgress,
- weak_factory_.GetWeakPtr(), src_url));
+ if (!validator_factory) {
+ scoped_ptr<webkit_blob::FileStreamReader> reader =
+ file_system_context()->CreateFileStreamReader(
+ src_url, 0, base::Time());
+ scoped_ptr<FileStreamWriter> writer =
+ file_system_context()->CreateFileStreamWriter(dest_url, 0);
+ if (reader && writer) {
+ impl = new StreamCopyOrMoveImpl(
+ operation_runner(), operation_type_, src_url, dest_url, option_,
+ reader.Pass(), writer.Pass(),
+ base::Bind(&CopyOrMoveOperationDelegate::OnCopyFileProgress,
+ weak_factory_.GetWeakPtr(), src_url));
+ }
+ }
+
+ if (!impl) {
+ impl = new SnapshotCopyOrMoveImpl(
+ operation_runner(), operation_type_, src_url, dest_url, option_,
+ validator_factory,
+ base::Bind(&CopyOrMoveOperationDelegate::OnCopyFileProgress,
+ weak_factory_.GetWeakPtr(), src_url));
+ }
}
// Register the running task.
@@ -400,19 +808,24 @@ void CopyOrMoveOperationDelegate::ProcessDirectory(
void CopyOrMoveOperationDelegate::PostProcessDirectory(
const FileSystemURL& src_url,
const StatusCallback& callback) {
- if (operation_type_ == OPERATION_COPY) {
- callback.Run(base::PLATFORM_FILE_OK);
+ if (option_ == FileSystemOperation::OPTION_NONE) {
+ PostProcessDirectoryAfterTouchFile(
+ src_url, callback, base::PLATFORM_FILE_OK);
return;
}
- DCHECK_EQ(OPERATION_MOVE, operation_type_);
+ operation_runner()->GetMetadata(
+ src_url,
+ base::Bind(
+ &CopyOrMoveOperationDelegate::PostProcessDirectoryAfterGetMetadata,
+ weak_factory_.GetWeakPtr(), src_url, callback));
+}
- // All files and subdirectories in the directory should be moved here,
- // so remove the source directory for finalizing move operation.
- operation_runner()->Remove(
- src_url, false /* recursive */,
- base::Bind(&CopyOrMoveOperationDelegate::DidRemoveSourceForMove,
- weak_factory_.GetWeakPtr(), callback));
+void CopyOrMoveOperationDelegate::OnCancel() {
+ // Request to cancel all running Copy/Move file.
+ for (std::set<CopyOrMoveImpl*>::iterator iter = running_copy_set_.begin();
+ iter != running_copy_set_.end(); ++iter)
+ (*iter)->Cancel();
}
void CopyOrMoveOperationDelegate::DidCopyOrMoveFile(
@@ -475,6 +888,47 @@ void CopyOrMoveOperationDelegate::DidCreateDirectory(
callback.Run(error);
}
+void CopyOrMoveOperationDelegate::PostProcessDirectoryAfterGetMetadata(
+ const FileSystemURL& src_url,
+ const StatusCallback& callback,
+ base::PlatformFileError error,
+ const base::PlatformFileInfo& file_info) {
+ if (error != base::PLATFORM_FILE_OK) {
+ // Ignore the error, and run post process which should run after TouchFile.
+ PostProcessDirectoryAfterTouchFile(
+ src_url, callback, base::PLATFORM_FILE_OK);
+ return;
+ }
+
+ operation_runner()->TouchFile(
+ CreateDestURL(src_url), base::Time::Now() /* last access */,
+ file_info.last_modified,
+ base::Bind(
+ &CopyOrMoveOperationDelegate::PostProcessDirectoryAfterTouchFile,
+ weak_factory_.GetWeakPtr(), src_url, callback));
+}
+
+void CopyOrMoveOperationDelegate::PostProcessDirectoryAfterTouchFile(
+ const FileSystemURL& src_url,
+ const StatusCallback& callback,
+ base::PlatformFileError error) {
+ // Even if the TouchFile is failed, just ignore it.
+
+ if (operation_type_ == OPERATION_COPY) {
+ callback.Run(base::PLATFORM_FILE_OK);
+ return;
+ }
+
+ DCHECK_EQ(OPERATION_MOVE, operation_type_);
+
+ // All files and subdirectories in the directory should be moved here,
+ // so remove the source directory for finalizing move operation.
+ operation_runner()->Remove(
+ src_url, false /* recursive */,
+ base::Bind(&CopyOrMoveOperationDelegate::DidRemoveSourceForMove,
+ weak_factory_.GetWeakPtr(), callback));
+}
+
void CopyOrMoveOperationDelegate::DidRemoveSourceForMove(
const StatusCallback& callback,
base::PlatformFileError error) {
diff --git a/chromium/webkit/browser/fileapi/copy_or_move_operation_delegate.h b/chromium/webkit/browser/fileapi/copy_or_move_operation_delegate.h
index 77d1a76efc6..2247c87202e 100644
--- a/chromium/webkit/browser/fileapi/copy_or_move_operation_delegate.h
+++ b/chromium/webkit/browser/fileapi/copy_or_move_operation_delegate.h
@@ -5,19 +5,28 @@
#ifndef WEBKIT_BROWSER_FILEAPI_COPY_OR_MOVE_OPERATION_DELEGATE_H_
#define WEBKIT_BROWSER_FILEAPI_COPY_OR_MOVE_OPERATION_DELEGATE_H_
+#include <set>
#include <stack>
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
+#include "base/time/time.h"
#include "webkit/browser/fileapi/recursive_operation_delegate.h"
+namespace net {
+class DrainableIOBuffer;
+class IOBufferWithSize;
+}
+
namespace webkit_blob {
+class FileStreamReader;
class ShareableFileReference;
}
namespace fileapi {
class CopyOrMoveFileValidator;
+class FileStreamWriter;
// A delegate class for recursive copy or move operations.
class CopyOrMoveOperationDelegate
@@ -25,17 +34,68 @@ class CopyOrMoveOperationDelegate
public:
class CopyOrMoveImpl;
typedef FileSystemOperation::CopyProgressCallback CopyProgressCallback;
+ typedef FileSystemOperation::CopyOrMoveOption CopyOrMoveOption;
enum OperationType {
OPERATION_COPY,
OPERATION_MOVE
};
+ // Helper to copy a file by reader and writer streams.
+ // Export for testing.
+ class WEBKIT_STORAGE_BROWSER_EXPORT StreamCopyHelper {
+ public:
+ StreamCopyHelper(
+ scoped_ptr<webkit_blob::FileStreamReader> reader,
+ scoped_ptr<FileStreamWriter> writer,
+ bool need_flush,
+ int buffer_size,
+ const FileSystemOperation::CopyFileProgressCallback&
+ file_progress_callback,
+ const base::TimeDelta& min_progress_callback_invocation_span);
+ ~StreamCopyHelper();
+
+ void Run(const StatusCallback& callback);
+
+ // Requests cancelling. After the cancelling is done, |callback| passed to
+ // Run will be called.
+ void Cancel();
+
+ private:
+ // Reads the content from the |reader_|.
+ void Read(const StatusCallback& callback);
+ void DidRead(const StatusCallback& callback, int result);
+
+ // Writes the content in |buffer| to |writer_|.
+ void Write(const StatusCallback& callback,
+ scoped_refptr<net::DrainableIOBuffer> buffer);
+ void DidWrite(const StatusCallback& callback,
+ scoped_refptr<net::DrainableIOBuffer> buffer, int result);
+
+ // Flushes the written content in |writer_|.
+ void Flush(const StatusCallback& callback, bool is_eof);
+ void DidFlush(const StatusCallback& callback, bool is_eof, int result);
+
+ scoped_ptr<webkit_blob::FileStreamReader> reader_;
+ scoped_ptr<FileStreamWriter> writer_;
+ const bool need_flush_;
+ FileSystemOperation::CopyFileProgressCallback file_progress_callback_;
+ scoped_refptr<net::IOBufferWithSize> io_buffer_;
+ int64 num_copied_bytes_;
+ int64 previous_flush_offset_;
+ base::Time last_progress_callback_invocation_time_;
+ base::TimeDelta min_progress_callback_invocation_span_;
+ bool cancel_requested_;
+ base::WeakPtrFactory<StreamCopyHelper> weak_factory_;
+ DISALLOW_COPY_AND_ASSIGN(StreamCopyHelper);
+ };
+
CopyOrMoveOperationDelegate(
FileSystemContext* file_system_context,
const FileSystemURL& src_root,
const FileSystemURL& dest_root,
OperationType operation_type,
+ CopyOrMoveOption option,
const CopyProgressCallback& progress_callback,
const StatusCallback& callback);
virtual ~CopyOrMoveOperationDelegate();
@@ -50,6 +110,10 @@ class CopyOrMoveOperationDelegate
virtual void PostProcessDirectory(const FileSystemURL& url,
const StatusCallback& callback) OVERRIDE;
+
+ protected:
+ virtual void OnCancel() OVERRIDE;
+
private:
void DidCopyOrMoveFile(const FileSystemURL& src_url,
const FileSystemURL& dest_url,
@@ -65,6 +129,14 @@ class CopyOrMoveOperationDelegate
const FileSystemURL& dest_url,
const StatusCallback& callback,
base::PlatformFileError error);
+ void PostProcessDirectoryAfterGetMetadata(
+ const FileSystemURL& src_url,
+ const StatusCallback& callback,
+ base::PlatformFileError error,
+ const base::PlatformFileInfo& file_info);
+ void PostProcessDirectoryAfterTouchFile(const FileSystemURL& src_url,
+ const StatusCallback& callback,
+ base::PlatformFileError error);
void DidRemoveSourceForMove(const StatusCallback& callback,
base::PlatformFileError error);
@@ -75,6 +147,7 @@ class CopyOrMoveOperationDelegate
FileSystemURL dest_root_;
bool same_file_system_;
OperationType operation_type_;
+ CopyOrMoveOption option_;
CopyProgressCallback progress_callback_;
StatusCallback callback_;
diff --git a/chromium/webkit/browser/fileapi/copy_or_move_operation_delegate_unittest.cc b/chromium/webkit/browser/fileapi/copy_or_move_operation_delegate_unittest.cc
deleted file mode 100644
index 322341dc40f..00000000000
--- a/chromium/webkit/browser/fileapi/copy_or_move_operation_delegate_unittest.cc
+++ /dev/null
@@ -1,665 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <map>
-#include <queue>
-
-#include "base/basictypes.h"
-#include "base/bind.h"
-#include "base/files/scoped_temp_dir.h"
-#include "base/message_loop/message_loop.h"
-#include "base/run_loop.h"
-#include "base/stl_util.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "webkit/browser/fileapi/async_file_test_helper.h"
-#include "webkit/browser/fileapi/copy_or_move_file_validator.h"
-#include "webkit/browser/fileapi/file_system_backend.h"
-#include "webkit/browser/fileapi/file_system_context.h"
-#include "webkit/browser/fileapi/file_system_operation.h"
-#include "webkit/browser/fileapi/file_system_url.h"
-#include "webkit/browser/fileapi/mock_file_system_context.h"
-#include "webkit/browser/fileapi/test_file_set.h"
-#include "webkit/browser/fileapi/test_file_system_backend.h"
-#include "webkit/browser/quota/mock_quota_manager.h"
-#include "webkit/browser/quota/quota_manager.h"
-#include "webkit/common/fileapi/file_system_util.h"
-
-namespace fileapi {
-
-typedef FileSystemOperation::FileEntryList FileEntryList;
-
-namespace {
-
-void ExpectOk(const GURL& origin_url,
- const std::string& name,
- base::PlatformFileError error) {
- ASSERT_EQ(base::PLATFORM_FILE_OK, error);
-}
-
-class TestValidatorFactory : public CopyOrMoveFileValidatorFactory {
- public:
- // A factory that creates validators that accept everything or nothing.
- TestValidatorFactory() {}
- virtual ~TestValidatorFactory() {}
-
- virtual CopyOrMoveFileValidator* CreateCopyOrMoveFileValidator(
- const FileSystemURL& /*src_url*/,
- const base::FilePath& /*platform_path*/) OVERRIDE {
- // Move arg management to TestValidator?
- return new TestValidator(true, true, std::string("2"));
- }
-
- private:
- class TestValidator : public CopyOrMoveFileValidator {
- public:
- explicit TestValidator(bool pre_copy_valid,
- bool post_copy_valid,
- const std::string& reject_string)
- : result_(pre_copy_valid ? base::PLATFORM_FILE_OK
- : base::PLATFORM_FILE_ERROR_SECURITY),
- write_result_(post_copy_valid ? base::PLATFORM_FILE_OK
- : base::PLATFORM_FILE_ERROR_SECURITY),
- reject_string_(reject_string) {
- }
- virtual ~TestValidator() {}
-
- virtual void StartPreWriteValidation(
- const ResultCallback& result_callback) OVERRIDE {
- // Post the result since a real validator must do work asynchronously.
- base::MessageLoop::current()->PostTask(
- FROM_HERE, base::Bind(result_callback, result_));
- }
-
- virtual void StartPostWriteValidation(
- const base::FilePath& dest_platform_path,
- const ResultCallback& result_callback) OVERRIDE {
- base::PlatformFileError result = write_result_;
- std::string unsafe = dest_platform_path.BaseName().AsUTF8Unsafe();
- if (unsafe.find(reject_string_) != std::string::npos) {
- result = base::PLATFORM_FILE_ERROR_SECURITY;
- }
- // Post the result since a real validator must do work asynchronously.
- base::MessageLoop::current()->PostTask(
- FROM_HERE, base::Bind(result_callback, result));
- }
-
- private:
- base::PlatformFileError result_;
- base::PlatformFileError write_result_;
- std::string reject_string_;
-
- DISALLOW_COPY_AND_ASSIGN(TestValidator);
- };
-};
-
-// Records CopyProgressCallback invocations.
-struct ProgressRecord {
- FileSystemOperation::CopyProgressType type;
- FileSystemURL source_url;
- FileSystemURL dest_url;
- int64 size;
-};
-
-void RecordProgressCallback(std::vector<ProgressRecord>* records,
- FileSystemOperation::CopyProgressType type,
- const FileSystemURL& source_url,
- const FileSystemURL& dest_url,
- int64 size) {
- ProgressRecord record;
- record.type = type;
- record.source_url = source_url;
- record.dest_url = dest_url;
- record.size = size;
- records->push_back(record);
-}
-
-} // namespace
-
-class CopyOrMoveOperationTestHelper {
- public:
- CopyOrMoveOperationTestHelper(
- const GURL& origin,
- FileSystemType src_type,
- FileSystemType dest_type)
- : origin_(origin),
- src_type_(src_type),
- dest_type_(dest_type) {}
-
- ~CopyOrMoveOperationTestHelper() {
- file_system_context_ = NULL;
- quota_manager_proxy_->SimulateQuotaManagerDestroyed();
- quota_manager_ = NULL;
- quota_manager_proxy_ = NULL;
- base::RunLoop().RunUntilIdle();
- }
-
- void SetUp() {
- SetUp(true, true);
- }
-
- void SetUpNoValidator() {
- SetUp(true, false);
- }
-
- void SetUp(bool require_copy_or_move_validator,
- bool init_copy_or_move_validator) {
- ASSERT_TRUE(base_.CreateUniqueTempDir());
- base::FilePath base_dir = base_.path();
- quota_manager_ =
- new quota::MockQuotaManager(false /* is_incognito */,
- base_dir,
- base::MessageLoopProxy::current().get(),
- base::MessageLoopProxy::current().get(),
- NULL /* special storage policy */);
- quota_manager_proxy_ = new quota::MockQuotaManagerProxy(
- quota_manager_.get(), base::MessageLoopProxy::current().get());
- file_system_context_ =
- CreateFileSystemContextForTesting(quota_manager_proxy_.get(), base_dir);
-
- // Prepare the origin's root directory.
- FileSystemBackend* backend =
- file_system_context_->GetFileSystemBackend(src_type_);
- backend->OpenFileSystem(origin_, src_type_,
- OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
- base::Bind(&ExpectOk));
- backend = file_system_context_->GetFileSystemBackend(dest_type_);
- if (dest_type_ == kFileSystemTypeTest) {
- TestFileSystemBackend* test_backend =
- static_cast<TestFileSystemBackend*>(backend);
- scoped_ptr<CopyOrMoveFileValidatorFactory> factory(
- new TestValidatorFactory);
- test_backend->set_require_copy_or_move_validator(
- require_copy_or_move_validator);
- if (init_copy_or_move_validator)
- test_backend->InitializeCopyOrMoveFileValidatorFactory(factory.Pass());
- }
- backend->OpenFileSystem(origin_, dest_type_,
- OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
- base::Bind(&ExpectOk));
- base::RunLoop().RunUntilIdle();
-
- // Grant relatively big quota initially.
- quota_manager_->SetQuota(origin_,
- FileSystemTypeToQuotaStorageType(src_type_),
- 1024 * 1024);
- quota_manager_->SetQuota(origin_,
- FileSystemTypeToQuotaStorageType(dest_type_),
- 1024 * 1024);
- }
-
- int64 GetSourceUsage() {
- int64 usage = 0;
- GetUsageAndQuota(src_type_, &usage, NULL);
- return usage;
- }
-
- int64 GetDestUsage() {
- int64 usage = 0;
- GetUsageAndQuota(dest_type_, &usage, NULL);
- return usage;
- }
-
- FileSystemURL SourceURL(const std::string& path) {
- return file_system_context_->CreateCrackedFileSystemURL(
- origin_, src_type_, base::FilePath::FromUTF8Unsafe(path));
- }
-
- FileSystemURL DestURL(const std::string& path) {
- return file_system_context_->CreateCrackedFileSystemURL(
- origin_, dest_type_, base::FilePath::FromUTF8Unsafe(path));
- }
-
- base::PlatformFileError Copy(const FileSystemURL& src,
- const FileSystemURL& dest) {
- return AsyncFileTestHelper::Copy(file_system_context_.get(), src, dest);
- }
-
- base::PlatformFileError CopyWithProgress(
- const FileSystemURL& src,
- const FileSystemURL& dest,
- const AsyncFileTestHelper::CopyProgressCallback& progress_callback) {
- return AsyncFileTestHelper::CopyWithProgress(
- file_system_context_.get(), src, dest, progress_callback);
- }
-
- base::PlatformFileError Move(const FileSystemURL& src,
- const FileSystemURL& dest) {
- return AsyncFileTestHelper::Move(file_system_context_.get(), src, dest);
- }
-
- base::PlatformFileError SetUpTestCaseFiles(
- const FileSystemURL& root,
- const test::TestCaseRecord* const test_cases,
- size_t test_case_size) {
- base::PlatformFileError result = base::PLATFORM_FILE_ERROR_FAILED;
- for (size_t i = 0; i < test_case_size; ++i) {
- const test::TestCaseRecord& test_case = test_cases[i];
- FileSystemURL url = file_system_context_->CreateCrackedFileSystemURL(
- root.origin(),
- root.mount_type(),
- root.virtual_path().Append(test_case.path));
- if (test_case.is_directory)
- result = CreateDirectory(url);
- else
- result = CreateFile(url, test_case.data_file_size);
- EXPECT_EQ(base::PLATFORM_FILE_OK, result) << url.DebugString();
- if (result != base::PLATFORM_FILE_OK)
- return result;
- }
- return result;
- }
-
- void VerifyTestCaseFiles(
- const FileSystemURL& root,
- const test::TestCaseRecord* const test_cases,
- size_t test_case_size) {
- std::map<base::FilePath, const test::TestCaseRecord*> test_case_map;
- for (size_t i = 0; i < test_case_size; ++i) {
- test_case_map[
- base::FilePath(test_cases[i].path).NormalizePathSeparators()] =
- &test_cases[i];
- }
-
- std::queue<FileSystemURL> directories;
- FileEntryList entries;
- directories.push(root);
- while (!directories.empty()) {
- FileSystemURL dir = directories.front();
- directories.pop();
- ASSERT_EQ(base::PLATFORM_FILE_OK, ReadDirectory(dir, &entries));
- for (size_t i = 0; i < entries.size(); ++i) {
- FileSystemURL url = file_system_context_->CreateCrackedFileSystemURL(
- dir.origin(),
- dir.mount_type(),
- dir.virtual_path().Append(entries[i].name));
- base::FilePath relative;
- root.virtual_path().AppendRelativePath(url.virtual_path(), &relative);
- relative = relative.NormalizePathSeparators();
- ASSERT_TRUE(ContainsKey(test_case_map, relative));
- if (entries[i].is_directory) {
- EXPECT_TRUE(test_case_map[relative]->is_directory);
- directories.push(url);
- } else {
- EXPECT_FALSE(test_case_map[relative]->is_directory);
- EXPECT_TRUE(FileExists(url, test_case_map[relative]->data_file_size));
- }
- test_case_map.erase(relative);
- }
- }
- EXPECT_TRUE(test_case_map.empty());
- std::map<base::FilePath, const test::TestCaseRecord*>::const_iterator it;
- for (it = test_case_map.begin(); it != test_case_map.end(); ++it) {
- LOG(ERROR) << "Extra entry: " << it->first.LossyDisplayName();
- }
- }
-
- base::PlatformFileError ReadDirectory(const FileSystemURL& url,
- FileEntryList* entries) {
- return AsyncFileTestHelper::ReadDirectory(
- file_system_context_.get(), url, entries);
- }
-
- base::PlatformFileError CreateDirectory(const FileSystemURL& url) {
- return AsyncFileTestHelper::CreateDirectory(file_system_context_.get(),
- url);
- }
-
- base::PlatformFileError CreateFile(const FileSystemURL& url, size_t size) {
- base::PlatformFileError result =
- AsyncFileTestHelper::CreateFile(file_system_context_.get(), url);
- if (result != base::PLATFORM_FILE_OK)
- return result;
- return AsyncFileTestHelper::TruncateFile(
- file_system_context_.get(), url, size);
- }
-
- bool FileExists(const FileSystemURL& url, int64 expected_size) {
- return AsyncFileTestHelper::FileExists(
- file_system_context_.get(), url, expected_size);
- }
-
- bool DirectoryExists(const FileSystemURL& url) {
- return AsyncFileTestHelper::DirectoryExists(file_system_context_.get(),
- url);
- }
-
- private:
- void GetUsageAndQuota(FileSystemType type, int64* usage, int64* quota) {
- quota::QuotaStatusCode status = AsyncFileTestHelper::GetUsageAndQuota(
- quota_manager_.get(), origin_, type, usage, quota);
- ASSERT_EQ(quota::kQuotaStatusOk, status);
- }
-
- private:
- base::ScopedTempDir base_;
-
- const GURL origin_;
- const FileSystemType src_type_;
- const FileSystemType dest_type_;
-
- base::MessageLoop message_loop_;
- scoped_refptr<FileSystemContext> file_system_context_;
- scoped_refptr<quota::MockQuotaManagerProxy> quota_manager_proxy_;
- scoped_refptr<quota::MockQuotaManager> quota_manager_;
-
- DISALLOW_COPY_AND_ASSIGN(CopyOrMoveOperationTestHelper);
-};
-
-TEST(LocalFileSystemCopyOrMoveOperationTest, CopySingleFile) {
- CopyOrMoveOperationTestHelper helper(GURL("http://foo"),
- kFileSystemTypeTemporary,
- kFileSystemTypePersistent);
- helper.SetUp();
-
- FileSystemURL src = helper.SourceURL("a");
- FileSystemURL dest = helper.DestURL("b");
- int64 src_initial_usage = helper.GetSourceUsage();
- int64 dest_initial_usage = helper.GetDestUsage();
-
- // Set up a source file.
- ASSERT_EQ(base::PLATFORM_FILE_OK, helper.CreateFile(src, 10));
- int64 src_increase = helper.GetSourceUsage() - src_initial_usage;
-
- // Copy it.
- ASSERT_EQ(base::PLATFORM_FILE_OK, helper.Copy(src, dest));
-
- // Verify.
- ASSERT_TRUE(helper.FileExists(src, 10));
- ASSERT_TRUE(helper.FileExists(dest, 10));
-
- int64 src_new_usage = helper.GetSourceUsage();
- ASSERT_EQ(src_initial_usage + src_increase, src_new_usage);
-
- int64 dest_increase = helper.GetDestUsage() - dest_initial_usage;
- ASSERT_EQ(src_increase, dest_increase);
-}
-
-TEST(LocalFileSystemCopyOrMoveOperationTest, MoveSingleFile) {
- CopyOrMoveOperationTestHelper helper(GURL("http://foo"),
- kFileSystemTypeTemporary,
- kFileSystemTypePersistent);
- helper.SetUp();
-
- FileSystemURL src = helper.SourceURL("a");
- FileSystemURL dest = helper.DestURL("b");
- int64 src_initial_usage = helper.GetSourceUsage();
- int64 dest_initial_usage = helper.GetDestUsage();
-
- // Set up a source file.
- ASSERT_EQ(base::PLATFORM_FILE_OK, helper.CreateFile(src, 10));
- int64 src_increase = helper.GetSourceUsage() - src_initial_usage;
-
- // Move it.
- ASSERT_EQ(base::PLATFORM_FILE_OK, helper.Move(src, dest));
-
- // Verify.
- ASSERT_FALSE(helper.FileExists(src, AsyncFileTestHelper::kDontCheckSize));
- ASSERT_TRUE(helper.FileExists(dest, 10));
-
- int64 src_new_usage = helper.GetSourceUsage();
- ASSERT_EQ(src_initial_usage, src_new_usage);
-
- int64 dest_increase = helper.GetDestUsage() - dest_initial_usage;
- ASSERT_EQ(src_increase, dest_increase);
-}
-
-TEST(LocalFileSystemCopyOrMoveOperationTest, CopySingleDirectory) {
- CopyOrMoveOperationTestHelper helper(GURL("http://foo"),
- kFileSystemTypeTemporary,
- kFileSystemTypePersistent);
- helper.SetUp();
-
- FileSystemURL src = helper.SourceURL("a");
- FileSystemURL dest = helper.DestURL("b");
- int64 src_initial_usage = helper.GetSourceUsage();
- int64 dest_initial_usage = helper.GetDestUsage();
-
- // Set up a source directory.
- ASSERT_EQ(base::PLATFORM_FILE_OK, helper.CreateDirectory(src));
- int64 src_increase = helper.GetSourceUsage() - src_initial_usage;
-
- // Copy it.
- ASSERT_EQ(base::PLATFORM_FILE_OK, helper.Copy(src, dest));
-
- // Verify.
- ASSERT_TRUE(helper.DirectoryExists(src));
- ASSERT_TRUE(helper.DirectoryExists(dest));
-
- int64 src_new_usage = helper.GetSourceUsage();
- ASSERT_EQ(src_initial_usage + src_increase, src_new_usage);
-
- int64 dest_increase = helper.GetDestUsage() - dest_initial_usage;
- ASSERT_EQ(src_increase, dest_increase);
-}
-
-TEST(LocalFileSystemCopyOrMoveOperationTest, MoveSingleDirectory) {
- CopyOrMoveOperationTestHelper helper(GURL("http://foo"),
- kFileSystemTypeTemporary,
- kFileSystemTypePersistent);
- helper.SetUp();
-
- FileSystemURL src = helper.SourceURL("a");
- FileSystemURL dest = helper.DestURL("b");
- int64 src_initial_usage = helper.GetSourceUsage();
- int64 dest_initial_usage = helper.GetDestUsage();
-
- // Set up a source directory.
- ASSERT_EQ(base::PLATFORM_FILE_OK, helper.CreateDirectory(src));
- int64 src_increase = helper.GetSourceUsage() - src_initial_usage;
-
- // Move it.
- ASSERT_EQ(base::PLATFORM_FILE_OK, helper.Move(src, dest));
-
- // Verify.
- ASSERT_FALSE(helper.DirectoryExists(src));
- ASSERT_TRUE(helper.DirectoryExists(dest));
-
- int64 src_new_usage = helper.GetSourceUsage();
- ASSERT_EQ(src_initial_usage, src_new_usage);
-
- int64 dest_increase = helper.GetDestUsage() - dest_initial_usage;
- ASSERT_EQ(src_increase, dest_increase);
-}
-
-TEST(LocalFileSystemCopyOrMoveOperationTest, CopyDirectory) {
- CopyOrMoveOperationTestHelper helper(GURL("http://foo"),
- kFileSystemTypeTemporary,
- kFileSystemTypePersistent);
- helper.SetUp();
-
- FileSystemURL src = helper.SourceURL("a");
- FileSystemURL dest = helper.DestURL("b");
- int64 src_initial_usage = helper.GetSourceUsage();
- int64 dest_initial_usage = helper.GetDestUsage();
-
- // Set up a source directory.
- ASSERT_EQ(base::PLATFORM_FILE_OK, helper.CreateDirectory(src));
- ASSERT_EQ(base::PLATFORM_FILE_OK,
- helper.SetUpTestCaseFiles(src,
- test::kRegularTestCases,
- test::kRegularTestCaseSize));
- int64 src_increase = helper.GetSourceUsage() - src_initial_usage;
-
- // Copy it.
- ASSERT_EQ(base::PLATFORM_FILE_OK,
- helper.CopyWithProgress(
- src, dest,
- AsyncFileTestHelper::CopyProgressCallback()));
-
- // Verify.
- ASSERT_TRUE(helper.DirectoryExists(src));
- ASSERT_TRUE(helper.DirectoryExists(dest));
-
- helper.VerifyTestCaseFiles(dest,
- test::kRegularTestCases,
- test::kRegularTestCaseSize);
-
- int64 src_new_usage = helper.GetSourceUsage();
- ASSERT_EQ(src_initial_usage + src_increase, src_new_usage);
-
- int64 dest_increase = helper.GetDestUsage() - dest_initial_usage;
- ASSERT_EQ(src_increase, dest_increase);
-}
-
-TEST(LocalFileSystemCopyOrMoveOperationTest, MoveDirectory) {
- CopyOrMoveOperationTestHelper helper(GURL("http://foo"),
- kFileSystemTypeTemporary,
- kFileSystemTypePersistent);
- helper.SetUp();
-
- FileSystemURL src = helper.SourceURL("a");
- FileSystemURL dest = helper.DestURL("b");
- int64 src_initial_usage = helper.GetSourceUsage();
- int64 dest_initial_usage = helper.GetDestUsage();
-
- // Set up a source directory.
- ASSERT_EQ(base::PLATFORM_FILE_OK, helper.CreateDirectory(src));
- ASSERT_EQ(base::PLATFORM_FILE_OK,
- helper.SetUpTestCaseFiles(src,
- test::kRegularTestCases,
- test::kRegularTestCaseSize));
- int64 src_increase = helper.GetSourceUsage() - src_initial_usage;
-
- // Move it.
- ASSERT_EQ(base::PLATFORM_FILE_OK, helper.Move(src, dest));
-
- // Verify.
- ASSERT_FALSE(helper.DirectoryExists(src));
- ASSERT_TRUE(helper.DirectoryExists(dest));
-
- helper.VerifyTestCaseFiles(dest,
- test::kRegularTestCases,
- test::kRegularTestCaseSize);
-
- int64 src_new_usage = helper.GetSourceUsage();
- ASSERT_EQ(src_initial_usage, src_new_usage);
-
- int64 dest_increase = helper.GetDestUsage() - dest_initial_usage;
- ASSERT_EQ(src_increase, dest_increase);
-}
-
-TEST(LocalFileSystemCopyOrMoveOperationTest,
- MoveDirectoryFailPostWriteValidation) {
- CopyOrMoveOperationTestHelper helper(GURL("http://foo"),
- kFileSystemTypeTemporary,
- kFileSystemTypeTest);
- helper.SetUp();
-
- FileSystemURL src = helper.SourceURL("a");
- FileSystemURL dest = helper.DestURL("b");
-
- // Set up a source directory.
- ASSERT_EQ(base::PLATFORM_FILE_OK, helper.CreateDirectory(src));
- ASSERT_EQ(base::PLATFORM_FILE_OK,
- helper.SetUpTestCaseFiles(src,
- test::kRegularTestCases,
- test::kRegularTestCaseSize));
-
- // Move it.
- helper.Move(src, dest);
-
- // Verify.
- ASSERT_TRUE(helper.DirectoryExists(src));
- ASSERT_TRUE(helper.DirectoryExists(dest));
-
- test::TestCaseRecord kMoveDirResultCases[] = {
- {false, FILE_PATH_LITERAL("file 0"), 38},
- {false, FILE_PATH_LITERAL("file 3"), 0},
- };
-
- helper.VerifyTestCaseFiles(dest,
- kMoveDirResultCases,
- arraysize(kMoveDirResultCases));
-}
-
-TEST(LocalFileSystemCopyOrMoveOperationTest, CopySingleFileNoValidator) {
- CopyOrMoveOperationTestHelper helper(GURL("http://foo"),
- kFileSystemTypeTemporary,
- kFileSystemTypeTest);
- helper.SetUpNoValidator();
-
- FileSystemURL src = helper.SourceURL("a");
- FileSystemURL dest = helper.DestURL("b");
-
- // Set up a source file.
- ASSERT_EQ(base::PLATFORM_FILE_OK, helper.CreateFile(src, 10));
-
- // The copy attempt should fail with a security error -- getting
- // the factory returns a security error, and the copy operation must
- // respect that.
- ASSERT_EQ(base::PLATFORM_FILE_ERROR_SECURITY, helper.Copy(src, dest));
-}
-
-TEST(LocalFileSystemCopyOrMoveOperationTest, ProgressCallback) {
- CopyOrMoveOperationTestHelper helper(GURL("http://foo"),
- kFileSystemTypeTemporary,
- kFileSystemTypePersistent);
- helper.SetUp();
-
- FileSystemURL src = helper.SourceURL("a");
- FileSystemURL dest = helper.DestURL("b");
-
- // Set up a source directory.
- ASSERT_EQ(base::PLATFORM_FILE_OK, helper.CreateDirectory(src));
- ASSERT_EQ(base::PLATFORM_FILE_OK,
- helper.SetUpTestCaseFiles(src,
- test::kRegularTestCases,
- test::kRegularTestCaseSize));
-
- std::vector<ProgressRecord> records;
- ASSERT_EQ(base::PLATFORM_FILE_OK,
- helper.CopyWithProgress(src, dest,
- base::Bind(&RecordProgressCallback,
- base::Unretained(&records))));
-
- // Verify progress callback.
- for (size_t i = 0; i < test::kRegularTestCaseSize; ++i) {
- const test::TestCaseRecord& test_case = test::kRegularTestCases[i];
-
- FileSystemURL src_url = helper.SourceURL(
- std::string("a/") + base::FilePath(test_case.path).AsUTF8Unsafe());
- FileSystemURL dest_url = helper.DestURL(
- std::string("b/") + base::FilePath(test_case.path).AsUTF8Unsafe());
-
- // Find the first and last progress record.
- size_t begin_index = records.size();
- size_t end_index = records.size();
- for (size_t j = 0; j < records.size(); ++j) {
- if (records[j].source_url == src_url) {
- if (begin_index == records.size())
- begin_index = j;
- end_index = j;
- }
- }
-
- // The record should be found.
- ASSERT_NE(begin_index, records.size());
- ASSERT_NE(end_index, records.size());
- ASSERT_NE(begin_index, end_index);
-
- EXPECT_EQ(FileSystemOperation::BEGIN_COPY_ENTRY,
- records[begin_index].type);
- EXPECT_FALSE(records[begin_index].dest_url.is_valid());
- EXPECT_EQ(FileSystemOperation::END_COPY_ENTRY, records[end_index].type);
- EXPECT_EQ(dest_url, records[end_index].dest_url);
-
- if (test_case.is_directory) {
- // For directory copy, the progress shouldn't be interlaced.
- EXPECT_EQ(begin_index + 1, end_index);
- } else {
- // PROGRESS event's size should be assending order.
- int64 current_size = 0;
- for (size_t j = begin_index + 1; j < end_index; ++j) {
- if (records[j].source_url == src_url) {
- EXPECT_EQ(FileSystemOperation::PROGRESS, records[j].type);
- EXPECT_FALSE(records[j].dest_url.is_valid());
- EXPECT_GE(records[j].size, current_size);
- current_size = records[j].size;
- }
- }
- }
- }
-}
-
-} // namespace fileapi
diff --git a/chromium/webkit/browser/fileapi/dragged_file_util.cc b/chromium/webkit/browser/fileapi/dragged_file_util.cc
index b4536a70f9a..3e81242532f 100644
--- a/chromium/webkit/browser/fileapi/dragged_file_util.cc
+++ b/chromium/webkit/browser/fileapi/dragged_file_util.cc
@@ -81,7 +81,7 @@ PlatformFileError DraggedFileUtil::GetFileInfo(
}
base::PlatformFileError error =
NativeFileUtil::GetFileInfo(url.path(), file_info);
- if (file_util::IsLink(url.path()) && !base::FilePath().IsParent(url.path())) {
+ if (base::IsLink(url.path()) && !base::FilePath().IsParent(url.path())) {
// Don't follow symlinks unless it's the one that are selected by the user.
return base::PLATFORM_FILE_ERROR_NOT_FOUND;
}
diff --git a/chromium/webkit/browser/fileapi/dragged_file_util_unittest.cc b/chromium/webkit/browser/fileapi/dragged_file_util_unittest.cc
deleted file mode 100644
index af15af8f9fd..00000000000
--- a/chromium/webkit/browser/fileapi/dragged_file_util_unittest.cc
+++ /dev/null
@@ -1,545 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <map>
-#include <queue>
-#include <set>
-#include <string>
-#include <vector>
-
-#include "base/file_util.h"
-#include "base/files/file_enumerator.h"
-#include "base/files/scoped_temp_dir.h"
-#include "base/logging.h"
-#include "base/message_loop/message_loop.h"
-#include "base/message_loop/message_loop_proxy.h"
-#include "base/time/time.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "webkit/browser/fileapi/async_file_test_helper.h"
-#include "webkit/browser/fileapi/dragged_file_util.h"
-#include "webkit/browser/fileapi/file_system_context.h"
-#include "webkit/browser/fileapi/file_system_operation_context.h"
-#include "webkit/browser/fileapi/isolated_context.h"
-#include "webkit/browser/fileapi/local_file_util.h"
-#include "webkit/browser/fileapi/mock_file_system_context.h"
-#include "webkit/browser/fileapi/native_file_util.h"
-#include "webkit/browser/fileapi/test_file_set.h"
-
-namespace fileapi {
-
-namespace {
-
-typedef AsyncFileTestHelper::FileEntryList FileEntryList;
-
-// Used in DraggedFileUtilTest::SimulateDropFiles().
-// Random root paths in which we create each file/directory of the
-// RegularTestCases (so that we can simulate a drop with files/directories
-// from multiple directories).
-static const base::FilePath::CharType* kRootPaths[] = {
- FILE_PATH_LITERAL("a"),
- FILE_PATH_LITERAL("b/c"),
- FILE_PATH_LITERAL("etc"),
-};
-
-base::FilePath GetTopLevelPath(const base::FilePath& path) {
- std::vector<base::FilePath::StringType> components;
- path.GetComponents(&components);
- return base::FilePath(components[0]);
-}
-
-bool IsDirectoryEmpty(FileSystemContext* context, const FileSystemURL& url) {
- FileEntryList entries;
- EXPECT_EQ(base::PLATFORM_FILE_OK,
- AsyncFileTestHelper::ReadDirectory(context, url, &entries));
- return entries.empty();
-}
-
-FileSystemURL GetEntryURL(FileSystemContext* file_system_context,
- const FileSystemURL& dir,
- const base::FilePath::StringType& name) {
- return file_system_context->CreateCrackedFileSystemURL(
- dir.origin(),
- dir.mount_type(),
- dir.virtual_path().Append(name));
-}
-
-base::FilePath GetRelativeVirtualPath(const FileSystemURL& root,
- const FileSystemURL& url) {
- if (root.virtual_path().empty())
- return url.virtual_path();
- base::FilePath relative;
- const bool success = root.virtual_path().AppendRelativePath(
- url.virtual_path(), &relative);
- DCHECK(success);
- return relative;
-}
-
-FileSystemURL GetOtherURL(FileSystemContext* file_system_context,
- const FileSystemURL& root,
- const FileSystemURL& other_root,
- const FileSystemURL& url) {
- return file_system_context->CreateCrackedFileSystemURL(
- other_root.origin(),
- other_root.mount_type(),
- other_root.virtual_path().Append(GetRelativeVirtualPath(root, url)));
-}
-
-} // namespace
-
-class DraggedFileUtilTest : public testing::Test {
- public:
- DraggedFileUtilTest() {}
-
- virtual void SetUp() {
- ASSERT_TRUE(data_dir_.CreateUniqueTempDir());
- ASSERT_TRUE(partition_dir_.CreateUniqueTempDir());
- file_util_.reset(new DraggedFileUtil());
-
- // Register the files/directories of RegularTestCases (with random
- // root paths) as dropped files.
- SimulateDropFiles();
-
- file_system_context_ = CreateFileSystemContextForTesting(
- NULL /* quota_manager */,
- partition_dir_.path());
-
- isolated_context()->AddReference(filesystem_id_);
- }
-
- virtual void TearDown() {
- isolated_context()->RemoveReference(filesystem_id_);
- }
-
- protected:
- IsolatedContext* isolated_context() const {
- return IsolatedContext::GetInstance();
- }
- const base::FilePath& root_path() const {
- return data_dir_.path();
- }
- FileSystemContext* file_system_context() const {
- return file_system_context_.get();
- }
- FileSystemFileUtil* file_util() const { return file_util_.get(); }
- std::string filesystem_id() const { return filesystem_id_; }
-
- base::FilePath GetTestCasePlatformPath(
- const base::FilePath::StringType& path) {
- return toplevel_root_map_[GetTopLevelPath(base::FilePath(path))]
- .Append(path).NormalizePathSeparators();
- }
-
- base::FilePath GetTestCaseLocalPath(const base::FilePath& path) {
- base::FilePath relative;
- if (data_dir_.path().AppendRelativePath(path, &relative))
- return relative;
- return path;
- }
-
- FileSystemURL GetFileSystemURL(const base::FilePath& path) const {
- base::FilePath virtual_path = isolated_context()->CreateVirtualRootPath(
- filesystem_id()).Append(path);
- return file_system_context_->CreateCrackedFileSystemURL(
- GURL("http://example.com"),
- kFileSystemTypeIsolated,
- virtual_path);
- }
-
- FileSystemURL GetOtherFileSystemURL(const base::FilePath& path) const {
- return file_system_context()->CreateCrackedFileSystemURL(
- GURL("http://example.com"),
- kFileSystemTypeTemporary,
- base::FilePath().AppendASCII("dest").Append(path));
- }
-
- void VerifyFilesHaveSameContent(const FileSystemURL& url1,
- const FileSystemURL& url2) {
- // Get the file info and the platform path for url1.
- base::PlatformFileInfo info1;
- ASSERT_EQ(base::PLATFORM_FILE_OK,
- AsyncFileTestHelper::GetMetadata(
- file_system_context(), url1, &info1));
- base::FilePath platform_path1;
- ASSERT_EQ(base::PLATFORM_FILE_OK,
- AsyncFileTestHelper::GetPlatformPath(
- file_system_context(), url1, &platform_path1));
-
- // Get the file info and the platform path for url2.
- base::PlatformFileInfo info2;
- ASSERT_EQ(base::PLATFORM_FILE_OK,
- AsyncFileTestHelper::GetMetadata(
- file_system_context(), url2, &info2));
- base::FilePath platform_path2;
- ASSERT_EQ(base::PLATFORM_FILE_OK,
- AsyncFileTestHelper::GetPlatformPath(
- file_system_context(), url2, &platform_path2));
-
- // See if file info matches with the other one.
- EXPECT_EQ(info1.is_directory, info2.is_directory);
- EXPECT_EQ(info1.size, info2.size);
- EXPECT_EQ(info1.is_symbolic_link, info2.is_symbolic_link);
- EXPECT_NE(platform_path1, platform_path2);
-
- std::string content1, content2;
- EXPECT_TRUE(base::ReadFileToString(platform_path1, &content1));
- EXPECT_TRUE(base::ReadFileToString(platform_path2, &content2));
- EXPECT_EQ(content1, content2);
- }
-
- void VerifyDirectoriesHaveSameContent(const FileSystemURL& root1,
- const FileSystemURL& root2) {
- base::FilePath root_path1 = root1.path();
- base::FilePath root_path2 = root2.path();
-
- FileEntryList entries;
- std::queue<FileSystemURL> directories;
-
- directories.push(root1);
- std::set<base::FilePath> file_set1;
- while (!directories.empty()) {
- FileSystemURL dir = directories.front();
- directories.pop();
-
- ASSERT_EQ(base::PLATFORM_FILE_OK,
- AsyncFileTestHelper::ReadDirectory(
- file_system_context(), dir, &entries));
- for (size_t i = 0; i < entries.size(); ++i) {
- FileSystemURL url = GetEntryURL(file_system_context(),
- dir, entries[i].name);
- if (entries[i].is_directory) {
- directories.push(url);
- continue;
- }
- file_set1.insert(GetRelativeVirtualPath(root1, url));
- }
- }
-
- directories.push(root2);
- while (!directories.empty()) {
- FileSystemURL dir = directories.front();
- directories.pop();
-
- ASSERT_EQ(base::PLATFORM_FILE_OK,
- AsyncFileTestHelper::ReadDirectory(
- file_system_context(), dir, &entries));
- for (size_t i = 0; i < entries.size(); ++i) {
- FileSystemURL url2 = GetEntryURL(file_system_context(),
- dir, entries[i].name);
- FileSystemURL url1 = GetOtherURL(file_system_context(),
- root2, root1, url2);
- if (entries[i].is_directory) {
- directories.push(url2);
- EXPECT_EQ(IsDirectoryEmpty(file_system_context(), url1),
- IsDirectoryEmpty(file_system_context(), url2));
- continue;
- }
- base::FilePath relative = GetRelativeVirtualPath(root2, url2);
- EXPECT_TRUE(file_set1.find(relative) != file_set1.end());
- VerifyFilesHaveSameContent(url1, url2);
- }
- }
- }
-
- scoped_ptr<FileSystemOperationContext> GetOperationContext() {
- return make_scoped_ptr(
- new FileSystemOperationContext(file_system_context())).Pass();
- }
-
-
- private:
- void SimulateDropFiles() {
- size_t root_path_index = 0;
-
- IsolatedContext::FileInfoSet toplevels;
- for (size_t i = 0; i < test::kRegularTestCaseSize; ++i) {
- const test::TestCaseRecord& test_case = test::kRegularTestCases[i];
- base::FilePath path(test_case.path);
- base::FilePath toplevel = GetTopLevelPath(path);
-
- // We create the test case files under one of the kRootPaths
- // to simulate a drop with multiple directories.
- if (toplevel_root_map_.find(toplevel) == toplevel_root_map_.end()) {
- base::FilePath root = root_path().Append(
- kRootPaths[(root_path_index++) % arraysize(kRootPaths)]);
- toplevel_root_map_[toplevel] = root;
- toplevels.AddPath(root.Append(path), NULL);
- }
-
- test::SetUpOneTestCase(toplevel_root_map_[toplevel], test_case);
- }
-
- // Register the toplevel entries.
- filesystem_id_ = isolated_context()->RegisterDraggedFileSystem(toplevels);
- }
-
- base::ScopedTempDir data_dir_;
- base::ScopedTempDir partition_dir_;
- base::MessageLoop message_loop_;
- std::string filesystem_id_;
- scoped_refptr<FileSystemContext> file_system_context_;
- std::map<base::FilePath, base::FilePath> toplevel_root_map_;
- scoped_ptr<DraggedFileUtil> file_util_;
- DISALLOW_COPY_AND_ASSIGN(DraggedFileUtilTest);
-};
-
-TEST_F(DraggedFileUtilTest, BasicTest) {
- for (size_t i = 0; i < test::kRegularTestCaseSize; ++i) {
- SCOPED_TRACE(testing::Message() << "Testing RegularTestCases " << i);
- const test::TestCaseRecord& test_case = test::kRegularTestCases[i];
-
- FileSystemURL url = GetFileSystemURL(base::FilePath(test_case.path));
-
- // See if we can query the file info via the isolated FileUtil.
- // (This should succeed since we have registered all the top-level
- // entries of the test cases in SetUp())
- base::PlatformFileInfo info;
- base::FilePath platform_path;
- FileSystemOperationContext context(file_system_context());
- ASSERT_EQ(base::PLATFORM_FILE_OK,
- file_util()->GetFileInfo(&context, url, &info, &platform_path));
-
- // See if the obtained file info is correct.
- if (!test_case.is_directory)
- ASSERT_EQ(test_case.data_file_size, info.size);
- ASSERT_EQ(test_case.is_directory, info.is_directory);
- ASSERT_EQ(GetTestCasePlatformPath(test_case.path),
- platform_path.NormalizePathSeparators());
- }
-}
-
-TEST_F(DraggedFileUtilTest, UnregisteredPathsTest) {
- static const fileapi::test::TestCaseRecord kUnregisteredCases[] = {
- {true, FILE_PATH_LITERAL("nonexistent"), 0},
- {true, FILE_PATH_LITERAL("nonexistent/dir foo"), 0},
- {false, FILE_PATH_LITERAL("nonexistent/false"), 0},
- {false, FILE_PATH_LITERAL("foo"), 30},
- {false, FILE_PATH_LITERAL("bar"), 20},
- };
-
- for (size_t i = 0; i < arraysize(kUnregisteredCases); ++i) {
- SCOPED_TRACE(testing::Message() << "Creating kUnregisteredCases " << i);
- const test::TestCaseRecord& test_case = kUnregisteredCases[i];
-
- // Prepare the test file/directory.
- SetUpOneTestCase(root_path(), test_case);
-
- // Make sure regular GetFileInfo succeeds.
- base::PlatformFileInfo info;
- ASSERT_TRUE(file_util::GetFileInfo(
- root_path().Append(test_case.path), &info));
- if (!test_case.is_directory)
- ASSERT_EQ(test_case.data_file_size, info.size);
- ASSERT_EQ(test_case.is_directory, info.is_directory);
- }
-
- for (size_t i = 0; i < arraysize(kUnregisteredCases); ++i) {
- SCOPED_TRACE(testing::Message() << "Creating kUnregisteredCases " << i);
- const test::TestCaseRecord& test_case = kUnregisteredCases[i];
- FileSystemURL url = GetFileSystemURL(base::FilePath(test_case.path));
-
- // We should not be able to get the valid URL for unregistered files.
- ASSERT_FALSE(url.is_valid());
- }
-}
-
-TEST_F(DraggedFileUtilTest, ReadDirectoryTest) {
- for (size_t i = 0; i < test::kRegularTestCaseSize; ++i) {
- const test::TestCaseRecord& test_case = test::kRegularTestCases[i];
- if (!test_case.is_directory)
- continue;
-
- SCOPED_TRACE(testing::Message() << "Testing RegularTestCases " << i
- << ": " << test_case.path);
-
- // Read entries in the directory to construct the expected results map.
- typedef std::map<base::FilePath::StringType, DirectoryEntry> EntryMap;
- EntryMap expected_entry_map;
-
- base::FilePath dir_path = GetTestCasePlatformPath(test_case.path);
- base::FileEnumerator file_enum(
- dir_path, false /* not recursive */,
- base::FileEnumerator::FILES | base::FileEnumerator::DIRECTORIES);
- base::FilePath current;
- while (!(current = file_enum.Next()).empty()) {
- base::FileEnumerator::FileInfo file_info = file_enum.GetInfo();
- DirectoryEntry entry;
- entry.is_directory = file_info.IsDirectory();
- entry.name = current.BaseName().value();
- entry.size = file_info.GetSize();
- entry.last_modified_time = file_info.GetLastModifiedTime();
- expected_entry_map[entry.name] = entry;
-
-#if defined(OS_POSIX)
- // Creates a symlink for each file/directory.
- // They should be ignored by ReadDirectory, so we don't add them
- // to expected_entry_map.
- file_util::CreateSymbolicLink(
- current,
- dir_path.Append(current.BaseName().AddExtension(
- FILE_PATH_LITERAL("link"))));
-#endif
- }
-
- // Perform ReadDirectory in the isolated filesystem.
- FileSystemURL url = GetFileSystemURL(base::FilePath(test_case.path));
- FileEntryList entries;
- ASSERT_EQ(base::PLATFORM_FILE_OK,
- AsyncFileTestHelper::ReadDirectory(
- file_system_context(), url, &entries));
-
- EXPECT_EQ(expected_entry_map.size(), entries.size());
- for (size_t i = 0; i < entries.size(); ++i) {
- const DirectoryEntry& entry = entries[i];
- EntryMap::iterator found = expected_entry_map.find(entry.name);
- EXPECT_TRUE(found != expected_entry_map.end());
- EXPECT_EQ(found->second.name, entry.name);
- EXPECT_EQ(found->second.is_directory, entry.is_directory);
- EXPECT_EQ(found->second.size, entry.size);
- EXPECT_EQ(found->second.last_modified_time.ToDoubleT(),
- entry.last_modified_time.ToDoubleT());
- }
- }
-}
-
-TEST_F(DraggedFileUtilTest, GetLocalFilePathTest) {
- for (size_t i = 0; i < test::kRegularTestCaseSize; ++i) {
- const test::TestCaseRecord& test_case = test::kRegularTestCases[i];
- FileSystemURL url = GetFileSystemURL(base::FilePath(test_case.path));
-
- FileSystemOperationContext context(file_system_context());
-
- base::FilePath local_file_path;
- EXPECT_EQ(base::PLATFORM_FILE_OK,
- file_util()->GetLocalFilePath(&context, url, &local_file_path));
- EXPECT_EQ(GetTestCasePlatformPath(test_case.path).value(),
- local_file_path.value());
- }
-}
-
-TEST_F(DraggedFileUtilTest, CopyOutFileTest) {
- FileSystemURL src_root = GetFileSystemURL(base::FilePath());
- FileSystemURL dest_root = GetOtherFileSystemURL(base::FilePath());
-
- FileEntryList entries;
- std::queue<FileSystemURL> directories;
- directories.push(src_root);
-
- ASSERT_EQ(base::PLATFORM_FILE_OK,
- AsyncFileTestHelper::CreateDirectory(file_system_context(),
- dest_root));
-
- while (!directories.empty()) {
- FileSystemURL dir = directories.front();
- directories.pop();
- ASSERT_EQ(base::PLATFORM_FILE_OK,
- AsyncFileTestHelper::ReadDirectory(file_system_context(),
- dir, &entries));
- for (size_t i = 0; i < entries.size(); ++i) {
- FileSystemURL src_url = GetEntryURL(file_system_context(),
- dir, entries[i].name);
- FileSystemURL dest_url = GetOtherURL(file_system_context(),
- src_root, dest_root, src_url);
-
- if (entries[i].is_directory) {
- ASSERT_EQ(base::PLATFORM_FILE_OK,
- AsyncFileTestHelper::CreateDirectory(file_system_context(),
- dest_url));
- directories.push(src_url);
- continue;
- }
- SCOPED_TRACE(testing::Message() << "Testing file copy "
- << src_url.path().value());
- ASSERT_EQ(base::PLATFORM_FILE_OK,
- AsyncFileTestHelper::Copy(file_system_context(),
- src_url, dest_url));
- VerifyFilesHaveSameContent(src_url, dest_url);
- }
- }
-}
-
-TEST_F(DraggedFileUtilTest, CopyOutDirectoryTest) {
- FileSystemURL src_root = GetFileSystemURL(base::FilePath());
- FileSystemURL dest_root = GetOtherFileSystemURL(base::FilePath());
-
- ASSERT_EQ(base::PLATFORM_FILE_OK,
- AsyncFileTestHelper::CreateDirectory(file_system_context(),
- dest_root));
-
- FileEntryList entries;
- ASSERT_EQ(base::PLATFORM_FILE_OK,
- AsyncFileTestHelper::ReadDirectory(file_system_context(),
- src_root, &entries));
- for (size_t i = 0; i < entries.size(); ++i) {
- if (!entries[i].is_directory)
- continue;
- FileSystemURL src_url = GetEntryURL(file_system_context(),
- src_root, entries[i].name);
- FileSystemURL dest_url = GetOtherURL(file_system_context(),
- src_root, dest_root, src_url);
- SCOPED_TRACE(testing::Message() << "Testing file copy "
- << src_url.path().value());
- ASSERT_EQ(base::PLATFORM_FILE_OK,
- AsyncFileTestHelper::Copy(file_system_context(),
- src_url, dest_url));
- VerifyDirectoriesHaveSameContent(src_url, dest_url);
- }
-}
-
-TEST_F(DraggedFileUtilTest, TouchTest) {
- for (size_t i = 0; i < test::kRegularTestCaseSize; ++i) {
- const test::TestCaseRecord& test_case = test::kRegularTestCases[i];
- if (test_case.is_directory)
- continue;
- SCOPED_TRACE(testing::Message() << test_case.path);
- FileSystemURL url = GetFileSystemURL(base::FilePath(test_case.path));
-
- base::Time last_access_time = base::Time::FromTimeT(1000);
- base::Time last_modified_time = base::Time::FromTimeT(2000);
-
- EXPECT_EQ(base::PLATFORM_FILE_OK,
- file_util()->Touch(GetOperationContext().get(), url,
- last_access_time,
- last_modified_time));
-
- // Verification.
- base::PlatformFileInfo info;
- base::FilePath platform_path;
- ASSERT_EQ(base::PLATFORM_FILE_OK,
- file_util()->GetFileInfo(GetOperationContext().get(), url,
- &info, &platform_path));
- EXPECT_EQ(last_access_time.ToTimeT(), info.last_accessed.ToTimeT());
- EXPECT_EQ(last_modified_time.ToTimeT(), info.last_modified.ToTimeT());
- }
-}
-
-TEST_F(DraggedFileUtilTest, TruncateTest) {
- for (size_t i = 0; i < test::kRegularTestCaseSize; ++i) {
- const test::TestCaseRecord& test_case = test::kRegularTestCases[i];
- if (test_case.is_directory)
- continue;
-
- SCOPED_TRACE(testing::Message() << test_case.path);
- FileSystemURL url = GetFileSystemURL(base::FilePath(test_case.path));
-
- // Truncate to 0.
- base::PlatformFileInfo info;
- base::FilePath platform_path;
- EXPECT_EQ(base::PLATFORM_FILE_OK,
- file_util()->Truncate(GetOperationContext().get(), url, 0));
- ASSERT_EQ(base::PLATFORM_FILE_OK,
- file_util()->GetFileInfo(GetOperationContext().get(), url,
- &info, &platform_path));
- EXPECT_EQ(0, info.size);
-
- // Truncate (extend) to 999.
- EXPECT_EQ(base::PLATFORM_FILE_OK,
- file_util()->Truncate(GetOperationContext().get(), url, 999));
- ASSERT_EQ(base::PLATFORM_FILE_OK,
- file_util()->GetFileInfo(GetOperationContext().get(), url,
- &info, &platform_path));
- EXPECT_EQ(999, info.size);
- }
-}
-
-} // namespace fileapi
diff --git a/chromium/webkit/browser/fileapi/dump_file_system.cc b/chromium/webkit/browser/fileapi/dump_file_system.cc
index 4dd60f26b36..a1ffa4a19c6 100644
--- a/chromium/webkit/browser/fileapi/dump_file_system.cc
+++ b/chromium/webkit/browser/fileapi/dump_file_system.cc
@@ -48,7 +48,7 @@
namespace {
bool g_opt_long;
-fileapi::FileSystemType g_opt_fs_type = fileapi::kFileSystemTypePersistent;
+const char* g_opt_fs_type = "p";
void ShowMessageAndExit(const std::string& msg) {
fprintf(stderr, "%s\n", msg.c_str());
@@ -67,8 +67,7 @@ namespace fileapi {
static void DumpDirectoryTree(const std::string& origin_name,
base::FilePath origin_dir) {
- origin_dir = origin_dir.Append(
- ObfuscatedFileUtil::GetDirectoryNameForType(g_opt_fs_type));
+ origin_dir = origin_dir.Append(g_opt_fs_type);
printf("=== ORIGIN %s %s ===\n",
origin_name.c_str(), FilePathToString(origin_dir).c_str());
@@ -117,7 +116,7 @@ static void DumpDirectoryTree(const std::string& origin_name,
if (info.is_directory()) {
size = static_cast<int64>(children.size());
} else {
- file_util::GetFileSize(origin_dir.Append(info.data_path), &size);
+ base::GetFileSize(origin_dir.Append(info.data_path), &size);
}
// TODO(hamaji): Modification time?
printf("%s%s %"PRId64" %"PRId64" %s\n",
@@ -173,11 +172,11 @@ int main(int argc, char* argv[]) {
argc--;
argv++;
} else if (std::string(argv[1]) == "-t") {
- g_opt_fs_type = fileapi::kFileSystemTypeTemporary;
+ g_opt_fs_type = "t";
argc--;
argv++;
} else if (std::string(argv[1]) == "-s") {
- g_opt_fs_type = fileapi::kFileSystemTypeSyncable;
+ g_opt_fs_type = "s";
argc--;
argv++;
} else {
diff --git a/chromium/webkit/browser/fileapi/external_mount_points.cc b/chromium/webkit/browser/fileapi/external_mount_points.cc
index a3ecd4b6678..42b6de7754c 100644
--- a/chromium/webkit/browser/fileapi/external_mount_points.cc
+++ b/chromium/webkit/browser/fileapi/external_mount_points.cc
@@ -57,16 +57,22 @@ namespace fileapi {
class ExternalMountPoints::Instance {
public:
- Instance(FileSystemType type, const base::FilePath& path)
- : type_(type), path_(path.StripTrailingSeparators()) {}
+ Instance(FileSystemType type,
+ const base::FilePath& path,
+ const FileSystemMountOption& mount_option)
+ : type_(type),
+ path_(path.StripTrailingSeparators()),
+ mount_option_(mount_option) {}
~Instance() {}
FileSystemType type() const { return type_; }
const base::FilePath& path() const { return path_; }
+ const FileSystemMountOption& mount_option() const { return mount_option_; }
private:
const FileSystemType type_;
const base::FilePath path_;
+ const FileSystemMountOption mount_option_;
DISALLOW_COPY_AND_ASSIGN(Instance);
};
@@ -86,14 +92,19 @@ scoped_refptr<ExternalMountPoints> ExternalMountPoints::CreateRefCounted() {
bool ExternalMountPoints::RegisterFileSystem(
const std::string& mount_name,
FileSystemType type,
+ const FileSystemMountOption& mount_option,
const base::FilePath& path_in) {
+ // COPY_SYNC_OPTION_SYNC is only applicable to native local file system.
+ DCHECK(type == kFileSystemTypeNativeLocal ||
+ mount_option.copy_sync_option() != COPY_SYNC_OPTION_SYNC);
+
base::AutoLock locker(lock_);
base::FilePath path = NormalizeFilePath(path_in);
if (!ValidateNewMountPoint(mount_name, path))
return false;
- instance_map_[mount_name] = new Instance(type, path);
+ instance_map_[mount_name] = new Instance(type, path, mount_option);
if (!path.empty())
path_to_name_map_.insert(std::make_pair(path, mount_name));
return true;
@@ -128,10 +139,12 @@ bool ExternalMountPoints::GetRegisteredPath(
return true;
}
-bool ExternalMountPoints::CrackVirtualPath(const base::FilePath& virtual_path,
- std::string* mount_name,
- FileSystemType* type,
- base::FilePath* path) const {
+bool ExternalMountPoints::CrackVirtualPath(
+ const base::FilePath& virtual_path,
+ std::string* mount_name,
+ FileSystemType* type,
+ base::FilePath* path,
+ FileSystemMountOption* mount_option) const {
DCHECK(mount_name);
DCHECK(path);
@@ -165,6 +178,7 @@ bool ExternalMountPoints::CrackVirtualPath(const base::FilePath& virtual_path,
if (type)
*type = instance->type();
cracked_path = instance->path();
+ *mount_option = instance->mount_option();
}
for (; component_iter != components.end(); ++component_iter)
@@ -233,6 +247,18 @@ FileSystemURL ExternalMountPoints::CreateExternalFileSystemURL(
base::FilePath::kSeparators[0] + path.value()));
}
+void ExternalMountPoints::RevokeAllFileSystems() {
+ NameToInstance instance_map_copy;
+ {
+ base::AutoLock locker(lock_);
+ instance_map_copy = instance_map_;
+ instance_map_.clear();
+ path_to_name_map_.clear();
+ }
+ STLDeleteContainerPairSecondPointers(instance_map_copy.begin(),
+ instance_map_copy.end());
+}
+
ExternalMountPoints::ExternalMountPoints() {}
ExternalMountPoints::~ExternalMountPoints() {
@@ -256,23 +282,24 @@ FileSystemURL ExternalMountPoints::CrackFileSystemURL(
return FileSystemURL(
url.origin(), url.mount_type(), url.virtual_path(),
url.mount_filesystem_id(), kFileSystemTypeNativeLocal,
- url.path(), url.filesystem_id());
+ url.path(), url.filesystem_id(), url.mount_option());
#endif
}
std::string mount_name;
FileSystemType cracked_type;
base::FilePath cracked_path;
+ FileSystemMountOption cracked_mount_option;
if (!CrackVirtualPath(virtual_path, &mount_name, &cracked_type,
- &cracked_path)) {
+ &cracked_path, &cracked_mount_option)) {
return FileSystemURL();
}
return FileSystemURL(
url.origin(), url.mount_type(), url.virtual_path(),
!url.filesystem_id().empty() ? url.filesystem_id() : mount_name,
- cracked_type, cracked_path, mount_name);
+ cracked_type, cracked_path, mount_name, cracked_mount_option);
}
bool ExternalMountPoints::ValidateNewMountPoint(const std::string& mount_name,
@@ -314,22 +341,4 @@ bool ExternalMountPoints::ValidateNewMountPoint(const std::string& mount_name,
!path.IsParent(potential_child->first);
}
-ScopedExternalFileSystem::ScopedExternalFileSystem(
- const std::string& mount_name,
- FileSystemType type,
- const base::FilePath& path)
- : mount_name_(mount_name) {
- ExternalMountPoints::GetSystemInstance()->RegisterFileSystem(
- mount_name, type, path);
-}
-
-base::FilePath ScopedExternalFileSystem::GetVirtualRootPath() const {
- return ExternalMountPoints::GetSystemInstance()->
- CreateVirtualRootPath(mount_name_);
-}
-
-ScopedExternalFileSystem::~ScopedExternalFileSystem() {
- ExternalMountPoints::GetSystemInstance()->RevokeFileSystem(mount_name_);
-}
-
} // namespace fileapi
diff --git a/chromium/webkit/browser/fileapi/external_mount_points.h b/chromium/webkit/browser/fileapi/external_mount_points.h
index 9118443b7b6..9fb3cc36cc3 100644
--- a/chromium/webkit/browser/fileapi/external_mount_points.h
+++ b/chromium/webkit/browser/fileapi/external_mount_points.h
@@ -13,6 +13,7 @@
#include "base/synchronization/lock.h"
#include "webkit/browser/fileapi/mount_points.h"
#include "webkit/browser/webkit_storage_browser_export.h"
+#include "webkit/common/fileapi/file_system_mount_option.h"
#include "webkit/common/fileapi/file_system_types.h"
namespace base {
@@ -61,6 +62,7 @@ class WEBKIT_STORAGE_BROWSER_EXPORT ExternalMountPoints
// by calling RevokeFileSystem with |mount_name|.
bool RegisterFileSystem(const std::string& mount_name,
FileSystemType type,
+ const FileSystemMountOption& mount_option,
const base::FilePath& path);
// MountPoints overrides.
@@ -68,10 +70,12 @@ class WEBKIT_STORAGE_BROWSER_EXPORT ExternalMountPoints
virtual bool RevokeFileSystem(const std::string& mount_name) OVERRIDE;
virtual bool GetRegisteredPath(const std::string& mount_name,
base::FilePath* path) const OVERRIDE;
- virtual bool CrackVirtualPath(const base::FilePath& virtual_path,
- std::string* mount_name,
- FileSystemType* type,
- base::FilePath* path) const OVERRIDE;
+ virtual bool CrackVirtualPath(
+ const base::FilePath& virtual_path,
+ std::string* mount_name,
+ FileSystemType* type,
+ base::FilePath* path,
+ FileSystemMountOption* mount_option) const OVERRIDE;
virtual FileSystemURL CrackURL(const GURL& url) const OVERRIDE;
virtual FileSystemURL CreateCrackedFileSystemURL(
const GURL& origin,
@@ -101,6 +105,9 @@ class WEBKIT_STORAGE_BROWSER_EXPORT ExternalMountPoints
const std::string& mount_name,
const base::FilePath& path) const;
+ // Revoke all registered filesystems. Used only by testing (for clean-ups).
+ void RevokeAllFileSystems();
+
private:
friend class base::RefCountedThreadSafe<ExternalMountPoints>;
@@ -140,20 +147,6 @@ class WEBKIT_STORAGE_BROWSER_EXPORT ExternalMountPoints
DISALLOW_COPY_AND_ASSIGN(ExternalMountPoints);
};
-// Registers a scoped external filesystem which gets revoked when it scopes out.
-class WEBKIT_STORAGE_BROWSER_EXPORT ScopedExternalFileSystem {
- public:
- ScopedExternalFileSystem(const std::string& mount_name,
- FileSystemType type,
- const base::FilePath& path);
- ~ScopedExternalFileSystem();
-
- base::FilePath GetVirtualRootPath() const;
-
- private:
- const std::string mount_name_;
-};
-
} // namespace fileapi
#endif // WEBKIT_BROWSER_FILEAPI_EXTERNAL_MOUNT_POINTS_H_
diff --git a/chromium/webkit/browser/fileapi/external_mount_points_unittest.cc b/chromium/webkit/browser/fileapi/external_mount_points_unittest.cc
index cc2acbe2a16..fa5d8d1de46 100644
--- a/chromium/webkit/browser/fileapi/external_mount_points_unittest.cc
+++ b/chromium/webkit/browser/fileapi/external_mount_points_unittest.cc
@@ -111,6 +111,7 @@ TEST(ExternalMountPointsTest, AddMountPoint) {
mount_points->RegisterFileSystem(
kTestCases[i].name,
fileapi::kFileSystemTypeNativeLocal,
+ fileapi::FileSystemMountOption(),
base::FilePath(kTestCases[i].path)))
<< "Adding mount point: " << kTestCases[i].name << " with path "
<< kTestCases[i].path;
@@ -136,24 +137,30 @@ TEST(ExternalMountPointsTest, GetVirtualPath) {
mount_points->RegisterFileSystem("c",
fileapi::kFileSystemTypeNativeLocal,
+ fileapi::FileSystemMountOption(),
base::FilePath(DRIVE FPL("/a/b/c")));
// Note that "/a/b/c" < "/a/b/c(1)" < "/a/b/c/".
mount_points->RegisterFileSystem("c(1)",
fileapi::kFileSystemTypeNativeLocal,
+ fileapi::FileSystemMountOption(),
base::FilePath(DRIVE FPL("/a/b/c(1)")));
mount_points->RegisterFileSystem("x",
fileapi::kFileSystemTypeNativeLocal,
+ fileapi::FileSystemMountOption(),
base::FilePath(DRIVE FPL("/z/y/x")));
mount_points->RegisterFileSystem("o",
fileapi::kFileSystemTypeNativeLocal,
+ fileapi::FileSystemMountOption(),
base::FilePath(DRIVE FPL("/m/n/o")));
// A mount point whose name does not match its path base name.
mount_points->RegisterFileSystem("mount",
fileapi::kFileSystemTypeNativeLocal,
+ fileapi::FileSystemMountOption(),
base::FilePath(DRIVE FPL("/root/foo")));
// A mount point with an empty path.
mount_points->RegisterFileSystem("empty_path",
fileapi::kFileSystemTypeNativeLocal,
+ fileapi::FileSystemMountOption(),
base::FilePath());
struct TestCase {
@@ -265,15 +272,19 @@ TEST(ExternalMountPointsTest, CreateCrackedFileSystemURL) {
mount_points->RegisterFileSystem("c",
fileapi::kFileSystemTypeNativeLocal,
+ fileapi::FileSystemMountOption(),
base::FilePath(DRIVE FPL("/a/b/c")));
mount_points->RegisterFileSystem("c(1)",
fileapi::kFileSystemTypeDrive,
+ fileapi::FileSystemMountOption(),
base::FilePath(DRIVE FPL("/a/b/c(1)")));
mount_points->RegisterFileSystem("empty_path",
fileapi::kFileSystemTypeSyncable,
+ fileapi::FileSystemMountOption(),
base::FilePath());
mount_points->RegisterFileSystem("mount",
fileapi::kFileSystemTypeDrive,
+ fileapi::FileSystemMountOption(),
base::FilePath(DRIVE FPL("/root")));
// Try cracking invalid GURL.
@@ -287,7 +298,9 @@ TEST(ExternalMountPointsTest, CreateCrackedFileSystemURL) {
// Try native local which is not cracked.
FileSystemURL native_local = mount_points->CreateCrackedFileSystemURL(
- kTestOrigin, fileapi::kFileSystemTypeNativeLocal, base::FilePath(FPL("c")));
+ kTestOrigin,
+ fileapi::kFileSystemTypeNativeLocal,
+ base::FilePath(FPL("c")));
EXPECT_FALSE(native_local.is_valid());
struct TestCase {
@@ -355,8 +368,8 @@ TEST(ExternalMountPointsTest, CreateCrackedFileSystemURL) {
<< "Test case index: " << i;
EXPECT_EQ(kTestCases[i].expect_type, cracked.type())
<< "Test case index: " << i;
- EXPECT_EQ(base::FilePath(kTestCases[i].expect_path).NormalizePathSeparators(),
- cracked.path())
+ EXPECT_EQ(base::FilePath(
+ kTestCases[i].expect_path).NormalizePathSeparators(), cracked.path())
<< "Test case index: " << i;
EXPECT_EQ(base::FilePath(kTestCases[i].path).NormalizePathSeparators(),
cracked.virtual_path())
@@ -376,15 +389,19 @@ TEST(ExternalMountPointsTest, CrackVirtualPath) {
mount_points->RegisterFileSystem("c",
fileapi::kFileSystemTypeNativeLocal,
+ fileapi::FileSystemMountOption(),
base::FilePath(DRIVE FPL("/a/b/c")));
mount_points->RegisterFileSystem("c(1)",
fileapi::kFileSystemTypeDrive,
+ fileapi::FileSystemMountOption(),
base::FilePath(DRIVE FPL("/a/b/c(1)")));
mount_points->RegisterFileSystem("empty_path",
fileapi::kFileSystemTypeSyncable,
+ fileapi::FileSystemMountOption(),
base::FilePath());
mount_points->RegisterFileSystem("mount",
fileapi::kFileSystemTypeDrive,
+ fileapi::FileSystemMountOption(),
base::FilePath(DRIVE FPL("/root")));
struct TestCase {
@@ -440,9 +457,10 @@ TEST(ExternalMountPointsTest, CrackVirtualPath) {
std::string cracked_name;
fileapi::FileSystemType cracked_type;
base::FilePath cracked_path;
+ fileapi::FileSystemMountOption cracked_option;
EXPECT_EQ(kTestCases[i].expect_valid,
mount_points->CrackVirtualPath(base::FilePath(kTestCases[i].path),
- &cracked_name, &cracked_type, &cracked_path))
+ &cracked_name, &cracked_type, &cracked_path, &cracked_option))
<< "Test case index: " << i;
if (!kTestCases[i].expect_valid)
@@ -450,13 +468,40 @@ TEST(ExternalMountPointsTest, CrackVirtualPath) {
EXPECT_EQ(kTestCases[i].expect_type, cracked_type)
<< "Test case index: " << i;
- EXPECT_EQ(base::FilePath(kTestCases[i].expect_path).NormalizePathSeparators(),
- cracked_path)
+ EXPECT_EQ(base::FilePath(
+ kTestCases[i].expect_path).NormalizePathSeparators(), cracked_path)
<< "Test case index: " << i;
EXPECT_EQ(kTestCases[i].expect_name, cracked_name)
<< "Test case index: " << i;
}
}
+TEST(ExternalMountPointsTest, MountOption) {
+ scoped_refptr<fileapi::ExternalMountPoints> mount_points(
+ fileapi::ExternalMountPoints::CreateRefCounted());
+
+ mount_points->RegisterFileSystem(
+ "nosync",
+ fileapi::kFileSystemTypeNativeLocal,
+ fileapi::FileSystemMountOption(fileapi::COPY_SYNC_OPTION_NO_SYNC),
+ base::FilePath(DRIVE FPL("/nosync")));
+ mount_points->RegisterFileSystem(
+ "sync",
+ fileapi::kFileSystemTypeNativeLocal,
+ fileapi::FileSystemMountOption(fileapi::COPY_SYNC_OPTION_SYNC),
+ base::FilePath(DRIVE FPL("/sync")));
+
+ std::string name;
+ fileapi::FileSystemType type;
+ fileapi::FileSystemMountOption option;
+ base::FilePath path;
+ EXPECT_TRUE(mount_points->CrackVirtualPath(
+ base::FilePath(FPL("nosync/file")), &name, &type, &path, &option));
+ EXPECT_EQ(fileapi::COPY_SYNC_OPTION_NO_SYNC, option.copy_sync_option());
+ EXPECT_TRUE(mount_points->CrackVirtualPath(
+ base::FilePath(FPL("sync/file")), &name, &type, &path, &option));
+ EXPECT_EQ(fileapi::COPY_SYNC_OPTION_SYNC, option.copy_sync_option());
+}
+
} // namespace
diff --git a/chromium/webkit/browser/fileapi/file_permission_policy.cc b/chromium/webkit/browser/fileapi/file_permission_policy.cc
deleted file mode 100644
index 6f1a36c3440..00000000000
--- a/chromium/webkit/browser/fileapi/file_permission_policy.cc
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "webkit/browser/fileapi/file_permission_policy.h"
-
-#include "base/platform_file.h"
-
-namespace fileapi {
-
-const int kReadFilePermissions = base::PLATFORM_FILE_OPEN |
- base::PLATFORM_FILE_READ |
- base::PLATFORM_FILE_EXCLUSIVE_READ |
- base::PLATFORM_FILE_ASYNC;
-
-const int kWriteFilePermissions = base::PLATFORM_FILE_OPEN |
- base::PLATFORM_FILE_WRITE |
- base::PLATFORM_FILE_EXCLUSIVE_WRITE |
- base::PLATFORM_FILE_ASYNC |
- base::PLATFORM_FILE_WRITE_ATTRIBUTES;
-
-const int kCreateFilePermissions = base::PLATFORM_FILE_CREATE;
-
-const int kOpenPepperFilePermissions = base::PLATFORM_FILE_OPEN |
- base::PLATFORM_FILE_CREATE |
- base::PLATFORM_FILE_OPEN_ALWAYS |
- base::PLATFORM_FILE_CREATE_ALWAYS |
- base::PLATFORM_FILE_OPEN_TRUNCATED |
- base::PLATFORM_FILE_READ |
- base::PLATFORM_FILE_WRITE |
- base::PLATFORM_FILE_APPEND |
- base::PLATFORM_FILE_EXCLUSIVE_WRITE |
- base::PLATFORM_FILE_DELETE_ON_CLOSE |
- base::PLATFORM_FILE_WRITE_ATTRIBUTES;
-
-
-} // namespace fileapi
diff --git a/chromium/webkit/browser/fileapi/file_permission_policy.h b/chromium/webkit/browser/fileapi/file_permission_policy.h
index 5c9ced54e8a..f1b6376183e 100644
--- a/chromium/webkit/browser/fileapi/file_permission_policy.h
+++ b/chromium/webkit/browser/fileapi/file_permission_policy.h
@@ -9,11 +9,6 @@
namespace fileapi {
-WEBKIT_STORAGE_BROWSER_EXPORT extern const int kReadFilePermissions;
-WEBKIT_STORAGE_BROWSER_EXPORT extern const int kWriteFilePermissions;
-WEBKIT_STORAGE_BROWSER_EXPORT extern const int kCreateFilePermissions;
-WEBKIT_STORAGE_BROWSER_EXPORT extern const int kOpenPepperFilePermissions;
-
enum FilePermissionPolicy {
// Any access should be always denied.
FILE_PERMISSION_ALWAYS_DENY = 0x0,
diff --git a/chromium/webkit/browser/fileapi/file_system_backend.h b/chromium/webkit/browser/fileapi/file_system_backend.h
index 2c8be930b3e..048c86d2a3b 100644
--- a/chromium/webkit/browser/fileapi/file_system_backend.h
+++ b/chromium/webkit/browser/fileapi/file_system_backend.h
@@ -98,10 +98,10 @@ class WEBKIT_STORAGE_BROWSER_EXPORT FileSystemBackend {
// This method itself does *not* check if the given path exists and is a
// regular file.
virtual scoped_ptr<webkit_blob::FileStreamReader> CreateFileStreamReader(
- const FileSystemURL& url,
- int64 offset,
- const base::Time& expected_modification_time,
- FileSystemContext* context) const = 0;
+ const FileSystemURL& url,
+ int64 offset,
+ const base::Time& expected_modification_time,
+ FileSystemContext* context) const = 0;
// Creates a new file stream writer for a given filesystem URL |url| with an
// offset |offset|.
diff --git a/chromium/webkit/browser/fileapi/file_system_context.cc b/chromium/webkit/browser/fileapi/file_system_context.cc
index 9098649f245..869410498c9 100644
--- a/chromium/webkit/browser/fileapi/file_system_context.cc
+++ b/chromium/webkit/browser/fileapi/file_system_context.cc
@@ -23,8 +23,8 @@
#include "webkit/browser/fileapi/isolated_context.h"
#include "webkit/browser/fileapi/isolated_file_system_backend.h"
#include "webkit/browser/fileapi/mount_points.h"
+#include "webkit/browser/fileapi/quota/quota_reservation.h"
#include "webkit/browser/fileapi/sandbox_file_system_backend.h"
-#include "webkit/browser/fileapi/test_file_system_backend.h"
#include "webkit/browser/quota/quota_manager.h"
#include "webkit/browser/quota/special_storage_policy.h"
#include "webkit/common/fileapi/file_system_info.h"
@@ -42,13 +42,6 @@ QuotaClient* CreateQuotaClient(
return new FileSystemQuotaClient(context, is_incognito);
}
-void DidOpenFileSystem(
- const FileSystemContext::OpenFileSystemCallback& callback,
- const GURL& filesystem_root,
- const std::string& filesystem_name,
- base::PlatformFileError error) {
- callback.Run(error, filesystem_name, filesystem_root);
-}
void DidGetMetadataForResolveURL(
const base::FilePath& path,
@@ -87,9 +80,11 @@ int FileSystemContext::GetPermissionPolicy(FileSystemType type) {
case kFileSystemTypeDeviceMedia:
case kFileSystemTypeDragged:
case kFileSystemTypeForTransientFile:
+ case kFileSystemTypeIphoto:
case kFileSystemTypeItunes:
case kFileSystemTypeNativeMedia:
case kFileSystemTypePicasa:
+ case kFileSystemTypePluginPrivate:
return FILE_PERMISSION_ALWAYS_DENY;
// Following types only appear as mount_type, and will not be
@@ -131,6 +126,11 @@ FileSystemContext::FileSystemContext(
sandbox_backend_(new SandboxFileSystemBackend(
sandbox_delegate_.get())),
isolated_backend_(new IsolatedFileSystemBackend()),
+ plugin_private_backend_(new PluginPrivateFileSystemBackend(
+ file_task_runner,
+ partition_path,
+ special_storage_policy,
+ options)),
additional_backends_(additional_backends.Pass()),
external_mount_points_(external_mount_points),
partition_path_(partition_path),
@@ -138,6 +138,7 @@ FileSystemContext::FileSystemContext(
operation_runner_(new FileSystemOperationRunner(this)) {
RegisterBackend(sandbox_backend_.get());
RegisterBackend(isolated_backend_.get());
+ RegisterBackend(plugin_private_backend_.get());
for (ScopedVector<FileSystemBackend>::const_iterator iter =
additional_backends_.begin();
@@ -153,6 +154,7 @@ FileSystemContext::FileSystemContext(
sandbox_backend_->Initialize(this);
isolated_backend_->Initialize(this);
+ plugin_private_backend_->Initialize(this);
for (ScopedVector<FileSystemBackend>::const_iterator iter =
additional_backends_.begin();
iter != additional_backends_.end(); ++iter) {
@@ -190,6 +192,18 @@ bool FileSystemContext::DeleteDataForOriginOnFileThread(
return success;
}
+scoped_refptr<QuotaReservation>
+FileSystemContext::CreateQuotaReservationOnFileTaskRunner(
+ const GURL& origin_url,
+ FileSystemType type) {
+ DCHECK(default_file_task_runner()->RunsTasksOnCurrentThread());
+ FileSystemBackend* backend = GetFileSystemBackend(type);
+ if (!backend || !backend->GetQuotaUtil())
+ return scoped_refptr<QuotaReservation>();
+ return backend->GetQuotaUtil()->CreateQuotaReservationOnFileTaskRunner(
+ origin_url, type);
+}
+
void FileSystemContext::Shutdown() {
if (!io_task_runner_->RunsTasksOnCurrentThread()) {
io_task_runner_->PostTask(
@@ -277,16 +291,22 @@ void FileSystemContext::OpenFileSystem(
FileSystemType type,
OpenFileSystemMode mode,
const OpenFileSystemCallback& callback) {
+ DCHECK(io_task_runner_->RunsTasksOnCurrentThread());
DCHECK(!callback.is_null());
+ if (!FileSystemContext::IsSandboxFileSystem(type)) {
+ // Disallow opening a non-sandboxed filesystem.
+ callback.Run(GURL(), std::string(), base::PLATFORM_FILE_ERROR_SECURITY);
+ return;
+ }
+
FileSystemBackend* backend = GetFileSystemBackend(type);
if (!backend) {
- callback.Run(base::PLATFORM_FILE_ERROR_SECURITY, std::string(), GURL());
+ callback.Run(GURL(), std::string(), base::PLATFORM_FILE_ERROR_SECURITY);
return;
}
- backend->OpenFileSystem(origin_url, type, mode,
- base::Bind(&DidOpenFileSystem, callback));
+ backend->OpenFileSystem(origin_url, type, mode, callback);
}
void FileSystemContext::ResolveURL(
@@ -295,6 +315,22 @@ void FileSystemContext::ResolveURL(
DCHECK(io_task_runner_->RunsTasksOnCurrentThread());
DCHECK(!callback.is_null());
+ if (!FileSystemContext::IsSandboxFileSystem(url.type())) {
+#ifdef OS_CHROMEOS
+ // Do not have to open a non-sandboxed filesystem.
+ // TODO(nhiroki): For now we assume this path is called only on ChromeOS,
+ // but this assumption may be broken in the future and we should handle
+ // more generally. http://crbug.com/304062.
+ FileSystemInfo info = GetFileSystemInfoForChromeOS(url.origin());
+ DidOpenFileSystemForResolveURL(
+ url, callback, info.root_url, info.name, base::PLATFORM_FILE_OK);
+ return;
+#endif
+ callback.Run(base::PLATFORM_FILE_ERROR_SECURITY,
+ FileSystemInfo(), base::FilePath(), false);
+ return;
+ }
+
FileSystemBackend* backend = GetFileSystemBackend(url.type());
if (!backend) {
callback.Run(base::PLATFORM_FILE_ERROR_SECURITY,
@@ -312,8 +348,11 @@ void FileSystemContext::ResolveURL(
void FileSystemContext::DeleteFileSystem(
const GURL& origin_url,
FileSystemType type,
- const DeleteFileSystemCallback& callback) {
+ const StatusCallback& callback) {
+ DCHECK(io_task_runner_->RunsTasksOnCurrentThread());
DCHECK(origin_url == origin_url.GetOrigin());
+ DCHECK(!callback.is_null());
+
FileSystemBackend* backend = GetFileSystemBackend(type);
if (!backend) {
callback.Run(base::PLATFORM_FILE_ERROR_SECURITY);
@@ -378,14 +417,17 @@ FileSystemURL FileSystemContext::CreateCrackedFileSystemURL(
return CrackFileSystemURL(FileSystemURL(origin, type, path));
}
-#if defined(OS_CHROMEOS) && defined(GOOGLE_CHROME_BUILD)
+#if defined(OS_CHROMEOS)
void FileSystemContext::EnableTemporaryFileSystemInIncognito() {
sandbox_backend_->set_enable_temporary_file_system_in_incognito(true);
}
#endif
bool FileSystemContext::CanServeURLRequest(const FileSystemURL& url) const {
-#if defined(OS_CHROMEOS) && defined(GOOGLE_CHROME_BUILD)
+ // We never support accessing files in isolated filesystems via an URL.
+ if (url.mount_type() == kFileSystemTypeIsolated)
+ return false;
+#if defined(OS_CHROMEOS)
if (url.type() == kFileSystemTypeTemporary &&
sandbox_backend_->enable_temporary_file_system_in_incognito()) {
return true;
@@ -394,6 +436,18 @@ bool FileSystemContext::CanServeURLRequest(const FileSystemURL& url) const {
return !is_incognito_ || !FileSystemContext::IsSandboxFileSystem(url.type());
}
+void FileSystemContext::OpenPluginPrivateFileSystem(
+ const GURL& origin_url,
+ FileSystemType type,
+ const std::string& filesystem_id,
+ const std::string& plugin_id,
+ OpenFileSystemMode mode,
+ const StatusCallback& callback) {
+ DCHECK(plugin_private_backend_);
+ plugin_private_backend_->OpenPrivateFileSystem(
+ origin_url, type, filesystem_id, plugin_id, mode, callback);
+}
+
FileSystemContext::~FileSystemContext() {
}
@@ -500,12 +554,13 @@ void FileSystemContext::DidOpenFileSystemForResolveURL(
filesystem_name, filesystem_root, url.mount_type());
// Extract the virtual path not containing a filesystem type part from |url|.
- base::FilePath parent =
- base::FilePath::FromUTF8Unsafe(filesystem_root.path());
- base::FilePath child = base::FilePath::FromUTF8Unsafe(url.ToGURL().path());
+ base::FilePath parent = CrackURL(filesystem_root).virtual_path();
+ base::FilePath child = url.virtual_path();
base::FilePath path;
- if (parent != child) {
+ if (parent.empty()) {
+ path = child;
+ } else if (parent != child) {
bool result = parent.AppendRelativePath(child, &path);
DCHECK(result);
}
diff --git a/chromium/webkit/browser/fileapi/file_system_context.h b/chromium/webkit/browser/fileapi/file_system_context.h
index 21a31b89eb8..2ceb96fb1aa 100644
--- a/chromium/webkit/browser/fileapi/file_system_context.h
+++ b/chromium/webkit/browser/fileapi/file_system_context.h
@@ -17,6 +17,7 @@
#include "base/sequenced_task_runner_helpers.h"
#include "webkit/browser/fileapi/file_system_url.h"
#include "webkit/browser/fileapi/open_file_system_mode.h"
+#include "webkit/browser/fileapi/plugin_private_file_system_backend.h"
#include "webkit/browser/fileapi/sandbox_file_system_backend_delegate.h"
#include "webkit/browser/fileapi/task_runner_bound_observer_list.h"
#include "webkit/browser/webkit_storage_browser_export.h"
@@ -58,6 +59,7 @@ class FileSystemQuotaUtil;
class FileSystemURL;
class IsolatedFileSystemBackend;
class MountPoints;
+class QuotaReservation;
class SandboxFileSystemBackend;
struct DefaultContextDeleter;
@@ -103,8 +105,18 @@ class WEBKIT_STORAGE_BROWSER_EXPORT FileSystemContext
const base::FilePath& partition_path,
const FileSystemOptions& options);
+ // TODO(nhiroki): Rename *OnFileThread methods since these are no longer on
+ // FILE thread.
bool DeleteDataForOriginOnFileThread(const GURL& origin_url);
+ // Creates a new QuotaReservation for the given |origin_url| and |type|.
+ // Returns NULL if |type| does not support quota or reservation fails.
+ // This should be run on |default_file_task_runner_| and the returned value
+ // should be destroyed on the runner.
+ scoped_refptr<QuotaReservation> CreateQuotaReservationOnFileTaskRunner(
+ const GURL& origin_url,
+ FileSystemType type);
+
quota::QuotaManagerProxy* quota_manager_proxy() const {
return quota_manager_proxy_.get();
}
@@ -151,9 +163,10 @@ class WEBKIT_STORAGE_BROWSER_EXPORT FileSystemContext
ExternalFileSystemBackend* external_backend() const;
// Used for OpenFileSystem.
- typedef base::Callback<void(base::PlatformFileError result,
+ typedef base::Callback<void(const GURL& root,
const std::string& name,
- const GURL& root)> OpenFileSystemCallback;
+ base::PlatformFileError result)>
+ OpenFileSystemCallback;
// Used for ResolveURL.
typedef base::Callback<void(base::PlatformFileError result,
@@ -161,9 +174,8 @@ class WEBKIT_STORAGE_BROWSER_EXPORT FileSystemContext
const base::FilePath& file_path,
bool is_directory)> ResolveURLCallback;
- // Used for DeleteFileSystem.
- typedef base::Callback<void(base::PlatformFileError result)>
- DeleteFileSystemCallback;
+ // Used for DeleteFileSystem and OpenPluginPrivateFileSystem.
+ typedef base::Callback<void(base::PlatformFileError result)> StatusCallback;
// Opens the filesystem for the given |origin_url| and |type|, and dispatches
// |callback| on completion.
@@ -188,7 +200,7 @@ class WEBKIT_STORAGE_BROWSER_EXPORT FileSystemContext
void DeleteFileSystem(
const GURL& origin_url,
FileSystemType type,
- const DeleteFileSystemCallback& callback);
+ const StatusCallback& callback);
// Creates new FileStreamReader instance to read a file pointed by the given
// filesystem URL |url| starting from |offset|. |expected_modification_time|
@@ -232,7 +244,7 @@ class WEBKIT_STORAGE_BROWSER_EXPORT FileSystemContext
FileSystemType type,
const base::FilePath& path) const;
-#if defined(OS_CHROMEOS) && defined(GOOGLE_CHROME_BUILD)
+#if defined(OS_CHROMEOS)
// Used only on ChromeOS for now.
void EnableTemporaryFileSystemInIncognito();
#endif
@@ -245,6 +257,16 @@ class WEBKIT_STORAGE_BROWSER_EXPORT FileSystemContext
// (E.g. this returns false if the context is created for incognito mode)
bool CanServeURLRequest(const FileSystemURL& url) const;
+ // This must be used to open 'plugin private' filesystem.
+ // See "plugin_private_file_system_backend.h" for more details.
+ void OpenPluginPrivateFileSystem(
+ const GURL& origin_url,
+ FileSystemType type,
+ const std::string& filesystem_id,
+ const std::string& plugin_id,
+ OpenFileSystemMode mode,
+ const StatusCallback& callback);
+
private:
typedef std::map<FileSystemType, FileSystemBackend*>
FileSystemBackendMap;
@@ -255,6 +277,9 @@ class WEBKIT_STORAGE_BROWSER_EXPORT FileSystemContext
// For sandbox_backend().
friend class SandboxFileSystemTestHelper;
+ // For plugin_private_backend().
+ friend class PluginPrivateFileSystemBackendTest;
+
// Deleters.
friend struct DefaultContextDeleter;
friend class base::DeleteHelper<FileSystemContext>;
@@ -300,6 +325,11 @@ class WEBKIT_STORAGE_BROWSER_EXPORT FileSystemContext
return sandbox_backend_.get();
}
+ // Used only by test code.
+ PluginPrivateFileSystemBackend* plugin_private_backend() const {
+ return plugin_private_backend_.get();
+ }
+
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
scoped_refptr<base::SequencedTaskRunner> default_file_task_runner_;
@@ -312,6 +342,7 @@ class WEBKIT_STORAGE_BROWSER_EXPORT FileSystemContext
scoped_ptr<IsolatedFileSystemBackend> isolated_backend_;
// Additional file system backends.
+ scoped_ptr<PluginPrivateFileSystemBackend> plugin_private_backend_;
ScopedVector<FileSystemBackend> additional_backends_;
// Registered file system backends.
diff --git a/chromium/webkit/browser/fileapi/file_system_context_unittest.cc b/chromium/webkit/browser/fileapi/file_system_context_unittest.cc
deleted file mode 100644
index 92256af625b..00000000000
--- a/chromium/webkit/browser/fileapi/file_system_context_unittest.cc
+++ /dev/null
@@ -1,328 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "webkit/browser/fileapi/file_system_context.h"
-
-#include "base/files/scoped_temp_dir.h"
-#include "base/message_loop/message_loop.h"
-#include "base/strings/stringprintf.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "webkit/browser/fileapi/external_mount_points.h"
-#include "webkit/browser/fileapi/file_system_backend.h"
-#include "webkit/browser/fileapi/isolated_context.h"
-#include "webkit/browser/fileapi/mock_file_system_options.h"
-#include "webkit/browser/quota/mock_quota_manager.h"
-#include "webkit/browser/quota/mock_special_storage_policy.h"
-
-#define FPL(x) FILE_PATH_LITERAL(x)
-
-#if defined(FILE_PATH_USES_DRIVE_LETTERS)
-#define DRIVE FPL("C:")
-#else
-#define DRIVE
-#endif
-
-namespace fileapi {
-
-namespace {
-
-const char kTestOrigin[] = "http://chromium.org/";
-const base::FilePath::CharType kVirtualPathNoRoot[] = FPL("root/file");
-
-GURL CreateRawFileSystemURL(const std::string& type_str,
- const std::string& fs_id) {
- std::string url_str = base::StringPrintf(
- "filesystem:http://chromium.org/%s/%s/root/file",
- type_str.c_str(),
- fs_id.c_str());
- return GURL(url_str);
-}
-
-class FileSystemContextTest : public testing::Test {
- public:
- FileSystemContextTest() {}
-
- virtual void SetUp() {
- ASSERT_TRUE(data_dir_.CreateUniqueTempDir());
-
- storage_policy_ = new quota::MockSpecialStoragePolicy();
-
- mock_quota_manager_ =
- new quota::MockQuotaManager(false /* is_incognito */,
- data_dir_.path(),
- base::MessageLoopProxy::current().get(),
- base::MessageLoopProxy::current().get(),
- storage_policy_.get());
- }
-
- protected:
- FileSystemContext* CreateFileSystemContextForTest(
- ExternalMountPoints* external_mount_points) {
- return new FileSystemContext(base::MessageLoopProxy::current().get(),
- base::MessageLoopProxy::current().get(),
- external_mount_points,
- storage_policy_.get(),
- mock_quota_manager_->proxy(),
- ScopedVector<FileSystemBackend>(),
- data_dir_.path(),
- CreateAllowFileAccessOptions());
- }
-
- // Verifies a *valid* filesystem url has expected values.
- void ExpectFileSystemURLMatches(const FileSystemURL& url,
- const GURL& expect_origin,
- FileSystemType expect_mount_type,
- FileSystemType expect_type,
- const base::FilePath& expect_path,
- const base::FilePath& expect_virtual_path,
- const std::string& expect_filesystem_id) {
- EXPECT_TRUE(url.is_valid());
-
- EXPECT_EQ(expect_origin, url.origin());
- EXPECT_EQ(expect_mount_type, url.mount_type());
- EXPECT_EQ(expect_type, url.type());
- EXPECT_EQ(expect_path, url.path());
- EXPECT_EQ(expect_virtual_path, url.virtual_path());
- EXPECT_EQ(expect_filesystem_id, url.filesystem_id());
- }
-
- private:
- base::ScopedTempDir data_dir_;
- base::MessageLoop message_loop_;
- scoped_refptr<quota::SpecialStoragePolicy> storage_policy_;
- scoped_refptr<quota::MockQuotaManager> mock_quota_manager_;
-};
-
-// It is not valid to pass NULL ExternalMountPoints to FileSystemContext on
-// ChromeOS.
-#if !defined(OS_CHROMEOS)
-TEST_F(FileSystemContextTest, NullExternalMountPoints) {
- scoped_refptr<FileSystemContext> file_system_context(
- CreateFileSystemContextForTest(NULL));
-
- // Cracking system external mount and isolated mount points should work.
- std::string isolated_name = "root";
- std::string isolated_id =
- IsolatedContext::GetInstance()->RegisterFileSystemForPath(
- kFileSystemTypeNativeLocal,
- base::FilePath(DRIVE FPL("/test/isolated/root")),
- &isolated_name);
- // Register system external mount point.
- ASSERT_TRUE(ExternalMountPoints::GetSystemInstance()->RegisterFileSystem(
- "system",
- kFileSystemTypeNativeLocal,
- base::FilePath(DRIVE FPL("/test/sys/"))));
-
- FileSystemURL cracked_isolated = file_system_context->CrackURL(
- CreateRawFileSystemURL("isolated", isolated_id));
-
- ExpectFileSystemURLMatches(
- cracked_isolated,
- GURL(kTestOrigin),
- kFileSystemTypeIsolated,
- kFileSystemTypeNativeLocal,
- base::FilePath(DRIVE FPL("/test/isolated/root/file")).NormalizePathSeparators(),
- base::FilePath::FromUTF8Unsafe(isolated_id).Append(FPL("root/file")).
- NormalizePathSeparators(),
- isolated_id);
-
- FileSystemURL cracked_external = file_system_context->CrackURL(
- CreateRawFileSystemURL("external", "system"));
-
- ExpectFileSystemURLMatches(
- cracked_external,
- GURL(kTestOrigin),
- kFileSystemTypeExternal,
- kFileSystemTypeNativeLocal,
- base::FilePath(
- DRIVE FPL("/test/sys/root/file")).NormalizePathSeparators(),
- base::FilePath(FPL("system/root/file")).NormalizePathSeparators(),
- "system");
-
-
- IsolatedContext::GetInstance()->RevokeFileSystem(isolated_id);
- ExternalMountPoints::GetSystemInstance()->RevokeFileSystem("system");
-}
-#endif // !defiend(OS_CHROMEOS)
-
-TEST_F(FileSystemContextTest, FileSystemContextKeepsMountPointsAlive) {
- scoped_refptr<ExternalMountPoints> mount_points =
- ExternalMountPoints::CreateRefCounted();
-
- // Register system external mount point.
- ASSERT_TRUE(mount_points->RegisterFileSystem(
- "system",
- kFileSystemTypeNativeLocal,
- base::FilePath(DRIVE FPL("/test/sys/"))));
-
- scoped_refptr<FileSystemContext> file_system_context(
- CreateFileSystemContextForTest(mount_points.get()));
-
- // Release a MountPoints reference created in the test.
- mount_points = NULL;
-
- // FileSystemContext should keep a reference to the |mount_points|, so it
- // should be able to resolve the URL.
- FileSystemURL cracked_external = file_system_context->CrackURL(
- CreateRawFileSystemURL("external", "system"));
-
- ExpectFileSystemURLMatches(
- cracked_external,
- GURL(kTestOrigin),
- kFileSystemTypeExternal,
- kFileSystemTypeNativeLocal,
- base::FilePath(
- DRIVE FPL("/test/sys/root/file")).NormalizePathSeparators(),
- base::FilePath(FPL("system/root/file")).NormalizePathSeparators(),
- "system");
-
- // No need to revoke the registered filesystem since |mount_points| lifetime
- // is bound to this test.
-}
-
-TEST_F(FileSystemContextTest, CrackFileSystemURL) {
- scoped_refptr<ExternalMountPoints> external_mount_points(
- ExternalMountPoints::CreateRefCounted());
- scoped_refptr<FileSystemContext> file_system_context(
- CreateFileSystemContextForTest(external_mount_points.get()));
-
- // Register an isolated mount point.
- std::string isolated_file_system_name = "root";
- const std::string kIsolatedFileSystemID =
- IsolatedContext::GetInstance()->RegisterFileSystemForPath(
- kFileSystemTypeNativeLocal,
- base::FilePath(DRIVE FPL("/test/isolated/root")),
- &isolated_file_system_name);
- // Register system external mount point.
- ASSERT_TRUE(ExternalMountPoints::GetSystemInstance()->RegisterFileSystem(
- "system",
- kFileSystemTypeDrive,
- base::FilePath(DRIVE FPL("/test/sys/"))));
- ASSERT_TRUE(ExternalMountPoints::GetSystemInstance()->RegisterFileSystem(
- "ext",
- kFileSystemTypeNativeLocal,
- base::FilePath(DRIVE FPL("/test/ext"))));
- // Register a system external mount point with the same name/id as the
- // registered isolated mount point.
- ASSERT_TRUE(ExternalMountPoints::GetSystemInstance()->RegisterFileSystem(
- kIsolatedFileSystemID,
- kFileSystemTypeRestrictedNativeLocal,
- base::FilePath(DRIVE FPL("/test/system/isolated"))));
- // Add a mount points with the same name as a system mount point to
- // FileSystemContext's external mount points.
- ASSERT_TRUE(external_mount_points->RegisterFileSystem(
- "ext",
- kFileSystemTypeNativeLocal,
- base::FilePath(DRIVE FPL("/test/local/ext/"))));
-
- const GURL kTestOrigin = GURL("http://chromium.org/");
- const base::FilePath kVirtualPathNoRoot = base::FilePath(FPL("root/file"));
-
- struct TestCase {
- // Test case values.
- std::string root;
- std::string type_str;
-
- // Expected test results.
- bool expect_is_valid;
- FileSystemType expect_mount_type;
- FileSystemType expect_type;
- const base::FilePath::CharType* expect_path;
- std::string expect_filesystem_id;
- };
-
- const TestCase kTestCases[] = {
- // Following should not be handled by the url crackers:
- {
- "pers_mount", "persistent", true /* is_valid */,
- kFileSystemTypePersistent, kFileSystemTypePersistent,
- FPL("pers_mount/root/file"),
- std::string() /* filesystem id */
- },
- {
- "temp_mount", "temporary", true /* is_valid */,
- kFileSystemTypeTemporary, kFileSystemTypeTemporary,
- FPL("temp_mount/root/file"),
- std::string() /* filesystem id */
- },
- // Should be cracked by isolated mount points:
- {
- kIsolatedFileSystemID, "isolated", true /* is_valid */,
- kFileSystemTypeIsolated, kFileSystemTypeNativeLocal,
- DRIVE FPL("/test/isolated/root/file"),
- kIsolatedFileSystemID
- },
- // Should be cracked by system mount points:
- {
- "system", "external", true /* is_valid */,
- kFileSystemTypeExternal, kFileSystemTypeDrive,
- DRIVE FPL("/test/sys/root/file"),
- "system"
- },
- {
- kIsolatedFileSystemID, "external", true /* is_valid */,
- kFileSystemTypeExternal, kFileSystemTypeRestrictedNativeLocal,
- DRIVE FPL("/test/system/isolated/root/file"),
- kIsolatedFileSystemID
- },
- // Should be cracked by FileSystemContext's ExternalMountPoints.
- {
- "ext", "external", true /* is_valid */,
- kFileSystemTypeExternal, kFileSystemTypeNativeLocal,
- DRIVE FPL("/test/local/ext/root/file"),
- "ext"
- },
- // Test for invalid filesystem url (made invalid by adding invalid
- // filesystem type).
- {
- "sytem", "external", false /* is_valid */,
- // The rest of values will be ignored.
- kFileSystemTypeUnknown, kFileSystemTypeUnknown, FPL(""),
- std::string()
- },
- // Test for URL with non-existing filesystem id.
- {
- "invalid", "external", false /* is_valid */,
- // The rest of values will be ignored.
- kFileSystemTypeUnknown, kFileSystemTypeUnknown, FPL(""),
- std::string()
- },
- };
-
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestCases); ++i) {
- const base::FilePath virtual_path =
- base::FilePath::FromUTF8Unsafe(kTestCases[i].root).Append(kVirtualPathNoRoot);
-
- GURL raw_url =
- CreateRawFileSystemURL(kTestCases[i].type_str, kTestCases[i].root);
- FileSystemURL cracked_url = file_system_context->CrackURL(raw_url);
-
- SCOPED_TRACE(testing::Message() << "Test case " << i << ": "
- << "Cracking URL: " << raw_url);
-
- EXPECT_EQ(kTestCases[i].expect_is_valid, cracked_url.is_valid());
- if (!kTestCases[i].expect_is_valid)
- continue;
-
- ExpectFileSystemURLMatches(
- cracked_url,
- GURL(kTestOrigin),
- kTestCases[i].expect_mount_type,
- kTestCases[i].expect_type,
- base::FilePath(kTestCases[i].expect_path).NormalizePathSeparators(),
- virtual_path.NormalizePathSeparators(),
- kTestCases[i].expect_filesystem_id);
- }
-
- IsolatedContext::GetInstance()->RevokeFileSystemByPath(
- base::FilePath(DRIVE FPL("/test/isolated/root")));
- ExternalMountPoints::GetSystemInstance()->RevokeFileSystem("system");
- ExternalMountPoints::GetSystemInstance()->RevokeFileSystem("ext");
- ExternalMountPoints::GetSystemInstance()->RevokeFileSystem(
- kIsolatedFileSystemID);
-}
-
-} // namespace
-
-} // namespace fileapi
diff --git a/chromium/webkit/browser/fileapi/file_system_dir_url_request_job.cc b/chromium/webkit/browser/fileapi/file_system_dir_url_request_job.cc
index 721a228b94e..7589b3732a0 100644
--- a/chromium/webkit/browser/fileapi/file_system_dir_url_request_job.cc
+++ b/chromium/webkit/browser/fileapi/file_system_dir_url_request_job.cc
@@ -117,7 +117,8 @@ void FileSystemDirURLRequestJob::DidReadDirectory(
if (data_.empty()) {
base::FilePath relative_path = url_.path();
#if defined(OS_POSIX)
- relative_path = base::FilePath(FILE_PATH_LITERAL("/") + relative_path.value());
+ relative_path =
+ base::FilePath(FILE_PATH_LITERAL("/") + relative_path.value());
#endif
const base::string16& title = relative_path.LossyDisplayName();
data_.append(net::GetDirectoryListingHeader(title));
diff --git a/chromium/webkit/browser/fileapi/file_system_dir_url_request_job_unittest.cc b/chromium/webkit/browser/fileapi/file_system_dir_url_request_job_unittest.cc
deleted file mode 100644
index e43ee4dfa3b..00000000000
--- a/chromium/webkit/browser/fileapi/file_system_dir_url_request_job_unittest.cc
+++ /dev/null
@@ -1,320 +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/browser/fileapi/file_system_dir_url_request_job.h"
-
-#include <string>
-
-#include "base/files/file_path.h"
-#include "base/files/scoped_temp_dir.h"
-#include "base/format_macros.h"
-#include "base/memory/weak_ptr.h"
-#include "base/message_loop/message_loop.h"
-#include "base/platform_file.h"
-#include "base/run_loop.h"
-#include "base/strings/string_piece.h"
-#include "base/strings/utf_string_conversions.h"
-#include "net/base/net_errors.h"
-#include "net/base/net_util.h"
-#include "net/http/http_request_headers.h"
-#include "net/url_request/url_request.h"
-#include "net/url_request/url_request_context.h"
-#include "net/url_request/url_request_test_util.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/icu/source/i18n/unicode/regex.h"
-#include "webkit/browser/fileapi/file_system_context.h"
-#include "webkit/browser/fileapi/file_system_file_util.h"
-#include "webkit/browser/fileapi/file_system_operation_context.h"
-#include "webkit/browser/fileapi/file_system_url.h"
-#include "webkit/browser/fileapi/mock_file_system_context.h"
-#include "webkit/browser/quota/mock_special_storage_policy.h"
-
-namespace fileapi {
-namespace {
-
-// We always use the TEMPORARY FileSystem in this test.
-static const char kFileSystemURLPrefix[] =
- "filesystem:http://remote/temporary/";
-
-} // namespace
-
-class FileSystemDirURLRequestJobTest : public testing::Test {
- protected:
- FileSystemDirURLRequestJobTest()
- : message_loop_(base::MessageLoop::TYPE_IO), // simulate an IO thread
- weak_factory_(this) {
- }
-
- virtual void SetUp() OVERRIDE {
- ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
-
- special_storage_policy_ = new quota::MockSpecialStoragePolicy;
- file_system_context_ = CreateFileSystemContextForTesting(
- NULL, temp_dir_.path());
-
- file_system_context_->OpenFileSystem(
- GURL("http://remote/"), kFileSystemTypeTemporary,
- OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
- base::Bind(&FileSystemDirURLRequestJobTest::OnOpenFileSystem,
- weak_factory_.GetWeakPtr()));
- base::RunLoop().RunUntilIdle();
-
- net::URLRequest::Deprecated::RegisterProtocolFactory(
- "filesystem", &FileSystemDirURLRequestJobFactory);
- }
-
- virtual void TearDown() OVERRIDE {
- // NOTE: order matters, request must die before delegate
- request_.reset(NULL);
- delegate_.reset(NULL);
-
- net::URLRequest::Deprecated::RegisterProtocolFactory("filesystem", NULL);
- ClearUnusedJob();
- }
-
- void OnOpenFileSystem(base::PlatformFileError result,
- const std::string& name,
- const GURL& root_url) {
- ASSERT_EQ(base::PLATFORM_FILE_OK, result);
- }
-
- void TestRequestHelper(const GURL& url, bool run_to_completion,
- FileSystemContext* file_system_context) {
- delegate_.reset(new net::TestDelegate());
- delegate_->set_quit_on_redirect(true);
- request_.reset(empty_context_.CreateRequest(url, delegate_.get()));
- job_ = new FileSystemDirURLRequestJob(
- request_.get(), NULL, file_system_context);
-
- request_->Start();
- ASSERT_TRUE(request_->is_pending()); // verify that we're starting async
- if (run_to_completion)
- base::MessageLoop::current()->Run();
- }
-
- void TestRequest(const GURL& url) {
- TestRequestHelper(url, true, file_system_context_.get());
- }
-
- void TestRequestWithContext(const GURL& url,
- FileSystemContext* file_system_context) {
- TestRequestHelper(url, true, file_system_context);
- }
-
- void TestRequestNoRun(const GURL& url) {
- TestRequestHelper(url, false, file_system_context_.get());
- }
-
- FileSystemURL CreateURL(const base::FilePath& file_path) {
- return file_system_context_->CreateCrackedFileSystemURL(
- GURL("http://remote"),
- fileapi::kFileSystemTypeTemporary,
- file_path);
- }
-
- FileSystemOperationContext* NewOperationContext() {
- FileSystemOperationContext* context(
- new FileSystemOperationContext(file_system_context_.get()));
- context->set_allowed_bytes_growth(1024);
- return context;
- }
-
- void CreateDirectory(const base::StringPiece& dir_name) {
- base::FilePath path = base::FilePath().AppendASCII(dir_name);
- scoped_ptr<FileSystemOperationContext> context(NewOperationContext());
- ASSERT_EQ(base::PLATFORM_FILE_OK, file_util()->CreateDirectory(
- context.get(),
- CreateURL(path),
- false /* exclusive */,
- false /* recursive */));
- }
-
- void EnsureFileExists(const base::StringPiece file_name) {
- base::FilePath path = base::FilePath().AppendASCII(file_name);
- scoped_ptr<FileSystemOperationContext> context(NewOperationContext());
- ASSERT_EQ(base::PLATFORM_FILE_OK, file_util()->EnsureFileExists(
- context.get(), CreateURL(path), NULL));
- }
-
- void TruncateFile(const base::StringPiece file_name, int64 length) {
- base::FilePath path = base::FilePath().AppendASCII(file_name);
- scoped_ptr<FileSystemOperationContext> context(NewOperationContext());
- ASSERT_EQ(base::PLATFORM_FILE_OK, file_util()->Truncate(
- context.get(), CreateURL(path), length));
- }
-
- base::PlatformFileError GetFileInfo(const base::FilePath& path,
- base::PlatformFileInfo* file_info,
- base::FilePath* platform_file_path) {
- scoped_ptr<FileSystemOperationContext> context(NewOperationContext());
- return file_util()->GetFileInfo(context.get(),
- CreateURL(path),
- file_info, platform_file_path);
- }
-
- void VerifyListingEntry(const std::string& entry_line,
- const std::string& name,
- const std::string& url,
- bool is_directory,
- int64 size) {
-#define STR "([^\"]*)"
- icu::UnicodeString pattern("^<script>addRow\\(\"" STR "\",\"" STR
- "\",(0|1),\"" STR "\",\"" STR "\"\\);</script>");
-#undef STR
- icu::UnicodeString input(entry_line.c_str());
-
- UErrorCode status = U_ZERO_ERROR;
- icu::RegexMatcher match(pattern, input, 0, status);
-
- EXPECT_TRUE(match.find());
- EXPECT_EQ(5, match.groupCount());
- EXPECT_EQ(icu::UnicodeString(name.c_str()), match.group(1, status));
- EXPECT_EQ(icu::UnicodeString(url.c_str()), match.group(2, status));
- EXPECT_EQ(icu::UnicodeString(is_directory ? "1" : "0"),
- match.group(3, status));
- icu::UnicodeString size_string(FormatBytesUnlocalized(size).c_str());
- EXPECT_EQ(size_string, match.group(4, status));
-
- base::Time date;
- icu::UnicodeString date_ustr(match.group(5, status));
- std::string date_str;
- UTF16ToUTF8(date_ustr.getBuffer(), date_ustr.length(), &date_str);
- EXPECT_TRUE(base::Time::FromString(date_str.c_str(), &date));
- EXPECT_FALSE(date.is_null());
- }
-
- GURL CreateFileSystemURL(const std::string path) {
- return GURL(kFileSystemURLPrefix + path);
- }
-
- static net::URLRequestJob* FileSystemDirURLRequestJobFactory(
- net::URLRequest* request,
- net::NetworkDelegate* network_delegate,
- const std::string& scheme) {
- DCHECK(job_);
- net::URLRequestJob* temp = job_;
- job_ = NULL;
- return temp;
- }
-
- static void ClearUnusedJob() {
- if (job_) {
- scoped_refptr<net::URLRequestJob> deleter = job_;
- job_ = NULL;
- }
- }
-
- FileSystemFileUtil* file_util() {
- return file_system_context_->sandbox_delegate()->sync_file_util();
- }
-
- // Put the message loop at the top, so that it's the last thing deleted.
- // Delete all MessageLoopProxy objects before the MessageLoop, to help prevent
- // leaks caused by tasks posted during shutdown.
- base::MessageLoop message_loop_;
-
- base::ScopedTempDir temp_dir_;
- net::URLRequestContext empty_context_;
- scoped_ptr<net::TestDelegate> delegate_;
- scoped_ptr<net::URLRequest> request_;
- scoped_refptr<quota::MockSpecialStoragePolicy> special_storage_policy_;
- scoped_refptr<FileSystemContext> file_system_context_;
- base::WeakPtrFactory<FileSystemDirURLRequestJobTest> weak_factory_;
-
- static net::URLRequestJob* job_;
-};
-
-// static
-net::URLRequestJob* FileSystemDirURLRequestJobTest::job_ = NULL;
-
-namespace {
-
-TEST_F(FileSystemDirURLRequestJobTest, DirectoryListing) {
- CreateDirectory("foo");
- CreateDirectory("foo/bar");
- CreateDirectory("foo/bar/baz");
-
- EnsureFileExists("foo/bar/hoge");
- TruncateFile("foo/bar/hoge", 10);
-
- TestRequest(CreateFileSystemURL("foo/bar/"));
-
- ASSERT_FALSE(request_->is_pending());
- EXPECT_EQ(1, delegate_->response_started_count());
- EXPECT_FALSE(delegate_->received_data_before_response());
- EXPECT_GT(delegate_->bytes_received(), 0);
-
- std::istringstream in(delegate_->data_received());
- std::string line;
- EXPECT_TRUE(std::getline(in, line));
-
-#if defined(OS_WIN)
- EXPECT_EQ("<script>start(\"foo\\\\bar\");</script>", line);
-#elif defined(OS_POSIX)
- EXPECT_EQ("<script>start(\"/foo/bar\");</script>", line);
-#endif
-
- EXPECT_TRUE(std::getline(in, line));
- VerifyListingEntry(line, "hoge", "hoge", false, 10);
-
- EXPECT_TRUE(std::getline(in, line));
- VerifyListingEntry(line, "baz", "baz", true, 0);
-}
-
-TEST_F(FileSystemDirURLRequestJobTest, InvalidURL) {
- TestRequest(GURL("filesystem:/foo/bar/baz"));
- ASSERT_FALSE(request_->is_pending());
- EXPECT_TRUE(delegate_->request_failed());
- ASSERT_FALSE(request_->status().is_success());
- EXPECT_EQ(net::ERR_INVALID_URL, request_->status().error());
-}
-
-TEST_F(FileSystemDirURLRequestJobTest, NoSuchRoot) {
- TestRequest(GURL("filesystem:http://remote/persistent/somedir/"));
- ASSERT_FALSE(request_->is_pending());
- ASSERT_FALSE(request_->status().is_success());
- EXPECT_EQ(net::ERR_FILE_NOT_FOUND, request_->status().error());
-}
-
-TEST_F(FileSystemDirURLRequestJobTest, NoSuchDirectory) {
- TestRequest(CreateFileSystemURL("somedir/"));
- ASSERT_FALSE(request_->is_pending());
- ASSERT_FALSE(request_->status().is_success());
- EXPECT_EQ(net::ERR_FILE_NOT_FOUND, request_->status().error());
-}
-
-TEST_F(FileSystemDirURLRequestJobTest, Cancel) {
- CreateDirectory("foo");
- TestRequestNoRun(CreateFileSystemURL("foo/"));
- // Run StartAsync() and only StartAsync().
- base::MessageLoop::current()->DeleteSoon(FROM_HERE, request_.release());
- base::RunLoop().RunUntilIdle();
- // If we get here, success! we didn't crash!
-}
-
-TEST_F(FileSystemDirURLRequestJobTest, Incognito) {
- CreateDirectory("foo");
-
- scoped_refptr<FileSystemContext> file_system_context =
- CreateIncognitoFileSystemContextForTesting(NULL, temp_dir_.path());
-
- TestRequestWithContext(CreateFileSystemURL("/"),
- file_system_context.get());
- ASSERT_FALSE(request_->is_pending());
- ASSERT_TRUE(request_->status().is_success());
-
- std::istringstream in(delegate_->data_received());
- std::string line;
- EXPECT_TRUE(std::getline(in, line));
- EXPECT_FALSE(std::getline(in, line));
-
- TestRequestWithContext(CreateFileSystemURL("foo"),
- file_system_context.get());
- ASSERT_FALSE(request_->is_pending());
- ASSERT_FALSE(request_->status().is_success());
- EXPECT_EQ(net::ERR_FILE_NOT_FOUND, request_->status().error());
-}
-
-} // namespace (anonymous)
-} // namespace fileapi
diff --git a/chromium/webkit/browser/fileapi/file_system_file_stream_reader.cc b/chromium/webkit/browser/fileapi/file_system_file_stream_reader.cc
index d3697c201e5..f5427b7620f 100644
--- a/chromium/webkit/browser/fileapi/file_system_file_stream_reader.cc
+++ b/chromium/webkit/browser/fileapi/file_system_file_stream_reader.cc
@@ -32,7 +32,7 @@ FileStreamReader* FileStreamReader::CreateForFileSystemFile(
expected_modification_time);
}
-} // webkit_blob
+} // namespace webkit_blob
namespace fileapi {
diff --git a/chromium/webkit/browser/fileapi/file_system_file_stream_reader_unittest.cc b/chromium/webkit/browser/fileapi/file_system_file_stream_reader_unittest.cc
deleted file mode 100644
index 0ce56585e42..00000000000
--- a/chromium/webkit/browser/fileapi/file_system_file_stream_reader_unittest.cc
+++ /dev/null
@@ -1,267 +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/browser/fileapi/file_system_file_stream_reader.h"
-
-#include <limits>
-#include <string>
-
-#include "base/files/scoped_temp_dir.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/platform_file.h"
-#include "base/run_loop.h"
-#include "net/base/io_buffer.h"
-#include "net/base/net_errors.h"
-#include "net/base/test_completion_callback.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "webkit/browser/fileapi/async_file_test_helper.h"
-#include "webkit/browser/fileapi/external_mount_points.h"
-#include "webkit/browser/fileapi/file_system_context.h"
-#include "webkit/browser/fileapi/file_system_file_util.h"
-#include "webkit/browser/fileapi/mock_file_system_context.h"
-
-namespace fileapi {
-
-namespace {
-
-const char kURLOrigin[] = "http://remote/";
-const char kTestFileName[] = "test.dat";
-const char kTestData[] = "0123456789";
-const int kTestDataSize = arraysize(kTestData) - 1;
-
-void ReadFromReader(FileSystemFileStreamReader* reader,
- std::string* data,
- size_t size,
- int* result) {
- ASSERT_TRUE(reader != NULL);
- ASSERT_TRUE(result != NULL);
- *result = net::OK;
- net::TestCompletionCallback callback;
- size_t total_bytes_read = 0;
- while (total_bytes_read < size) {
- scoped_refptr<net::IOBufferWithSize> buf(
- new net::IOBufferWithSize(size - total_bytes_read));
- int rv = reader->Read(buf.get(), buf->size(), callback.callback());
- if (rv == net::ERR_IO_PENDING)
- rv = callback.WaitForResult();
- if (rv < 0)
- *result = rv;
- if (rv <= 0)
- break;
- total_bytes_read += rv;
- data->append(buf->data(), rv);
- }
-}
-
-void NeverCalled(int unused) { ADD_FAILURE(); }
-
-} // namespace
-
-class FileSystemFileStreamReaderTest : public testing::Test {
- public:
- FileSystemFileStreamReaderTest()
- : message_loop_(base::MessageLoop::TYPE_IO) {}
-
- virtual void SetUp() OVERRIDE {
- ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
-
- file_system_context_ = CreateFileSystemContextForTesting(
- NULL, temp_dir_.path());
-
- file_system_context_->OpenFileSystem(
- GURL(kURLOrigin), kFileSystemTypeTemporary,
- OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
- base::Bind(&OnOpenFileSystem));
- base::RunLoop().RunUntilIdle();
-
- WriteFile(kTestFileName, kTestData, kTestDataSize,
- &test_file_modification_time_);
- }
-
- virtual void TearDown() OVERRIDE {
- base::RunLoop().RunUntilIdle();
- }
-
- protected:
- FileSystemFileStreamReader* CreateFileReader(
- const std::string& file_name,
- int64 initial_offset,
- const base::Time& expected_modification_time) {
- return new FileSystemFileStreamReader(file_system_context_.get(),
- GetFileSystemURL(file_name),
- initial_offset,
- expected_modification_time);
- }
-
- base::Time test_file_modification_time() const {
- return test_file_modification_time_;
- }
-
- void WriteFile(const std::string& file_name,
- const char* buf,
- int buf_size,
- base::Time* modification_time) {
- FileSystemURL url = GetFileSystemURL(file_name);
-
- ASSERT_EQ(base::PLATFORM_FILE_OK,
- fileapi::AsyncFileTestHelper::CreateFileWithData(
- file_system_context_, url, buf, buf_size));
-
- base::PlatformFileInfo file_info;
- ASSERT_EQ(base::PLATFORM_FILE_OK,
- AsyncFileTestHelper::GetMetadata(
- file_system_context_, url, &file_info));
- if (modification_time)
- *modification_time = file_info.last_modified;
- }
-
- private:
- static void OnOpenFileSystem(base::PlatformFileError result,
- const std::string& name,
- const GURL& root_url) {
- ASSERT_EQ(base::PLATFORM_FILE_OK, result);
- }
-
- FileSystemURL GetFileSystemURL(const std::string& file_name) {
- return file_system_context_->CreateCrackedFileSystemURL(
- GURL(kURLOrigin),
- kFileSystemTypeTemporary,
- base::FilePath().AppendASCII(file_name));
- }
-
- base::MessageLoop message_loop_;
- base::ScopedTempDir temp_dir_;
- scoped_refptr<FileSystemContext> file_system_context_;
- base::Time test_file_modification_time_;
-};
-
-TEST_F(FileSystemFileStreamReaderTest, NonExistent) {
- const char kFileName[] = "nonexistent";
- scoped_ptr<FileSystemFileStreamReader> reader(
- CreateFileReader(kFileName, 0, base::Time()));
- int result = 0;
- std::string data;
- ReadFromReader(reader.get(), &data, 10, &result);
- ASSERT_EQ(net::ERR_FILE_NOT_FOUND, result);
- ASSERT_EQ(0U, data.size());
-}
-
-TEST_F(FileSystemFileStreamReaderTest, Empty) {
- const char kFileName[] = "empty";
- WriteFile(kFileName, NULL, 0, NULL);
-
- scoped_ptr<FileSystemFileStreamReader> reader(
- CreateFileReader(kFileName, 0, base::Time()));
- int result = 0;
- std::string data;
- ReadFromReader(reader.get(), &data, 10, &result);
- ASSERT_EQ(net::OK, result);
- ASSERT_EQ(0U, data.size());
-
- net::TestInt64CompletionCallback callback;
- int64 length_result = reader->GetLength(callback.callback());
- if (length_result == net::ERR_IO_PENDING)
- length_result = callback.WaitForResult();
- ASSERT_EQ(0, length_result);
-}
-
-TEST_F(FileSystemFileStreamReaderTest, GetLengthNormal) {
- scoped_ptr<FileSystemFileStreamReader> reader(
- CreateFileReader(kTestFileName, 0, test_file_modification_time()));
- net::TestInt64CompletionCallback callback;
- int64 result = reader->GetLength(callback.callback());
- if (result == net::ERR_IO_PENDING)
- result = callback.WaitForResult();
- ASSERT_EQ(kTestDataSize, result);
-}
-
-TEST_F(FileSystemFileStreamReaderTest, GetLengthAfterModified) {
- // Pass a fake expected modifictaion time so that the expectation fails.
- base::Time fake_expected_modification_time =
- test_file_modification_time() - base::TimeDelta::FromSeconds(10);
-
- scoped_ptr<FileSystemFileStreamReader> reader(
- CreateFileReader(kTestFileName, 0, fake_expected_modification_time));
- net::TestInt64CompletionCallback callback;
- int64 result = reader->GetLength(callback.callback());
- if (result == net::ERR_IO_PENDING)
- result = callback.WaitForResult();
- ASSERT_EQ(net::ERR_UPLOAD_FILE_CHANGED, result);
-
- // With NULL expected modification time this should work.
- reader.reset(CreateFileReader(kTestFileName, 0, base::Time()));
- result = reader->GetLength(callback.callback());
- if (result == net::ERR_IO_PENDING)
- result = callback.WaitForResult();
- ASSERT_EQ(kTestDataSize, result);
-}
-
-TEST_F(FileSystemFileStreamReaderTest, GetLengthWithOffset) {
- scoped_ptr<FileSystemFileStreamReader> reader(
- CreateFileReader(kTestFileName, 3, base::Time()));
- net::TestInt64CompletionCallback callback;
- int64 result = reader->GetLength(callback.callback());
- if (result == net::ERR_IO_PENDING)
- result = callback.WaitForResult();
- // Initial offset does not affect the result of GetLength.
- ASSERT_EQ(kTestDataSize, result);
-}
-
-TEST_F(FileSystemFileStreamReaderTest, ReadNormal) {
- scoped_ptr<FileSystemFileStreamReader> reader(
- CreateFileReader(kTestFileName, 0, test_file_modification_time()));
- int result = 0;
- std::string data;
- ReadFromReader(reader.get(), &data, kTestDataSize, &result);
- ASSERT_EQ(net::OK, result);
- ASSERT_EQ(kTestData, data);
-}
-
-TEST_F(FileSystemFileStreamReaderTest, ReadAfterModified) {
- // Pass a fake expected modifictaion time so that the expectation fails.
- base::Time fake_expected_modification_time =
- test_file_modification_time() - base::TimeDelta::FromSeconds(10);
-
- scoped_ptr<FileSystemFileStreamReader> reader(
- CreateFileReader(kTestFileName, 0, fake_expected_modification_time));
- int result = 0;
- std::string data;
- ReadFromReader(reader.get(), &data, kTestDataSize, &result);
- ASSERT_EQ(net::ERR_UPLOAD_FILE_CHANGED, result);
- ASSERT_EQ(0U, data.size());
-
- // With NULL expected modification time this should work.
- data.clear();
- reader.reset(CreateFileReader(kTestFileName, 0, base::Time()));
- ReadFromReader(reader.get(), &data, kTestDataSize, &result);
- ASSERT_EQ(net::OK, result);
- ASSERT_EQ(kTestData, data);
-}
-
-TEST_F(FileSystemFileStreamReaderTest, ReadWithOffset) {
- scoped_ptr<FileSystemFileStreamReader> reader(
- CreateFileReader(kTestFileName, 3, base::Time()));
- int result = 0;
- std::string data;
- ReadFromReader(reader.get(), &data, kTestDataSize, &result);
- ASSERT_EQ(net::OK, result);
- ASSERT_EQ(&kTestData[3], data);
-}
-
-TEST_F(FileSystemFileStreamReaderTest, DeleteWithUnfinishedRead) {
- scoped_ptr<FileSystemFileStreamReader> reader(
- CreateFileReader(kTestFileName, 0, base::Time()));
-
- net::TestCompletionCallback callback;
- scoped_refptr<net::IOBufferWithSize> buf(
- new net::IOBufferWithSize(kTestDataSize));
- int rv = reader->Read(buf.get(), buf->size(), base::Bind(&NeverCalled));
- ASSERT_TRUE(rv == net::ERR_IO_PENDING || rv >= 0);
-
- // Delete immediately.
- // Should not crash; nor should NeverCalled be callback.
- reader.reset();
-}
-
-} // namespace fileapi
diff --git a/chromium/webkit/browser/fileapi/file_system_file_util.h b/chromium/webkit/browser/fileapi/file_system_file_util.h
index 13ea0e40a4d..5a4d730b5c8 100644
--- a/chromium/webkit/browser/fileapi/file_system_file_util.h
+++ b/chromium/webkit/browser/fileapi/file_system_file_util.h
@@ -8,6 +8,7 @@
#include "base/files/file_path.h"
#include "base/memory/scoped_ptr.h"
#include "base/platform_file.h"
+#include "webkit/browser/fileapi/file_system_operation.h"
#include "webkit/browser/webkit_storage_browser_export.h"
#include "webkit/common/blob/scoped_file.h"
@@ -27,6 +28,8 @@ class FileSystemURL;
// See http://crbug.com/128136 if you need it.
class WEBKIT_STORAGE_BROWSER_EXPORT FileSystemFileUtil {
public:
+ typedef FileSystemOperation::CopyOrMoveOption CopyOrMoveOption;
+
// It will be implemented by each subclass such as FileSystemFileEnumerator.
class WEBKIT_STORAGE_BROWSER_EXPORT AbstractFileEnumerator {
public:
@@ -56,7 +59,7 @@ class WEBKIT_STORAGE_BROWSER_EXPORT FileSystemFileUtil {
// Creates or opens a file with the given flags.
// See header comments for AsyncFileUtil::CreateOrOpen() for more details.
- // This is used only by Pepper/NaCL File API.
+ // This is used only by Pepper/NaCl File API.
virtual base::PlatformFileError CreateOrOpen(
FileSystemOperationContext* context,
const FileSystemURL& url,
@@ -65,7 +68,7 @@ class WEBKIT_STORAGE_BROWSER_EXPORT FileSystemFileUtil {
bool* created) = 0;
// Closes the given file handle.
- // This is used only for Pepper/NaCL File API.
+ // This is used only for Pepper/NaCl File API.
virtual base::PlatformFileError Close(
FileSystemOperationContext* context,
base::PlatformFile file) = 0;
@@ -129,6 +132,7 @@ class WEBKIT_STORAGE_BROWSER_EXPORT FileSystemFileUtil {
// Copies or moves a single file from |src_url| to |dest_url|.
// The filesystem type of |src_url| and |dest_url| MUST be same.
+ // For |option|, please see file_system_operation.h
//
// This returns:
// - PLATFORM_FILE_ERROR_NOT_FOUND if |src_url|
@@ -143,6 +147,7 @@ class WEBKIT_STORAGE_BROWSER_EXPORT FileSystemFileUtil {
FileSystemOperationContext* context,
const FileSystemURL& src_url,
const FileSystemURL& dest_url,
+ CopyOrMoveOption option,
bool copy) = 0;
// Copies in a single file from a different filesystem.
diff --git a/chromium/webkit/browser/fileapi/file_system_operation.h b/chromium/webkit/browser/fileapi/file_system_operation.h
index 99d3b3d6a97..ded87f71ec2 100644
--- a/chromium/webkit/browser/fileapi/file_system_operation.h
+++ b/chromium/webkit/browser/fileapi/file_system_operation.h
@@ -80,8 +80,7 @@ class FileSystemOperation {
typedef base::Callback<
void(base::PlatformFileError result,
base::PlatformFile file,
- const base::Closure& on_close_callback,
- base::ProcessHandle peer_handle)> OpenFileCallback;
+ const base::Closure& on_close_callback)> OpenFileCallback;
// Used for ReadDirectoryCallback.
typedef std::vector<DirectoryEntry> FileEntryList;
@@ -209,6 +208,18 @@ class FileSystemOperation {
// set to the copied file size.
typedef base::Callback<void(int64 size)> CopyFileProgressCallback;
+ // The option for copy or move operation.
+ enum CopyOrMoveOption {
+ // No additional operation.
+ OPTION_NONE,
+
+ // Preserves last modified time if possible. If the operation to update
+ // last modified time is not supported on the file system for the
+ // destination file, this option would be simply ignored (i.e. Copy would
+ // be successfully done without preserving last modified time).
+ OPTION_PRESERVE_LAST_MODIFIED,
+ };
+
// Used for Write().
typedef base::Callback<void(base::PlatformFileError result,
int64 bytes,
@@ -233,6 +244,8 @@ class FileSystemOperation {
// |src_path| is a directory, the contents of |src_path| are copied to
// |dest_path| recursively. A new file or directory is created at
// |dest_path| as needed.
+ // |option| specifies the minor behavior of Copy(). See CopyOrMoveOption's
+ // comment for details.
// |progress_callback| is periodically called to report the progress
// update. See also the comment of CopyProgressCallback. This callback is
// optional.
@@ -247,11 +260,14 @@ class FileSystemOperation {
//
virtual void Copy(const FileSystemURL& src_path,
const FileSystemURL& dest_path,
+ CopyOrMoveOption option,
const CopyProgressCallback& progress_callback,
const StatusCallback& callback) = 0;
// Moves a file or directory from |src_path| to |dest_path|. A new file
// or directory is created at |dest_path| as needed.
+ // |option| specifies the minor behavior of Copy(). See CopyOrMoveOption's
+ // comment for details.
//
// For recursive case this internally creates new FileSystemOperations and
// calls:
@@ -263,6 +279,7 @@ class FileSystemOperation {
//
virtual void Move(const FileSystemURL& src_path,
const FileSystemURL& dest_path,
+ CopyOrMoveOption option,
const StatusCallback& callback) = 0;
// Checks if a directory is present at |path|.
@@ -337,13 +354,9 @@ class FileSystemOperation {
// Opens a file at |path| with |file_flags|, where flags are OR'ed
// values of base::PlatformFileFlags.
//
- // |peer_handle| is the process handle of a pepper plugin process, which
- // is necessary for underlying IPC calls with Pepper plugins.
- //
// This function is used only by Pepper as of writing.
virtual void OpenFile(const FileSystemURL& path,
int file_flags,
- base::ProcessHandle peer_handle,
const OpenFileCallback& callback) = 0;
// Creates a local snapshot file for a given |path| and returns the
@@ -393,6 +406,8 @@ class FileSystemOperation {
// Copies a file from |src_url| to |dest_url|.
// This must be called for files that belong to the same filesystem
// (i.e. type() and origin() of the |src_url| and |dest_url| must match).
+ // |option| specifies the minor behavior of Copy(). See CopyOrMoveOption's
+ // comment for details.
// |progress_callback| is periodically called to report the progress
// update. See also the comment of CopyFileProgressCallback. This callback is
// optional.
@@ -408,12 +423,15 @@ class FileSystemOperation {
//
virtual void CopyFileLocal(const FileSystemURL& src_url,
const FileSystemURL& dest_url,
+ CopyOrMoveOption option,
const CopyFileProgressCallback& progress_callback,
const StatusCallback& callback) = 0;
// Moves a local file from |src_url| to |dest_url|.
// This must be called for files that belong to the same filesystem
// (i.e. type() and origin() of the |src_url| and |dest_url| must match).
+ // |option| specifies the minor behavior of Copy(). See CopyOrMoveOption's
+ // comment for details.
//
// This returns:
// - PLATFORM_FILE_ERROR_NOT_FOUND if |src_url|
@@ -426,6 +444,7 @@ class FileSystemOperation {
//
virtual void MoveFileLocal(const FileSystemURL& src_url,
const FileSystemURL& dest_url,
+ CopyOrMoveOption option,
const StatusCallback& callback) = 0;
// Synchronously gets the platform path for the given |url|.
diff --git a/chromium/webkit/browser/fileapi/file_system_operation_impl.cc b/chromium/webkit/browser/fileapi/file_system_operation_impl.cc
index c9e75eb9acd..180e1205b4e 100644
--- a/chromium/webkit/browser/fileapi/file_system_operation_impl.cc
+++ b/chromium/webkit/browser/fileapi/file_system_operation_impl.cc
@@ -69,6 +69,7 @@ void FileSystemOperationImpl::CreateDirectory(const FileSystemURL& url,
void FileSystemOperationImpl::Copy(
const FileSystemURL& src_url,
const FileSystemURL& dest_url,
+ CopyOrMoveOption option,
const CopyProgressCallback& progress_callback,
const StatusCallback& callback) {
DCHECK(SetPendingOperationType(kOperationCopy));
@@ -80,6 +81,7 @@ void FileSystemOperationImpl::Copy(
file_system_context(),
src_url, dest_url,
CopyOrMoveOperationDelegate::OPERATION_COPY,
+ option,
progress_callback,
base::Bind(&FileSystemOperationImpl::DidFinishOperation,
weak_factory_.GetWeakPtr(), callback)));
@@ -88,6 +90,7 @@ void FileSystemOperationImpl::Copy(
void FileSystemOperationImpl::Move(const FileSystemURL& src_url,
const FileSystemURL& dest_url,
+ CopyOrMoveOption option,
const StatusCallback& callback) {
DCHECK(SetPendingOperationType(kOperationMove));
DCHECK(!recursive_operation_delegate_);
@@ -96,6 +99,7 @@ void FileSystemOperationImpl::Move(const FileSystemURL& src_url,
file_system_context(),
src_url, dest_url,
CopyOrMoveOperationDelegate::OPERATION_MOVE,
+ option,
FileSystemOperation::CopyProgressCallback(),
base::Bind(&FileSystemOperationImpl::DidFinishOperation,
weak_factory_.GetWeakPtr(), callback)));
@@ -195,18 +199,14 @@ void FileSystemOperationImpl::TouchFile(const FileSystemURL& url,
void FileSystemOperationImpl::OpenFile(const FileSystemURL& url,
int file_flags,
- base::ProcessHandle peer_handle,
const OpenFileCallback& callback) {
DCHECK(SetPendingOperationType(kOperationOpenFile));
- peer_handle_ = peer_handle;
- if (file_flags & (
- (base::PLATFORM_FILE_ENUMERATE | base::PLATFORM_FILE_TEMPORARY |
- base::PLATFORM_FILE_HIDDEN))) {
+ if (file_flags &
+ (base::PLATFORM_FILE_TEMPORARY | base::PLATFORM_FILE_HIDDEN)) {
callback.Run(base::PLATFORM_FILE_ERROR_FAILED,
base::kInvalidPlatformFileValue,
- base::Closure(),
- base::kNullProcessHandle);
+ base::Closure());
return;
}
GetUsageAndQuotaThenRunTask(
@@ -216,8 +216,7 @@ void FileSystemOperationImpl::OpenFile(const FileSystemURL& url,
url, callback, file_flags),
base::Bind(callback, base::PLATFORM_FILE_ERROR_FAILED,
base::kInvalidPlatformFileValue,
- base::Closure(),
- base::kNullProcessHandle));
+ base::Closure()));
}
// We can only get here on a write or truncate that's not yet completed.
@@ -284,6 +283,7 @@ void FileSystemOperationImpl::RemoveDirectory(
void FileSystemOperationImpl::CopyFileLocal(
const FileSystemURL& src_url,
const FileSystemURL& dest_url,
+ CopyOrMoveOption option,
const CopyFileProgressCallback& progress_callback,
const StatusCallback& callback) {
DCHECK(SetPendingOperationType(kOperationCopy));
@@ -292,7 +292,7 @@ void FileSystemOperationImpl::CopyFileLocal(
GetUsageAndQuotaThenRunTask(
dest_url,
base::Bind(&FileSystemOperationImpl::DoCopyFileLocal,
- weak_factory_.GetWeakPtr(), src_url, dest_url,
+ weak_factory_.GetWeakPtr(), src_url, dest_url, option,
progress_callback, callback),
base::Bind(callback, base::PLATFORM_FILE_ERROR_FAILED));
}
@@ -300,13 +300,15 @@ void FileSystemOperationImpl::CopyFileLocal(
void FileSystemOperationImpl::MoveFileLocal(
const FileSystemURL& src_url,
const FileSystemURL& dest_url,
+ CopyOrMoveOption option,
const StatusCallback& callback) {
DCHECK(SetPendingOperationType(kOperationMove));
DCHECK(src_url.IsInSameFileSystem(dest_url));
GetUsageAndQuotaThenRunTask(
dest_url,
base::Bind(&FileSystemOperationImpl::DoMoveFileLocal,
- weak_factory_.GetWeakPtr(), src_url, dest_url, callback),
+ weak_factory_.GetWeakPtr(),
+ src_url, dest_url, option, callback),
base::Bind(callback, base::PLATFORM_FILE_ERROR_FAILED));
}
@@ -329,7 +331,6 @@ FileSystemOperationImpl::FileSystemOperationImpl(
: file_system_context_(file_system_context),
operation_context_(operation_context.Pass()),
async_file_util_(NULL),
- peer_handle_(base::kNullProcessHandle),
pending_operation_(kOperationNone),
weak_factory_(this) {
DCHECK(operation_context_.get());
@@ -404,10 +405,11 @@ void FileSystemOperationImpl::DoCreateDirectory(
void FileSystemOperationImpl::DoCopyFileLocal(
const FileSystemURL& src_url,
const FileSystemURL& dest_url,
+ CopyOrMoveOption option,
const CopyFileProgressCallback& progress_callback,
const StatusCallback& callback) {
async_file_util_->CopyFileLocal(
- operation_context_.Pass(), src_url, dest_url, progress_callback,
+ operation_context_.Pass(), src_url, dest_url, option, progress_callback,
base::Bind(&FileSystemOperationImpl::DidFinishOperation,
weak_factory_.GetWeakPtr(), callback));
}
@@ -415,9 +417,10 @@ void FileSystemOperationImpl::DoCopyFileLocal(
void FileSystemOperationImpl::DoMoveFileLocal(
const FileSystemURL& src_url,
const FileSystemURL& dest_url,
+ CopyOrMoveOption option,
const StatusCallback& callback) {
async_file_util_->MoveFileLocal(
- operation_context_.Pass(), src_url, dest_url,
+ operation_context_.Pass(), src_url, dest_url, option,
base::Bind(&FileSystemOperationImpl::DidFinishOperation,
weak_factory_.GetWeakPtr(), callback));
}
@@ -545,9 +548,7 @@ void FileSystemOperationImpl::DidOpenFile(
base::PlatformFileError rv,
base::PassPlatformFile file,
const base::Closure& on_close_callback) {
- if (rv == base::PLATFORM_FILE_OK)
- CHECK_NE(base::kNullProcessHandle, peer_handle_);
- callback.Run(rv, file.ReleaseValue(), on_close_callback, peer_handle_);
+ callback.Run(rv, file.ReleaseValue(), on_close_callback);
}
bool FileSystemOperationImpl::SetPendingOperationType(OperationType type) {
diff --git a/chromium/webkit/browser/fileapi/file_system_operation_impl.h b/chromium/webkit/browser/fileapi/file_system_operation_impl.h
index 8433479f881..06259950ce2 100644
--- a/chromium/webkit/browser/fileapi/file_system_operation_impl.h
+++ b/chromium/webkit/browser/fileapi/file_system_operation_impl.h
@@ -40,10 +40,12 @@ class WEBKIT_STORAGE_BROWSER_EXPORT FileSystemOperationImpl
const StatusCallback& callback) OVERRIDE;
virtual void Copy(const FileSystemURL& src_url,
const FileSystemURL& dest_url,
+ CopyOrMoveOption option,
const CopyProgressCallback& progress_callback,
const StatusCallback& callback) OVERRIDE;
virtual void Move(const FileSystemURL& src_url,
const FileSystemURL& dest_url,
+ CopyOrMoveOption option,
const StatusCallback& callback) OVERRIDE;
virtual void DirectoryExists(const FileSystemURL& url,
const StatusCallback& callback) OVERRIDE;
@@ -67,7 +69,6 @@ class WEBKIT_STORAGE_BROWSER_EXPORT FileSystemOperationImpl
const StatusCallback& callback) OVERRIDE;
virtual void OpenFile(const FileSystemURL& url,
int file_flags,
- base::ProcessHandle peer_handle,
const OpenFileCallback& callback) OVERRIDE;
virtual void Cancel(const StatusCallback& cancel_callback) OVERRIDE;
virtual void CreateSnapshotFile(
@@ -82,10 +83,12 @@ class WEBKIT_STORAGE_BROWSER_EXPORT FileSystemOperationImpl
const StatusCallback& callback) OVERRIDE;
virtual void CopyFileLocal(const FileSystemURL& src_url,
const FileSystemURL& dest_url,
+ CopyOrMoveOption option,
const CopyFileProgressCallback& progress_callback,
const StatusCallback& callback) OVERRIDE;
virtual void MoveFileLocal(const FileSystemURL& src_url,
const FileSystemURL& dest_url,
+ CopyOrMoveOption option,
const StatusCallback& callback) OVERRIDE;
virtual base::PlatformFileError SyncGetPlatformPath(
const FileSystemURL& url,
@@ -131,10 +134,12 @@ class WEBKIT_STORAGE_BROWSER_EXPORT FileSystemOperationImpl
bool recursive);
void DoCopyFileLocal(const FileSystemURL& src,
const FileSystemURL& dest,
+ CopyOrMoveOption option,
const CopyFileProgressCallback& progress_callback,
const StatusCallback& callback);
void DoMoveFileLocal(const FileSystemURL& src,
const FileSystemURL& dest,
+ CopyOrMoveOption option,
const StatusCallback& callback);
void DoCopyInForeignFile(const base::FilePath& src_local_disk_file_path,
const FileSystemURL& dest,
@@ -189,10 +194,6 @@ class WEBKIT_STORAGE_BROWSER_EXPORT FileSystemOperationImpl
StatusCallback cancel_callback_;
- // Used only by OpenFile, in order to clone the file handle back to the
- // requesting process.
- base::ProcessHandle peer_handle_;
-
// A flag to make sure we call operation only once per instance.
OperationType pending_operation_;
diff --git a/chromium/webkit/browser/fileapi/file_system_operation_impl_unittest.cc b/chromium/webkit/browser/fileapi/file_system_operation_impl_unittest.cc
deleted file mode 100644
index 7443aa066d1..00000000000
--- a/chromium/webkit/browser/fileapi/file_system_operation_impl_unittest.cc
+++ /dev/null
@@ -1,1210 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "webkit/browser/fileapi/file_system_operation_impl.h"
-
-#include "base/bind.h"
-#include "base/file_util.h"
-#include "base/files/scoped_temp_dir.h"
-#include "base/logging.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/memory/weak_ptr.h"
-#include "base/run_loop.h"
-#include "base/strings/stringprintf.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "url/gurl.h"
-#include "webkit/browser/fileapi/async_file_test_helper.h"
-#include "webkit/browser/fileapi/file_system_context.h"
-#include "webkit/browser/fileapi/file_system_file_util.h"
-#include "webkit/browser/fileapi/file_system_operation_context.h"
-#include "webkit/browser/fileapi/file_system_operation_runner.h"
-#include "webkit/browser/fileapi/mock_file_change_observer.h"
-#include "webkit/browser/fileapi/sandbox_file_system_backend.h"
-#include "webkit/browser/fileapi/sandbox_file_system_test_helper.h"
-#include "webkit/browser/quota/mock_quota_manager.h"
-#include "webkit/browser/quota/quota_manager.h"
-#include "webkit/common/blob/shareable_file_reference.h"
-#include "webkit/common/fileapi/file_system_util.h"
-
-using quota::QuotaManager;
-using quota::QuotaManagerProxy;
-using webkit_blob::ShareableFileReference;
-
-namespace fileapi {
-
-namespace {
-
-const int kFileOperationStatusNotSet = 1;
-
-void AssertFileErrorEq(const tracked_objects::Location& from_here,
- base::PlatformFileError expected,
- base::PlatformFileError actual) {
- ASSERT_EQ(expected, actual) << from_here.ToString();
-}
-
-} // namespace (anonymous)
-
-// Test class for FileSystemOperationImpl.
-class FileSystemOperationImplTest
- : public testing::Test {
- public:
- FileSystemOperationImplTest()
- : status_(kFileOperationStatusNotSet),
- weak_factory_(this) {}
-
- protected:
- virtual void SetUp() OVERRIDE {
- EXPECT_TRUE(base_.CreateUniqueTempDir());
- change_observers_ = MockFileChangeObserver::CreateList(&change_observer_);
-
- base::FilePath base_dir = base_.path().AppendASCII("filesystem");
- quota_manager_ =
- new quota::MockQuotaManager(false /* is_incognito */,
- base_dir,
- base::MessageLoopProxy::current().get(),
- base::MessageLoopProxy::current().get(),
- NULL /* special storage policy */);
- quota_manager_proxy_ = new quota::MockQuotaManagerProxy(
- quota_manager(), base::MessageLoopProxy::current().get());
- sandbox_file_system_.SetUp(base_dir, quota_manager_proxy_.get());
- sandbox_file_system_.AddFileChangeObserver(&change_observer_);
- }
-
- virtual void TearDown() OVERRIDE {
- // Let the client go away before dropping a ref of the quota manager proxy.
- quota_manager_proxy()->SimulateQuotaManagerDestroyed();
- quota_manager_ = NULL;
- quota_manager_proxy_ = NULL;
- sandbox_file_system_.TearDown();
- }
-
- FileSystemOperationRunner* operation_runner() {
- return sandbox_file_system_.operation_runner();
- }
-
- int status() const { return status_; }
- const base::PlatformFileInfo& info() const { return info_; }
- const base::FilePath& path() const { return path_; }
- const std::vector<DirectoryEntry>& entries() const {
- return entries_;
- }
-
- const ShareableFileReference* shareable_file_ref() const {
- return shareable_file_ref_.get();
- }
-
- quota::MockQuotaManager* quota_manager() {
- return static_cast<quota::MockQuotaManager*>(quota_manager_.get());
- }
-
- quota::MockQuotaManagerProxy* quota_manager_proxy() {
- return static_cast<quota::MockQuotaManagerProxy*>(
- quota_manager_proxy_.get());
- }
-
- FileSystemFileUtil* file_util() {
- return sandbox_file_system_.file_util();
- }
-
- MockFileChangeObserver* change_observer() {
- return &change_observer_;
- }
-
- scoped_ptr<FileSystemOperationContext> NewContext() {
- FileSystemOperationContext* context =
- sandbox_file_system_.NewOperationContext();
- // Grant enough quota for all test cases.
- context->set_allowed_bytes_growth(1000000);
- return make_scoped_ptr(context);
- }
-
- FileSystemURL URLForPath(const std::string& path) const {
- return sandbox_file_system_.CreateURLFromUTF8(path);
- }
-
- base::FilePath PlatformPath(const std::string& path) {
- return sandbox_file_system_.GetLocalPath(
- base::FilePath::FromUTF8Unsafe(path));
- }
-
- bool FileExists(const std::string& path) {
- return AsyncFileTestHelper::FileExists(
- sandbox_file_system_.file_system_context(), URLForPath(path),
- AsyncFileTestHelper::kDontCheckSize);
- }
-
- bool DirectoryExists(const std::string& path) {
- return AsyncFileTestHelper::DirectoryExists(
- sandbox_file_system_.file_system_context(), URLForPath(path));
- }
-
- FileSystemURL CreateFile(const std::string& path) {
- FileSystemURL url = URLForPath(path);
- bool created = false;
- EXPECT_EQ(base::PLATFORM_FILE_OK,
- file_util()->EnsureFileExists(NewContext().get(),
- url, &created));
- EXPECT_TRUE(created);
- return url;
- }
-
- FileSystemURL CreateDirectory(const std::string& path) {
- FileSystemURL url = URLForPath(path);
- EXPECT_EQ(base::PLATFORM_FILE_OK,
- file_util()->CreateDirectory(NewContext().get(), url,
- false /* exclusive */, true));
- return url;
- }
-
- int64 GetFileSize(const std::string& path) {
- base::PlatformFileInfo info;
- EXPECT_TRUE(file_util::GetFileInfo(PlatformPath(path), &info));
- return info.size;
- }
-
- // Callbacks for recording test results.
- FileSystemOperation::StatusCallback RecordStatusCallback() {
- return base::Bind(&FileSystemOperationImplTest::DidFinish,
- weak_factory_.GetWeakPtr());
- }
-
- FileSystemOperation::ReadDirectoryCallback
- RecordReadDirectoryCallback() {
- return base::Bind(&FileSystemOperationImplTest::DidReadDirectory,
- weak_factory_.GetWeakPtr());
- }
-
- FileSystemOperation::GetMetadataCallback RecordMetadataCallback() {
- return base::Bind(&FileSystemOperationImplTest::DidGetMetadata,
- weak_factory_.GetWeakPtr());
- }
-
- FileSystemOperation::SnapshotFileCallback RecordSnapshotFileCallback() {
- return base::Bind(&FileSystemOperationImplTest::DidCreateSnapshotFile,
- weak_factory_.GetWeakPtr());
- }
-
- void DidFinish(base::PlatformFileError status) {
- status_ = status;
- }
-
- void DidReadDirectory(
- base::PlatformFileError status,
- const std::vector<DirectoryEntry>& entries,
- bool /* has_more */) {
- entries_ = entries;
- status_ = status;
- }
-
- void DidGetMetadata(base::PlatformFileError status,
- const base::PlatformFileInfo& info) {
- info_ = info;
- status_ = status;
- }
-
- void DidCreateSnapshotFile(
- base::PlatformFileError status,
- const base::PlatformFileInfo& info,
- const base::FilePath& platform_path,
- const scoped_refptr<ShareableFileReference>& shareable_file_ref) {
- info_ = info;
- path_ = platform_path;
- status_ = status;
- shareable_file_ref_ = shareable_file_ref;
- }
-
- int64 GetDataSizeOnDisk() {
- return sandbox_file_system_.ComputeCurrentOriginUsage() -
- sandbox_file_system_.ComputeCurrentDirectoryDatabaseUsage();
- }
-
- void GetUsageAndQuota(int64* usage, int64* quota) {
- quota::QuotaStatusCode status =
- AsyncFileTestHelper::GetUsageAndQuota(quota_manager_.get(),
- sandbox_file_system_.origin(),
- sandbox_file_system_.type(),
- usage,
- quota);
- base::RunLoop().RunUntilIdle();
- ASSERT_EQ(quota::kQuotaStatusOk, status);
- }
-
- int64 ComputePathCost(const FileSystemURL& url) {
- int64 base_usage;
- GetUsageAndQuota(&base_usage, NULL);
-
- AsyncFileTestHelper::CreateFile(
- sandbox_file_system_.file_system_context(), url);
- operation_runner()->Remove(url, false /* recursive */,
- base::Bind(&AssertFileErrorEq, FROM_HERE,
- base::PLATFORM_FILE_OK));
- base::RunLoop().RunUntilIdle();
- change_observer()->ResetCount();
-
- int64 total_usage;
- GetUsageAndQuota(&total_usage, NULL);
- return total_usage - base_usage;
- }
-
- void GrantQuotaForCurrentUsage() {
- int64 usage;
- GetUsageAndQuota(&usage, NULL);
- quota_manager()->SetQuota(sandbox_file_system_.origin(),
- sandbox_file_system_.storage_type(),
- usage);
- }
-
- int64 GetUsage() {
- int64 usage = 0;
- GetUsageAndQuota(&usage, NULL);
- return usage;
- }
-
- void AddQuota(int64 quota_delta) {
- int64 quota;
- GetUsageAndQuota(NULL, &quota);
- quota_manager()->SetQuota(sandbox_file_system_.origin(),
- sandbox_file_system_.storage_type(),
- quota + quota_delta);
- }
-
- base::MessageLoop message_loop_;
- scoped_refptr<QuotaManager> quota_manager_;
- scoped_refptr<QuotaManagerProxy> quota_manager_proxy_;
-
- // Common temp base for nondestructive uses.
- base::ScopedTempDir base_;
-
- SandboxFileSystemTestHelper sandbox_file_system_;
-
- // For post-operation status.
- int status_;
- base::PlatformFileInfo info_;
- base::FilePath path_;
- std::vector<DirectoryEntry> entries_;
- scoped_refptr<ShareableFileReference> shareable_file_ref_;
-
- MockFileChangeObserver change_observer_;
- ChangeObserverList change_observers_;
-
- base::WeakPtrFactory<FileSystemOperationImplTest> weak_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(FileSystemOperationImplTest);
-};
-
-TEST_F(FileSystemOperationImplTest, TestMoveFailureSrcDoesntExist) {
- change_observer()->ResetCount();
- operation_runner()->Move(URLForPath("a"), URLForPath("b"),
- RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, status());
- EXPECT_TRUE(change_observer()->HasNoChange());
-}
-
-TEST_F(FileSystemOperationImplTest, TestMoveFailureContainsPath) {
- FileSystemURL src_dir(CreateDirectory("src"));
- FileSystemURL dest_dir(CreateDirectory("src/dest"));
-
- operation_runner()->Move(src_dir, dest_dir, RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::PLATFORM_FILE_ERROR_INVALID_OPERATION, status());
- EXPECT_TRUE(change_observer()->HasNoChange());
-}
-
-TEST_F(FileSystemOperationImplTest, TestMoveFailureSrcDirExistsDestFile) {
- // Src exists and is dir. Dest is a file.
- FileSystemURL src_dir(CreateDirectory("src"));
- FileSystemURL dest_dir(CreateDirectory("dest"));
- FileSystemURL dest_file(CreateFile("dest/file"));
-
- operation_runner()->Move(src_dir, dest_file, RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::PLATFORM_FILE_ERROR_INVALID_OPERATION, status());
- EXPECT_TRUE(change_observer()->HasNoChange());
-}
-
-TEST_F(FileSystemOperationImplTest,
- TestMoveFailureSrcFileExistsDestNonEmptyDir) {
- // Src exists and is a directory. Dest is a non-empty directory.
- FileSystemURL src_dir(CreateDirectory("src"));
- FileSystemURL dest_dir(CreateDirectory("dest"));
- FileSystemURL dest_file(CreateFile("dest/file"));
-
- operation_runner()->Move(src_dir, dest_dir, RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_EMPTY, status());
- EXPECT_TRUE(change_observer()->HasNoChange());
-}
-
-TEST_F(FileSystemOperationImplTest, TestMoveFailureSrcFileExistsDestDir) {
- // Src exists and is a file. Dest is a directory.
- FileSystemURL src_dir(CreateDirectory("src"));
- FileSystemURL src_file(CreateFile("src/file"));
- FileSystemURL dest_dir(CreateDirectory("dest"));
-
- operation_runner()->Move(src_file, dest_dir, RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::PLATFORM_FILE_ERROR_INVALID_OPERATION, status());
- EXPECT_TRUE(change_observer()->HasNoChange());
-}
-
-TEST_F(FileSystemOperationImplTest, TestMoveFailureDestParentDoesntExist) {
- // Dest. parent path does not exist.
- FileSystemURL src_dir(CreateDirectory("src"));
- operation_runner()->Move(src_dir, URLForPath("nonexistent/deset"),
- RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, status());
- EXPECT_TRUE(change_observer()->HasNoChange());
-}
-
-TEST_F(FileSystemOperationImplTest, TestMoveSuccessSrcFileAndOverwrite) {
- FileSystemURL src_file(CreateFile("src"));
- FileSystemURL dest_file(CreateFile("dest"));
-
- operation_runner()->Move(src_file, dest_file, RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::PLATFORM_FILE_OK, status());
- EXPECT_TRUE(FileExists("dest"));
-
- EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count());
- EXPECT_EQ(1, change_observer()->get_and_reset_remove_file_count());
- EXPECT_TRUE(change_observer()->HasNoChange());
-
- EXPECT_EQ(1, quota_manager_proxy()->notify_storage_accessed_count());
-}
-
-TEST_F(FileSystemOperationImplTest, TestMoveSuccessSrcFileAndNew) {
- FileSystemURL src_file(CreateFile("src"));
-
- operation_runner()->Move(src_file, URLForPath("new"), RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::PLATFORM_FILE_OK, status());
- EXPECT_TRUE(FileExists("new"));
-
- EXPECT_EQ(1, change_observer()->get_and_reset_create_file_from_count());
- EXPECT_EQ(1, change_observer()->get_and_reset_remove_file_count());
- EXPECT_TRUE(change_observer()->HasNoChange());
-}
-
-TEST_F(FileSystemOperationImplTest, TestMoveSuccessSrcDirAndOverwrite) {
- FileSystemURL src_dir(CreateDirectory("src"));
- FileSystemURL dest_dir(CreateDirectory("dest"));
-
- operation_runner()->Move(src_dir, dest_dir, RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::PLATFORM_FILE_OK, status());
- EXPECT_FALSE(DirectoryExists("src"));
-
- EXPECT_EQ(1, change_observer()->get_and_reset_create_directory_count());
- EXPECT_EQ(2, change_observer()->get_and_reset_remove_directory_count());
- EXPECT_TRUE(change_observer()->HasNoChange());
-
- // Make sure we've overwritten but not moved the source under the |dest_dir|.
- EXPECT_TRUE(DirectoryExists("dest"));
- EXPECT_FALSE(DirectoryExists("dest/src"));
-}
-
-TEST_F(FileSystemOperationImplTest, TestMoveSuccessSrcDirAndNew) {
- FileSystemURL src_dir(CreateDirectory("src"));
- FileSystemURL dest_dir(CreateDirectory("dest"));
-
- operation_runner()->Move(src_dir, URLForPath("dest/new"),
- RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::PLATFORM_FILE_OK, status());
- EXPECT_FALSE(DirectoryExists("src"));
- EXPECT_TRUE(DirectoryExists("dest/new"));
-
- EXPECT_EQ(1, change_observer()->get_and_reset_remove_directory_count());
- EXPECT_EQ(1, change_observer()->get_and_reset_create_directory_count());
- EXPECT_TRUE(change_observer()->HasNoChange());
-}
-
-TEST_F(FileSystemOperationImplTest, TestMoveSuccessSrcDirRecursive) {
- FileSystemURL src_dir(CreateDirectory("src"));
- CreateDirectory("src/dir");
- CreateFile("src/dir/sub");
-
- FileSystemURL dest_dir(CreateDirectory("dest"));
-
- operation_runner()->Move(src_dir, dest_dir, RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::PLATFORM_FILE_OK, status());
- EXPECT_TRUE(DirectoryExists("dest/dir"));
- EXPECT_TRUE(FileExists("dest/dir/sub"));
-
- EXPECT_EQ(3, change_observer()->get_and_reset_remove_directory_count());
- EXPECT_EQ(2, change_observer()->get_and_reset_create_directory_count());
- EXPECT_EQ(1, change_observer()->get_and_reset_remove_file_count());
- EXPECT_EQ(1, change_observer()->get_and_reset_create_file_from_count());
- EXPECT_TRUE(change_observer()->HasNoChange());
-}
-
-TEST_F(FileSystemOperationImplTest, TestCopyFailureSrcDoesntExist) {
- operation_runner()->Copy(URLForPath("a"), URLForPath("b"),
- FileSystemOperationRunner::CopyProgressCallback(),
- RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, status());
- EXPECT_TRUE(change_observer()->HasNoChange());
-}
-
-TEST_F(FileSystemOperationImplTest, TestCopyFailureContainsPath) {
- FileSystemURL src_dir(CreateDirectory("src"));
- FileSystemURL dest_dir(CreateDirectory("src/dir"));
-
- operation_runner()->Copy(src_dir, dest_dir,
- FileSystemOperationRunner::CopyProgressCallback(),
- RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::PLATFORM_FILE_ERROR_INVALID_OPERATION, status());
- EXPECT_TRUE(change_observer()->HasNoChange());
-}
-
-TEST_F(FileSystemOperationImplTest, TestCopyFailureSrcDirExistsDestFile) {
- // Src exists and is dir. Dest is a file.
- FileSystemURL src_dir(CreateDirectory("src"));
- FileSystemURL dest_dir(CreateDirectory("dest"));
- FileSystemURL dest_file(CreateFile("dest/file"));
-
- operation_runner()->Copy(src_dir, dest_file,
- FileSystemOperationRunner::CopyProgressCallback(),
- RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::PLATFORM_FILE_ERROR_INVALID_OPERATION, status());
- EXPECT_TRUE(change_observer()->HasNoChange());
-}
-
-TEST_F(FileSystemOperationImplTest,
- TestCopyFailureSrcFileExistsDestNonEmptyDir) {
- // Src exists and is a directory. Dest is a non-empty directory.
- FileSystemURL src_dir(CreateDirectory("src"));
- FileSystemURL dest_dir(CreateDirectory("dest"));
- FileSystemURL dest_file(CreateFile("dest/file"));
-
- operation_runner()->Copy(src_dir, dest_dir,
- FileSystemOperationRunner::CopyProgressCallback(),
- RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_EMPTY, status());
- EXPECT_TRUE(change_observer()->HasNoChange());
-}
-
-TEST_F(FileSystemOperationImplTest, TestCopyFailureSrcFileExistsDestDir) {
- // Src exists and is a file. Dest is a directory.
- FileSystemURL src_file(CreateFile("src"));
- FileSystemURL dest_dir(CreateDirectory("dest"));
-
- operation_runner()->Copy(src_file, dest_dir,
- FileSystemOperationRunner::CopyProgressCallback(),
- RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::PLATFORM_FILE_ERROR_INVALID_OPERATION, status());
- EXPECT_TRUE(change_observer()->HasNoChange());
-}
-
-TEST_F(FileSystemOperationImplTest, TestCopyFailureDestParentDoesntExist) {
- // Dest. parent path does not exist.
- FileSystemURL src_dir(CreateDirectory("src"));
-
- operation_runner()->Copy(src_dir, URLForPath("nonexistent/dest"),
- FileSystemOperationRunner::CopyProgressCallback(),
- RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, status());
- EXPECT_TRUE(change_observer()->HasNoChange());
-}
-
-TEST_F(FileSystemOperationImplTest, TestCopyFailureByQuota) {
- FileSystemURL src_dir(CreateDirectory("src"));
- FileSystemURL src_file(CreateFile("src/file"));
- FileSystemURL dest_dir(CreateDirectory("dest"));
- operation_runner()->Truncate(src_file, 6, RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::PLATFORM_FILE_OK, status());
- EXPECT_EQ(6, GetFileSize("src/file"));
-
- FileSystemURL dest_file(URLForPath("dest/file"));
- int64 dest_path_cost = ComputePathCost(dest_file);
- GrantQuotaForCurrentUsage();
- AddQuota(6 + dest_path_cost - 1);
-
- operation_runner()->Copy(src_file, dest_file,
- FileSystemOperationRunner::CopyProgressCallback(),
- RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::PLATFORM_FILE_ERROR_NO_SPACE, status());
- EXPECT_FALSE(FileExists("dest/file"));
-}
-
-TEST_F(FileSystemOperationImplTest, TestCopySuccessSrcFileAndOverwrite) {
- FileSystemURL src_file(CreateFile("src"));
- FileSystemURL dest_file(CreateFile("dest"));
-
- operation_runner()->Copy(src_file, dest_file,
- FileSystemOperationRunner::CopyProgressCallback(),
- RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::PLATFORM_FILE_OK, status());
- EXPECT_TRUE(FileExists("dest"));
- EXPECT_EQ(2, quota_manager_proxy()->notify_storage_accessed_count());
-
- EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count());
- EXPECT_TRUE(change_observer()->HasNoChange());
-}
-
-TEST_F(FileSystemOperationImplTest, TestCopySuccessSrcFileAndNew) {
- FileSystemURL src_file(CreateFile("src"));
-
- operation_runner()->Copy(src_file, URLForPath("new"),
- FileSystemOperationRunner::CopyProgressCallback(),
- RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::PLATFORM_FILE_OK, status());
- EXPECT_TRUE(FileExists("new"));
- EXPECT_EQ(2, quota_manager_proxy()->notify_storage_accessed_count());
-
- EXPECT_EQ(1, change_observer()->get_and_reset_create_file_from_count());
- EXPECT_TRUE(change_observer()->HasNoChange());
-}
-
-TEST_F(FileSystemOperationImplTest, TestCopySuccessSrcDirAndOverwrite) {
- FileSystemURL src_dir(CreateDirectory("src"));
- FileSystemURL dest_dir(CreateDirectory("dest"));
-
- operation_runner()->Copy(src_dir, dest_dir,
- FileSystemOperationRunner::CopyProgressCallback(),
- RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::PLATFORM_FILE_OK, status());
-
- // Make sure we've overwritten but not copied the source under the |dest_dir|.
- EXPECT_TRUE(DirectoryExists("dest"));
- EXPECT_FALSE(DirectoryExists("dest/src"));
- EXPECT_GE(quota_manager_proxy()->notify_storage_accessed_count(), 3);
-
- EXPECT_EQ(1, change_observer()->get_and_reset_remove_directory_count());
- EXPECT_EQ(1, change_observer()->get_and_reset_create_directory_count());
- EXPECT_TRUE(change_observer()->HasNoChange());
-}
-
-TEST_F(FileSystemOperationImplTest, TestCopySuccessSrcDirAndNew) {
- FileSystemURL src_dir(CreateDirectory("src"));
- FileSystemURL dest_dir_new(URLForPath("dest"));
-
- operation_runner()->Copy(src_dir, dest_dir_new,
- FileSystemOperationRunner::CopyProgressCallback(),
- RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::PLATFORM_FILE_OK, status());
- EXPECT_TRUE(DirectoryExists("dest"));
- EXPECT_GE(quota_manager_proxy()->notify_storage_accessed_count(), 2);
-
- EXPECT_EQ(1, change_observer()->get_and_reset_create_directory_count());
- EXPECT_TRUE(change_observer()->HasNoChange());
-}
-
-TEST_F(FileSystemOperationImplTest, TestCopySuccessSrcDirRecursive) {
- FileSystemURL src_dir(CreateDirectory("src"));
- CreateDirectory("src/dir");
- CreateFile("src/dir/sub");
-
- FileSystemURL dest_dir(CreateDirectory("dest"));
-
- operation_runner()->Copy(src_dir, dest_dir,
- FileSystemOperationRunner::CopyProgressCallback(),
- RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
-
- EXPECT_EQ(base::PLATFORM_FILE_OK, status());
- EXPECT_TRUE(DirectoryExists("dest/dir"));
- EXPECT_TRUE(FileExists("dest/dir/sub"));
-
- // For recursive copy we may record multiple read access.
- EXPECT_GE(quota_manager_proxy()->notify_storage_accessed_count(), 1);
-
- EXPECT_EQ(2, change_observer()->get_and_reset_create_directory_count());
- EXPECT_EQ(1, change_observer()->get_and_reset_remove_directory_count());
- EXPECT_EQ(1, change_observer()->get_and_reset_create_file_from_count());
- EXPECT_TRUE(change_observer()->HasNoChange());
-}
-
-TEST_F(FileSystemOperationImplTest, TestCopyInForeignFileSuccess) {
- base::FilePath src_local_disk_file_path;
- file_util::CreateTemporaryFile(&src_local_disk_file_path);
- const char test_data[] = "foo";
- int data_size = ARRAYSIZE_UNSAFE(test_data);
- file_util::WriteFile(src_local_disk_file_path, test_data, data_size);
-
- FileSystemURL dest_dir(CreateDirectory("dest"));
-
- int64 before_usage;
- GetUsageAndQuota(&before_usage, NULL);
-
- // Check that the file copied and corresponding usage increased.
- operation_runner()->CopyInForeignFile(src_local_disk_file_path,
- URLForPath("dest/file"),
- RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
-
- EXPECT_EQ(1, change_observer()->create_file_count());
- EXPECT_EQ(base::PLATFORM_FILE_OK, status());
- EXPECT_TRUE(FileExists("dest/file"));
- int64 after_usage;
- GetUsageAndQuota(&after_usage, NULL);
- EXPECT_GT(after_usage, before_usage);
-
- // Compare contents of src and copied file.
- char buffer[100];
- EXPECT_EQ(data_size, file_util::ReadFile(PlatformPath("dest/file"),
- buffer, data_size));
- for (int i = 0; i < data_size; ++i)
- EXPECT_EQ(test_data[i], buffer[i]);
-}
-
-TEST_F(FileSystemOperationImplTest, TestCopyInForeignFileFailureByQuota) {
- base::FilePath src_local_disk_file_path;
- file_util::CreateTemporaryFile(&src_local_disk_file_path);
- const char test_data[] = "foo";
- file_util::WriteFile(src_local_disk_file_path, test_data,
- ARRAYSIZE_UNSAFE(test_data));
-
- FileSystemURL dest_dir(CreateDirectory("dest"));
-
- GrantQuotaForCurrentUsage();
- operation_runner()->CopyInForeignFile(src_local_disk_file_path,
- URLForPath("dest/file"),
- RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
-
- EXPECT_FALSE(FileExists("dest/file"));
- EXPECT_EQ(0, change_observer()->create_file_count());
- EXPECT_EQ(base::PLATFORM_FILE_ERROR_NO_SPACE, status());
-}
-
-TEST_F(FileSystemOperationImplTest, TestCreateFileFailure) {
- // Already existing file and exclusive true.
- FileSystemURL file(CreateFile("file"));
- operation_runner()->CreateFile(file, true, RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::PLATFORM_FILE_ERROR_EXISTS, status());
- EXPECT_TRUE(change_observer()->HasNoChange());
-}
-
-TEST_F(FileSystemOperationImplTest, TestCreateFileSuccessFileExists) {
- // Already existing file and exclusive false.
- FileSystemURL file(CreateFile("file"));
- operation_runner()->CreateFile(file, false, RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::PLATFORM_FILE_OK, status());
- EXPECT_TRUE(FileExists("file"));
-
- // The file was already there; did nothing.
- EXPECT_TRUE(change_observer()->HasNoChange());
-}
-
-TEST_F(FileSystemOperationImplTest, TestCreateFileSuccessExclusive) {
- // File doesn't exist but exclusive is true.
- operation_runner()->CreateFile(URLForPath("new"), true,
- RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::PLATFORM_FILE_OK, status());
- EXPECT_TRUE(FileExists("new"));
- EXPECT_EQ(1, change_observer()->get_and_reset_create_file_count());
-}
-
-TEST_F(FileSystemOperationImplTest, TestCreateFileSuccessFileDoesntExist) {
- // Non existing file.
- operation_runner()->CreateFile(URLForPath("nonexistent"), false,
- RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::PLATFORM_FILE_OK, status());
- EXPECT_EQ(1, change_observer()->get_and_reset_create_file_count());
-}
-
-TEST_F(FileSystemOperationImplTest,
- TestCreateDirFailureDestParentDoesntExist) {
- // Dest. parent path does not exist.
- operation_runner()->CreateDirectory(
- URLForPath("nonexistent/dir"), false, false,
- RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, status());
- EXPECT_TRUE(change_observer()->HasNoChange());
-}
-
-TEST_F(FileSystemOperationImplTest, TestCreateDirFailureDirExists) {
- // Exclusive and dir existing at path.
- FileSystemURL dir(CreateDirectory("dir"));
- operation_runner()->CreateDirectory(dir, true, false,
- RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::PLATFORM_FILE_ERROR_EXISTS, status());
- EXPECT_TRUE(change_observer()->HasNoChange());
-}
-
-TEST_F(FileSystemOperationImplTest, TestCreateDirFailureFileExists) {
- // Exclusive true and file existing at path.
- FileSystemURL file(CreateFile("file"));
- operation_runner()->CreateDirectory(file, true, false,
- RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::PLATFORM_FILE_ERROR_EXISTS, status());
- EXPECT_TRUE(change_observer()->HasNoChange());
-}
-
-TEST_F(FileSystemOperationImplTest, TestCreateDirSuccess) {
- // Dir exists and exclusive is false.
- FileSystemURL dir(CreateDirectory("dir"));
- operation_runner()->CreateDirectory(dir, false, false,
- RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::PLATFORM_FILE_OK, status());
- EXPECT_TRUE(change_observer()->HasNoChange());
-
- // Dir doesn't exist.
- operation_runner()->CreateDirectory(URLForPath("new"), false, false,
- RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::PLATFORM_FILE_OK, status());
- EXPECT_TRUE(DirectoryExists("new"));
- EXPECT_EQ(1, change_observer()->get_and_reset_create_directory_count());
-}
-
-TEST_F(FileSystemOperationImplTest, TestCreateDirSuccessExclusive) {
- // Dir doesn't exist.
- operation_runner()->CreateDirectory(URLForPath("new"), true, false,
- RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::PLATFORM_FILE_OK, status());
- EXPECT_TRUE(DirectoryExists("new"));
- EXPECT_EQ(1, change_observer()->get_and_reset_create_directory_count());
- EXPECT_TRUE(change_observer()->HasNoChange());
-}
-
-TEST_F(FileSystemOperationImplTest, TestExistsAndMetadataFailure) {
- operation_runner()->GetMetadata(URLForPath("nonexistent"),
- RecordMetadataCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, status());
-
- operation_runner()->FileExists(URLForPath("nonexistent"),
- RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, status());
-
- operation_runner()->DirectoryExists(URLForPath("nonexistent"),
- RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, status());
- EXPECT_TRUE(change_observer()->HasNoChange());
-}
-
-TEST_F(FileSystemOperationImplTest, TestExistsAndMetadataSuccess) {
- FileSystemURL dir(CreateDirectory("dir"));
- FileSystemURL file(CreateFile("dir/file"));
- int read_access = 0;
-
- operation_runner()->DirectoryExists(dir, RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::PLATFORM_FILE_OK, status());
- ++read_access;
-
- operation_runner()->GetMetadata(dir, RecordMetadataCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::PLATFORM_FILE_OK, status());
- EXPECT_TRUE(info().is_directory);
- ++read_access;
-
- operation_runner()->FileExists(file, RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::PLATFORM_FILE_OK, status());
- ++read_access;
-
- operation_runner()->GetMetadata(file, RecordMetadataCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::PLATFORM_FILE_OK, status());
- EXPECT_FALSE(info().is_directory);
- ++read_access;
-
- EXPECT_EQ(read_access,
- quota_manager_proxy()->notify_storage_accessed_count());
- EXPECT_TRUE(change_observer()->HasNoChange());
-}
-
-TEST_F(FileSystemOperationImplTest, TestTypeMismatchErrors) {
- FileSystemURL dir(CreateDirectory("dir"));
- operation_runner()->FileExists(dir, RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_A_FILE, status());
-
- FileSystemURL file(CreateFile("file"));
- operation_runner()->DirectoryExists(file, RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY, status());
-}
-
-TEST_F(FileSystemOperationImplTest, TestReadDirFailure) {
- // Path doesn't exist
- operation_runner()->ReadDirectory(URLForPath("nonexistent"),
- RecordReadDirectoryCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, status());
-
- // File exists.
- FileSystemURL file(CreateFile("file"));
- operation_runner()->ReadDirectory(file, RecordReadDirectoryCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY, status());
- EXPECT_TRUE(change_observer()->HasNoChange());
-}
-
-TEST_F(FileSystemOperationImplTest, TestReadDirSuccess) {
- // parent_dir
- // | |
- // child_dir child_file
- // Verify reading parent_dir.
- FileSystemURL parent_dir(CreateDirectory("dir"));
- FileSystemURL child_dir(CreateDirectory("dir/child_dir"));
- FileSystemURL child_file(CreateFile("dir/child_file"));
-
- operation_runner()->ReadDirectory(parent_dir, RecordReadDirectoryCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::PLATFORM_FILE_OK, status());
- EXPECT_EQ(2u, entries().size());
-
- for (size_t i = 0; i < entries().size(); ++i) {
- if (entries()[i].is_directory)
- EXPECT_EQ(FILE_PATH_LITERAL("child_dir"), entries()[i].name);
- else
- EXPECT_EQ(FILE_PATH_LITERAL("child_file"), entries()[i].name);
- }
- EXPECT_EQ(1, quota_manager_proxy()->notify_storage_accessed_count());
- EXPECT_TRUE(change_observer()->HasNoChange());
-}
-
-TEST_F(FileSystemOperationImplTest, TestRemoveFailure) {
- // Path doesn't exist.
- operation_runner()->Remove(URLForPath("nonexistent"), false /* recursive */,
- RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, status());
-
- // It's an error to try to remove a non-empty directory if recursive flag
- // is false.
- // parent_dir
- // | |
- // child_dir child_file
- // Verify deleting parent_dir.
- FileSystemURL parent_dir(CreateDirectory("dir"));
- FileSystemURL child_dir(CreateDirectory("dir/child_dir"));
- FileSystemURL child_file(CreateFile("dir/child_file"));
-
- operation_runner()->Remove(parent_dir, false /* recursive */,
- RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_EMPTY, status());
- EXPECT_TRUE(change_observer()->HasNoChange());
-}
-
-TEST_F(FileSystemOperationImplTest, TestRemoveSuccess) {
- FileSystemURL empty_dir(CreateDirectory("empty_dir"));
- EXPECT_TRUE(DirectoryExists("empty_dir"));
- operation_runner()->Remove(empty_dir, false /* recursive */,
- RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::PLATFORM_FILE_OK, status());
- EXPECT_FALSE(DirectoryExists("empty_dir"));
-
- EXPECT_EQ(1, change_observer()->get_and_reset_remove_directory_count());
- EXPECT_TRUE(change_observer()->HasNoChange());
-}
-
-TEST_F(FileSystemOperationImplTest, TestRemoveSuccessRecursive) {
- // Removing a non-empty directory with recursive flag == true should be ok.
- // parent_dir
- // | |
- // child_dir child_files
- // |
- // child_files
- //
- // Verify deleting parent_dir.
- FileSystemURL parent_dir(CreateDirectory("dir"));
- for (int i = 0; i < 8; ++i)
- CreateFile(base::StringPrintf("dir/file-%d", i));
- FileSystemURL child_dir(CreateDirectory("dir/child_dir"));
- for (int i = 0; i < 8; ++i)
- CreateFile(base::StringPrintf("dir/child_dir/file-%d", i));
-
- operation_runner()->Remove(parent_dir, true /* recursive */,
- RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::PLATFORM_FILE_OK, status());
- EXPECT_FALSE(DirectoryExists("parent_dir"));
-
- EXPECT_EQ(2, change_observer()->get_and_reset_remove_directory_count());
- EXPECT_EQ(16, change_observer()->get_and_reset_remove_file_count());
- EXPECT_TRUE(change_observer()->HasNoChange());
-}
-
-TEST_F(FileSystemOperationImplTest, TestTruncate) {
- FileSystemURL file(CreateFile("file"));
- base::FilePath platform_path = PlatformPath("file");
-
- char test_data[] = "test data";
- int data_size = static_cast<int>(sizeof(test_data));
- EXPECT_EQ(data_size,
- file_util::WriteFile(platform_path, test_data, data_size));
-
- // Check that its length is the size of the data written.
- operation_runner()->GetMetadata(file, RecordMetadataCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::PLATFORM_FILE_OK, status());
- EXPECT_FALSE(info().is_directory);
- EXPECT_EQ(data_size, info().size);
-
- // Extend the file by truncating it.
- int length = 17;
- operation_runner()->Truncate(file, length, RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::PLATFORM_FILE_OK, status());
-
- EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count());
- EXPECT_TRUE(change_observer()->HasNoChange());
-
- // Check that its length is now 17 and that it's all zeroes after the test
- // data.
- EXPECT_EQ(length, GetFileSize("file"));
- char data[100];
- EXPECT_EQ(length, file_util::ReadFile(platform_path, data, length));
- for (int i = 0; i < length; ++i) {
- if (i < static_cast<int>(sizeof(test_data)))
- EXPECT_EQ(test_data[i], data[i]);
- else
- EXPECT_EQ(0, data[i]);
- }
-
- // Shorten the file by truncating it.
- length = 3;
- operation_runner()->Truncate(file, length, RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::PLATFORM_FILE_OK, status());
-
- EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count());
- EXPECT_TRUE(change_observer()->HasNoChange());
-
- // Check that its length is now 3 and that it contains only bits of test data.
- EXPECT_EQ(length, GetFileSize("file"));
- EXPECT_EQ(length, file_util::ReadFile(platform_path, data, length));
- for (int i = 0; i < length; ++i)
- EXPECT_EQ(test_data[i], data[i]);
-
- // Truncate is not a 'read' access. (Here expected access count is 1
- // since we made 1 read access for GetMetadata.)
- EXPECT_EQ(1, quota_manager_proxy()->notify_storage_accessed_count());
-}
-
-TEST_F(FileSystemOperationImplTest, TestTruncateFailureByQuota) {
- FileSystemURL dir(CreateDirectory("dir"));
- FileSystemURL file(CreateFile("dir/file"));
-
- GrantQuotaForCurrentUsage();
- AddQuota(10);
-
- operation_runner()->Truncate(file, 10, RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::PLATFORM_FILE_OK, status());
- EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count());
- EXPECT_TRUE(change_observer()->HasNoChange());
-
- EXPECT_EQ(10, GetFileSize("dir/file"));
-
- operation_runner()->Truncate(file, 11, RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::PLATFORM_FILE_ERROR_NO_SPACE, status());
- EXPECT_TRUE(change_observer()->HasNoChange());
-
- EXPECT_EQ(10, GetFileSize("dir/file"));
-}
-
-TEST_F(FileSystemOperationImplTest, TestTouchFile) {
- FileSystemURL file(CreateFile("file"));
- base::FilePath platform_path = PlatformPath("file");
-
- base::PlatformFileInfo info;
- EXPECT_TRUE(file_util::GetFileInfo(platform_path, &info));
- EXPECT_FALSE(info.is_directory);
- EXPECT_EQ(0, info.size);
- const base::Time last_modified = info.last_modified;
- const base::Time last_accessed = info.last_accessed;
-
- const base::Time new_modified_time = base::Time::UnixEpoch();
- const base::Time new_accessed_time = new_modified_time +
- base::TimeDelta::FromHours(77);
- ASSERT_NE(last_modified, new_modified_time);
- ASSERT_NE(last_accessed, new_accessed_time);
-
- operation_runner()->TouchFile(file, new_accessed_time, new_modified_time,
- RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::PLATFORM_FILE_OK, status());
- EXPECT_TRUE(change_observer()->HasNoChange());
-
- EXPECT_TRUE(file_util::GetFileInfo(platform_path, &info));
- // We compare as time_t here to lower our resolution, to avoid false
- // negatives caused by conversion to the local filesystem's native
- // representation and back.
- EXPECT_EQ(new_modified_time.ToTimeT(), info.last_modified.ToTimeT());
- EXPECT_EQ(new_accessed_time.ToTimeT(), info.last_accessed.ToTimeT());
-}
-
-TEST_F(FileSystemOperationImplTest, TestCreateSnapshotFile) {
- FileSystemURL dir(CreateDirectory("dir"));
-
- // Create a file for the testing.
- operation_runner()->DirectoryExists(dir, RecordStatusCallback());
- FileSystemURL file(CreateFile("dir/file"));
- operation_runner()->FileExists(file, RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::PLATFORM_FILE_OK, status());
-
- // See if we can get a 'snapshot' file info for the file.
- // Since FileSystemOperationImpl assumes the file exists in the local
- // directory it should just returns the same metadata and platform_path
- // as the file itself.
- operation_runner()->CreateSnapshotFile(file, RecordSnapshotFileCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::PLATFORM_FILE_OK, status());
- EXPECT_FALSE(info().is_directory);
- EXPECT_EQ(PlatformPath("dir/file"), path());
- EXPECT_TRUE(change_observer()->HasNoChange());
-
- // The FileSystemOpration implementation does not create a
- // shareable file reference.
- EXPECT_EQ(NULL, shareable_file_ref());
-}
-
-TEST_F(FileSystemOperationImplTest,
- TestMoveSuccessSrcDirRecursiveWithQuota) {
- FileSystemURL src(CreateDirectory("src"));
- int src_path_cost = GetUsage();
-
- FileSystemURL dest(CreateDirectory("dest"));
- FileSystemURL child_file1(CreateFile("src/file1"));
- FileSystemURL child_file2(CreateFile("src/file2"));
- FileSystemURL child_dir(CreateDirectory("src/dir"));
- FileSystemURL grandchild_file1(CreateFile("src/dir/file1"));
- FileSystemURL grandchild_file2(CreateFile("src/dir/file2"));
-
- int total_path_cost = GetUsage();
- EXPECT_EQ(0, GetDataSizeOnDisk());
-
- operation_runner()->Truncate(
- child_file1, 5000,
- base::Bind(&AssertFileErrorEq, FROM_HERE, base::PLATFORM_FILE_OK));
- operation_runner()->Truncate(
- child_file2, 400,
- base::Bind(&AssertFileErrorEq, FROM_HERE, base::PLATFORM_FILE_OK));
- operation_runner()->Truncate(
- grandchild_file1, 30,
- base::Bind(&AssertFileErrorEq, FROM_HERE, base::PLATFORM_FILE_OK));
- operation_runner()->Truncate(
- grandchild_file2, 2,
- base::Bind(&AssertFileErrorEq, FROM_HERE, base::PLATFORM_FILE_OK));
- base::RunLoop().RunUntilIdle();
-
- const int64 all_file_size = 5000 + 400 + 30 + 2;
- EXPECT_EQ(all_file_size, GetDataSizeOnDisk());
- EXPECT_EQ(all_file_size + total_path_cost, GetUsage());
-
- operation_runner()->Move(
- src, dest,
- base::Bind(&AssertFileErrorEq, FROM_HERE, base::PLATFORM_FILE_OK));
- base::RunLoop().RunUntilIdle();
-
- EXPECT_FALSE(DirectoryExists("src/dir"));
- EXPECT_FALSE(FileExists("src/dir/file2"));
- EXPECT_TRUE(DirectoryExists("dest/dir"));
- EXPECT_TRUE(FileExists("dest/dir/file2"));
-
- EXPECT_EQ(all_file_size, GetDataSizeOnDisk());
- EXPECT_EQ(all_file_size + total_path_cost - src_path_cost,
- GetUsage());
-}
-
-TEST_F(FileSystemOperationImplTest,
- TestCopySuccessSrcDirRecursiveWithQuota) {
- FileSystemURL src(CreateDirectory("src"));
- FileSystemURL dest1(CreateDirectory("dest1"));
- FileSystemURL dest2(CreateDirectory("dest2"));
-
- int64 usage = GetUsage();
- FileSystemURL child_file1(CreateFile("src/file1"));
- FileSystemURL child_file2(CreateFile("src/file2"));
- FileSystemURL child_dir(CreateDirectory("src/dir"));
- int64 child_path_cost = GetUsage() - usage;
- usage += child_path_cost;
-
- FileSystemURL grandchild_file1(CreateFile("src/dir/file1"));
- FileSystemURL grandchild_file2(CreateFile("src/dir/file2"));
- int64 total_path_cost = GetUsage();
- int64 grandchild_path_cost = total_path_cost - usage;
-
- EXPECT_EQ(0, GetDataSizeOnDisk());
-
- operation_runner()->Truncate(
- child_file1, 8000,
- base::Bind(&AssertFileErrorEq, FROM_HERE, base::PLATFORM_FILE_OK));
- operation_runner()->Truncate(
- child_file2, 700,
- base::Bind(&AssertFileErrorEq, FROM_HERE, base::PLATFORM_FILE_OK));
- operation_runner()->Truncate(
- grandchild_file1, 60,
- base::Bind(&AssertFileErrorEq, FROM_HERE, base::PLATFORM_FILE_OK));
- operation_runner()->Truncate(
- grandchild_file2, 5,
- base::Bind(&AssertFileErrorEq, FROM_HERE, base::PLATFORM_FILE_OK));
- base::RunLoop().RunUntilIdle();
-
- const int64 child_file_size = 8000 + 700;
- const int64 grandchild_file_size = 60 + 5;
- const int64 all_file_size = child_file_size + grandchild_file_size;
- int64 expected_usage = all_file_size + total_path_cost;
-
- usage = GetUsage();
- EXPECT_EQ(all_file_size, GetDataSizeOnDisk());
- EXPECT_EQ(expected_usage, usage);
-
- // Copy src to dest1.
- operation_runner()->Copy(
- src, dest1,
- FileSystemOperationRunner::CopyProgressCallback(),
- base::Bind(&AssertFileErrorEq, FROM_HERE, base::PLATFORM_FILE_OK));
- base::RunLoop().RunUntilIdle();
-
- expected_usage += all_file_size + child_path_cost + grandchild_path_cost;
- EXPECT_TRUE(DirectoryExists("src/dir"));
- EXPECT_TRUE(FileExists("src/dir/file2"));
- EXPECT_TRUE(DirectoryExists("dest1/dir"));
- EXPECT_TRUE(FileExists("dest1/dir/file2"));
-
- EXPECT_EQ(2 * all_file_size, GetDataSizeOnDisk());
- EXPECT_EQ(expected_usage, GetUsage());
-
- // Copy src/dir to dest2.
- operation_runner()->Copy(
- child_dir, dest2,
- FileSystemOperationRunner::CopyProgressCallback(),
- base::Bind(&AssertFileErrorEq, FROM_HERE, base::PLATFORM_FILE_OK));
- base::RunLoop().RunUntilIdle();
-
- expected_usage += grandchild_file_size + grandchild_path_cost;
- usage = GetUsage();
- EXPECT_EQ(2 * child_file_size + 3 * grandchild_file_size,
- GetDataSizeOnDisk());
- EXPECT_EQ(expected_usage, usage);
-}
-
-} // namespace fileapi
diff --git a/chromium/webkit/browser/fileapi/file_system_operation_impl_write_unittest.cc b/chromium/webkit/browser/fileapi/file_system_operation_impl_write_unittest.cc
deleted file mode 100644
index 7fb9aa4ae86..00000000000
--- a/chromium/webkit/browser/fileapi/file_system_operation_impl_write_unittest.cc
+++ /dev/null
@@ -1,329 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <vector>
-
-#include "base/files/scoped_temp_dir.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/memory/weak_ptr.h"
-#include "base/message_loop/message_loop_proxy.h"
-#include "base/run_loop.h"
-#include "net/url_request/url_request.h"
-#include "net/url_request/url_request_context.h"
-#include "net/url_request/url_request_job.h"
-#include "net/url_request/url_request_job_factory_impl.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "url/gurl.h"
-#include "webkit/browser/blob/blob_storage_context.h"
-#include "webkit/browser/blob/blob_url_request_job.h"
-#include "webkit/browser/blob/mock_blob_url_request_context.h"
-#include "webkit/browser/fileapi/file_system_context.h"
-#include "webkit/browser/fileapi/file_system_file_util.h"
-#include "webkit/browser/fileapi/file_system_operation_context.h"
-#include "webkit/browser/fileapi/file_system_operation_runner.h"
-#include "webkit/browser/fileapi/local_file_util.h"
-#include "webkit/browser/fileapi/mock_file_change_observer.h"
-#include "webkit/browser/fileapi/mock_file_system_context.h"
-#include "webkit/browser/fileapi/test_file_system_backend.h"
-#include "webkit/browser/quota/mock_quota_manager.h"
-#include "webkit/common/blob/blob_data.h"
-#include "webkit/common/fileapi/file_system_util.h"
-
-using webkit_blob::MockBlobURLRequestContext;
-using webkit_blob::ScopedTextBlob;
-
-namespace fileapi {
-
-namespace {
-
-const GURL kOrigin("http://example.com");
-const FileSystemType kFileSystemType = kFileSystemTypeTest;
-
-void AssertStatusEq(base::PlatformFileError expected,
- base::PlatformFileError actual) {
- ASSERT_EQ(expected, actual);
-}
-
-} // namespace
-
-class FileSystemOperationImplWriteTest
- : public testing::Test {
- public:
- FileSystemOperationImplWriteTest()
- : loop_(base::MessageLoop::TYPE_IO),
- status_(base::PLATFORM_FILE_OK),
- cancel_status_(base::PLATFORM_FILE_ERROR_FAILED),
- bytes_written_(0),
- complete_(false),
- weak_factory_(this) {
- change_observers_ = MockFileChangeObserver::CreateList(&change_observer_);
- }
-
- virtual void SetUp() {
- ASSERT_TRUE(dir_.CreateUniqueTempDir());
-
- quota_manager_ =
- new quota::MockQuotaManager(false /* is_incognito */,
- dir_.path(),
- base::MessageLoopProxy::current().get(),
- base::MessageLoopProxy::current().get(),
- NULL /* special storage policy */);
- virtual_path_ = base::FilePath(FILE_PATH_LITERAL("temporary file"));
-
- file_system_context_ = CreateFileSystemContextForTesting(
- quota_manager_->proxy(), dir_.path());
- url_request_context_.reset(
- new MockBlobURLRequestContext(file_system_context_.get()));
-
- file_system_context_->operation_runner()->CreateFile(
- URLForPath(virtual_path_), true /* exclusive */,
- base::Bind(&AssertStatusEq, base::PLATFORM_FILE_OK));
-
- static_cast<TestFileSystemBackend*>(
- file_system_context_->GetFileSystemBackend(kFileSystemType))
- ->AddFileChangeObserver(change_observer());
- }
-
- virtual void TearDown() {
- quota_manager_ = NULL;
- file_system_context_ = NULL;
- base::RunLoop().RunUntilIdle();
- }
-
- base::PlatformFileError status() const { return status_; }
- base::PlatformFileError cancel_status() const { return cancel_status_; }
- void add_bytes_written(int64 bytes, bool complete) {
- bytes_written_ += bytes;
- EXPECT_FALSE(complete_);
- complete_ = complete;
- }
- int64 bytes_written() const { return bytes_written_; }
- bool complete() const { return complete_; }
-
- protected:
- const ChangeObserverList& change_observers() const {
- return change_observers_;
- }
-
- MockFileChangeObserver* change_observer() {
- return &change_observer_;
- }
-
- FileSystemURL URLForPath(const base::FilePath& path) const {
- return file_system_context_->CreateCrackedFileSystemURL(
- kOrigin, kFileSystemType, path);
- }
-
- // Callback function for recording test results.
- FileSystemOperation::WriteCallback RecordWriteCallback() {
- return base::Bind(&FileSystemOperationImplWriteTest::DidWrite,
- weak_factory_.GetWeakPtr());
- }
-
- FileSystemOperation::StatusCallback RecordCancelCallback() {
- return base::Bind(&FileSystemOperationImplWriteTest::DidCancel,
- weak_factory_.GetWeakPtr());
- }
-
- void DidWrite(base::PlatformFileError status, int64 bytes, bool complete) {
- if (status == base::PLATFORM_FILE_OK) {
- add_bytes_written(bytes, complete);
- if (complete)
- base::MessageLoop::current()->Quit();
- } else {
- EXPECT_FALSE(complete_);
- EXPECT_EQ(status_, base::PLATFORM_FILE_OK);
- complete_ = true;
- status_ = status;
- if (base::MessageLoop::current()->is_running())
- base::MessageLoop::current()->Quit();
- }
- }
-
- void DidCancel(base::PlatformFileError status) {
- cancel_status_ = status;
- }
-
- const MockBlobURLRequestContext& url_request_context() const {
- return *url_request_context_;
- }
-
- scoped_refptr<FileSystemContext> file_system_context_;
- scoped_refptr<quota::MockQuotaManager> quota_manager_;
-
- base::MessageLoop loop_;
-
- base::ScopedTempDir dir_;
- base::FilePath virtual_path_;
-
- // For post-operation status.
- base::PlatformFileError status_;
- base::PlatformFileError cancel_status_;
- int64 bytes_written_;
- bool complete_;
-
- scoped_ptr<MockBlobURLRequestContext> url_request_context_;
-
- MockFileChangeObserver change_observer_;
- ChangeObserverList change_observers_;
-
- base::WeakPtrFactory<FileSystemOperationImplWriteTest> weak_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(FileSystemOperationImplWriteTest);
-};
-
-TEST_F(FileSystemOperationImplWriteTest, TestWriteSuccess) {
- ScopedTextBlob blob(url_request_context(),
- "blob-id:success",
- "Hello, world!\n");
- file_system_context_->operation_runner()->Write(
- &url_request_context(), URLForPath(virtual_path_),
- blob.GetBlobDataHandle(),
- 0, RecordWriteCallback());
- base::MessageLoop::current()->Run();
-
- EXPECT_EQ(14, bytes_written());
- EXPECT_EQ(base::PLATFORM_FILE_OK, status());
- EXPECT_TRUE(complete());
-
- EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count());
-}
-
-TEST_F(FileSystemOperationImplWriteTest, TestWriteZero) {
- ScopedTextBlob blob(url_request_context(), "blob_id:zero", "");
- file_system_context_->operation_runner()->Write(
- &url_request_context(), URLForPath(virtual_path_),
- blob.GetBlobDataHandle(), 0, RecordWriteCallback());
- base::MessageLoop::current()->Run();
-
- EXPECT_EQ(0, bytes_written());
- EXPECT_EQ(base::PLATFORM_FILE_OK, status());
- EXPECT_TRUE(complete());
-
- EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count());
-}
-
-
-TEST_F(FileSystemOperationImplWriteTest, TestWriteInvalidBlobUrl) {
- scoped_ptr<webkit_blob::BlobDataHandle> null_handle;
- file_system_context_->operation_runner()->Write(
- &url_request_context(), URLForPath(virtual_path_),
- null_handle.Pass(), 0, RecordWriteCallback());
- base::MessageLoop::current()->Run();
-
- EXPECT_EQ(0, bytes_written());
- EXPECT_EQ(base::PLATFORM_FILE_ERROR_FAILED, status());
- EXPECT_TRUE(complete());
-
- EXPECT_EQ(0, change_observer()->get_and_reset_modify_file_count());
-}
-
-TEST_F(FileSystemOperationImplWriteTest, TestWriteInvalidFile) {
- ScopedTextBlob blob(url_request_context(), "blob_id:writeinvalidfile",
- "It\'ll not be written.");
- file_system_context_->operation_runner()->Write(
- &url_request_context(),
- URLForPath(base::FilePath(FILE_PATH_LITERAL("nonexist"))),
- blob.GetBlobDataHandle(), 0, RecordWriteCallback());
- base::MessageLoop::current()->Run();
-
- EXPECT_EQ(0, bytes_written());
- EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, status());
- EXPECT_TRUE(complete());
-
- EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count());
-}
-
-TEST_F(FileSystemOperationImplWriteTest, TestWriteDir) {
- base::FilePath virtual_dir_path(FILE_PATH_LITERAL("d"));
- file_system_context_->operation_runner()->CreateDirectory(
- URLForPath(virtual_dir_path),
- true /* exclusive */, false /* recursive */,
- base::Bind(&AssertStatusEq, base::PLATFORM_FILE_OK));
-
- ScopedTextBlob blob(url_request_context(), "blob:writedir",
- "It\'ll not be written, too.");
- file_system_context_->operation_runner()->Write(
- &url_request_context(), URLForPath(virtual_dir_path),
- blob.GetBlobDataHandle(), 0, RecordWriteCallback());
- base::MessageLoop::current()->Run();
-
- EXPECT_EQ(0, bytes_written());
- // TODO(kinuko): This error code is platform- or fileutil- dependent
- // right now. Make it return PLATFORM_FILE_ERROR_NOT_A_FILE in every case.
- EXPECT_TRUE(status() == base::PLATFORM_FILE_ERROR_NOT_A_FILE ||
- status() == base::PLATFORM_FILE_ERROR_ACCESS_DENIED ||
- status() == base::PLATFORM_FILE_ERROR_FAILED);
- EXPECT_TRUE(complete());
-
- EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count());
-}
-
-TEST_F(FileSystemOperationImplWriteTest, TestWriteFailureByQuota) {
- ScopedTextBlob blob(url_request_context(), "blob:success",
- "Hello, world!\n");
- quota_manager_->SetQuota(
- kOrigin, FileSystemTypeToQuotaStorageType(kFileSystemType), 10);
- file_system_context_->operation_runner()->Write(
- &url_request_context(), URLForPath(virtual_path_),
- blob.GetBlobDataHandle(), 0, RecordWriteCallback());
- base::MessageLoop::current()->Run();
-
- EXPECT_EQ(10, bytes_written());
- EXPECT_EQ(base::PLATFORM_FILE_ERROR_NO_SPACE, status());
- EXPECT_TRUE(complete());
-
- EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count());
-}
-
-TEST_F(FileSystemOperationImplWriteTest, TestImmediateCancelSuccessfulWrite) {
- ScopedTextBlob blob(url_request_context(), "blob:success",
- "Hello, world!\n");
- FileSystemOperationRunner::OperationID id =
- file_system_context_->operation_runner()->Write(
- &url_request_context(), URLForPath(virtual_path_),
- blob.GetBlobDataHandle(), 0, RecordWriteCallback());
- file_system_context_->operation_runner()->Cancel(id, RecordCancelCallback());
- // We use RunAllPendings() instead of Run() here, because we won't dispatch
- // callbacks after Cancel() is issued (so no chance to Quit) nor do we need
- // to run another write cycle.
- base::RunLoop().RunUntilIdle();
-
- // Issued Cancel() before receiving any response from Write(),
- // so nothing should have happen.
- EXPECT_EQ(0, bytes_written());
- EXPECT_EQ(base::PLATFORM_FILE_ERROR_ABORT, status());
- EXPECT_EQ(base::PLATFORM_FILE_OK, cancel_status());
- EXPECT_TRUE(complete());
-
- EXPECT_EQ(0, change_observer()->get_and_reset_modify_file_count());
-}
-
-TEST_F(FileSystemOperationImplWriteTest, TestImmediateCancelFailingWrite) {
- ScopedTextBlob blob(url_request_context(), "blob:writeinvalidfile",
- "It\'ll not be written.");
- FileSystemOperationRunner::OperationID id =
- file_system_context_->operation_runner()->Write(
- &url_request_context(),
- URLForPath(base::FilePath(FILE_PATH_LITERAL("nonexist"))),
- blob.GetBlobDataHandle(), 0, RecordWriteCallback());
- file_system_context_->operation_runner()->Cancel(id, RecordCancelCallback());
- // We use RunAllPendings() instead of Run() here, because we won't dispatch
- // callbacks after Cancel() is issued (so no chance to Quit) nor do we need
- // to run another write cycle.
- base::RunLoop().RunUntilIdle();
-
- // Issued Cancel() before receiving any response from Write(),
- // so nothing should have happen.
- EXPECT_EQ(0, bytes_written());
- EXPECT_EQ(base::PLATFORM_FILE_ERROR_ABORT, status());
- EXPECT_EQ(base::PLATFORM_FILE_OK, cancel_status());
- EXPECT_TRUE(complete());
-
- EXPECT_EQ(0, change_observer()->get_and_reset_modify_file_count());
-}
-
-// TODO(ericu,dmikurube,kinuko): Add more tests for cancel cases.
-
-} // namespace fileapi
diff --git a/chromium/webkit/browser/fileapi/file_system_operation_runner.cc b/chromium/webkit/browser/fileapi/file_system_operation_runner.cc
index 5a31ecc44ec..d552a783193 100644
--- a/chromium/webkit/browser/fileapi/file_system_operation_runner.cc
+++ b/chromium/webkit/browser/fileapi/file_system_operation_runner.cc
@@ -86,6 +86,7 @@ OperationID FileSystemOperationRunner::CreateDirectory(
OperationID FileSystemOperationRunner::Copy(
const FileSystemURL& src_url,
const FileSystemURL& dest_url,
+ CopyOrMoveOption option,
const CopyProgressCallback& progress_callback,
const StatusCallback& callback) {
base::PlatformFileError error = base::PLATFORM_FILE_OK;
@@ -100,7 +101,7 @@ OperationID FileSystemOperationRunner::Copy(
PrepareForWrite(handle.id, dest_url);
PrepareForRead(handle.id, src_url);
operation->Copy(
- src_url, dest_url,
+ src_url, dest_url, option,
progress_callback.is_null() ?
CopyProgressCallback() :
base::Bind(&FileSystemOperationRunner::OnCopyProgress, AsWeakPtr(),
@@ -113,6 +114,7 @@ OperationID FileSystemOperationRunner::Copy(
OperationID FileSystemOperationRunner::Move(
const FileSystemURL& src_url,
const FileSystemURL& dest_url,
+ CopyOrMoveOption option,
const StatusCallback& callback) {
base::PlatformFileError error = base::PLATFORM_FILE_OK;
FileSystemOperation* operation =
@@ -126,7 +128,7 @@ OperationID FileSystemOperationRunner::Move(
PrepareForWrite(handle.id, dest_url);
PrepareForWrite(handle.id, src_url);
operation->Move(
- src_url, dest_url,
+ src_url, dest_url, option,
base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(),
handle, callback));
return handle.id;
@@ -337,7 +339,6 @@ OperationID FileSystemOperationRunner::TouchFile(
OperationID FileSystemOperationRunner::OpenFile(
const FileSystemURL& url,
int file_flags,
- base::ProcessHandle peer_handle,
const OpenFileCallback& callback) {
base::PlatformFileError error = base::PLATFORM_FILE_OK;
FileSystemOperation* operation =
@@ -346,7 +347,7 @@ OperationID FileSystemOperationRunner::OpenFile(
OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr());
if (!operation) {
DidOpenFile(handle, callback, error, base::kInvalidPlatformFileValue,
- base::Closure(), base::ProcessHandle());
+ base::Closure());
return handle.id;
}
if (file_flags &
@@ -360,7 +361,7 @@ OperationID FileSystemOperationRunner::OpenFile(
PrepareForRead(handle.id, url);
}
operation->OpenFile(
- url, file_flags, peer_handle,
+ url, file_flags,
base::Bind(&FileSystemOperationRunner::DidOpenFile, AsWeakPtr(),
handle, callback));
return handle.id;
@@ -448,6 +449,7 @@ OperationID FileSystemOperationRunner::RemoveDirectory(
OperationID FileSystemOperationRunner::CopyFileLocal(
const FileSystemURL& src_url,
const FileSystemURL& dest_url,
+ CopyOrMoveOption option,
const CopyFileProgressCallback& progress_callback,
const StatusCallback& callback) {
base::PlatformFileError error = base::PLATFORM_FILE_OK;
@@ -460,7 +462,7 @@ OperationID FileSystemOperationRunner::CopyFileLocal(
return handle.id;
}
operation->CopyFileLocal(
- src_url, dest_url, progress_callback,
+ src_url, dest_url, option, progress_callback,
base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(),
handle, callback));
return handle.id;
@@ -469,6 +471,7 @@ OperationID FileSystemOperationRunner::CopyFileLocal(
OperationID FileSystemOperationRunner::MoveFileLocal(
const FileSystemURL& src_url,
const FileSystemURL& dest_url,
+ CopyOrMoveOption option,
const StatusCallback& callback) {
base::PlatformFileError error = base::PLATFORM_FILE_OK;
FileSystemOperation* operation =
@@ -480,7 +483,7 @@ OperationID FileSystemOperationRunner::MoveFileLocal(
return handle.id;
}
operation->MoveFileLocal(
- src_url, dest_url,
+ src_url, dest_url, option,
base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(),
handle, callback));
return handle.id;
@@ -490,9 +493,9 @@ base::PlatformFileError FileSystemOperationRunner::SyncGetPlatformPath(
const FileSystemURL& url,
base::FilePath* platform_path) {
base::PlatformFileError error = base::PLATFORM_FILE_OK;
- FileSystemOperation* operation =
- file_system_context_->CreateFileSystemOperation(url, &error);
- if (!operation)
+ scoped_ptr<FileSystemOperation> operation(
+ file_system_context_->CreateFileSystemOperation(url, &error));
+ if (!operation.get())
return error;
return operation->SyncGetPlatformPath(url, platform_path);
}
@@ -574,17 +577,16 @@ void FileSystemOperationRunner::DidOpenFile(
const OpenFileCallback& callback,
base::PlatformFileError rv,
base::PlatformFile file,
- const base::Closure& on_close_callback,
- base::ProcessHandle peer_handle) {
+ const base::Closure& on_close_callback) {
if (handle.scope) {
finished_operations_.insert(handle.id);
base::MessageLoopProxy::current()->PostTask(
FROM_HERE, base::Bind(&FileSystemOperationRunner::DidOpenFile,
AsWeakPtr(), handle, callback, rv, file,
- on_close_callback, peer_handle));
+ on_close_callback));
return;
}
- callback.Run(rv, file, on_close_callback, peer_handle);
+ callback.Run(rv, file, on_close_callback);
FinishOperation(handle.id);
}
diff --git a/chromium/webkit/browser/fileapi/file_system_operation_runner.h b/chromium/webkit/browser/fileapi/file_system_operation_runner.h
index ea93f38e1fc..fba6b1cab96 100644
--- a/chromium/webkit/browser/fileapi/file_system_operation_runner.h
+++ b/chromium/webkit/browser/fileapi/file_system_operation_runner.h
@@ -6,6 +6,8 @@
#define WEBKIT_BROWSER_FILEAPI_FILE_SYSTEM_OPERATION_RUNNER_H_
#include <map>
+#include <set>
+#include <vector>
#include "base/basictypes.h"
#include "base/id_map.h"
@@ -44,6 +46,7 @@ class WEBKIT_STORAGE_BROWSER_EXPORT FileSystemOperationRunner
typedef FileSystemOperation::CopyProgressCallback CopyProgressCallback;
typedef FileSystemOperation::CopyFileProgressCallback
CopyFileProgressCallback;
+ typedef FileSystemOperation::CopyOrMoveOption CopyOrMoveOption;
typedef int OperationID;
@@ -67,16 +70,20 @@ class WEBKIT_STORAGE_BROWSER_EXPORT FileSystemOperationRunner
// |src_url| is a directory, the contents of |src_url| are copied to
// |dest_url| recursively. A new file or directory is created at
// |dest_url| as needed.
- // For |progress_callback|, see file_system_operation.h for details.
+ // For |option| and |progress_callback|, see file_system_operation.h for
+ // details.
OperationID Copy(const FileSystemURL& src_url,
const FileSystemURL& dest_url,
+ CopyOrMoveOption option,
const CopyProgressCallback& progress_callback,
const StatusCallback& callback);
// Moves a file or directory from |src_url| to |dest_url|. A new file
// or directory is created at |dest_url| as needed.
+ // For |option|, see file_system_operation.h for details.
OperationID Move(const FileSystemURL& src_url,
const FileSystemURL& dest_url,
+ CopyOrMoveOption option,
const StatusCallback& callback);
// Checks if a directory is present at |url|.
@@ -138,7 +145,6 @@ class WEBKIT_STORAGE_BROWSER_EXPORT FileSystemOperationRunner
// This function is used only by Pepper as of writing.
OperationID OpenFile(const FileSystemURL& url,
int file_flags,
- base::ProcessHandle peer_handle,
const OpenFileCallback& callback);
// Creates a local snapshot file for a given |url| and returns the
@@ -188,7 +194,8 @@ class WEBKIT_STORAGE_BROWSER_EXPORT FileSystemOperationRunner
// Copies a file from |src_url| to |dest_url|.
// This must be called for files that belong to the same filesystem
// (i.e. type() and origin() of the |src_url| and |dest_url| must match).
- // For |progress_callback|, see file_system_operation.h for details.
+ // For |option| and |progress_callback|, see file_system_operation.h for
+ // details.
//
// This returns:
// - PLATFORM_FILE_ERROR_NOT_FOUND if |src_url|
@@ -201,12 +208,14 @@ class WEBKIT_STORAGE_BROWSER_EXPORT FileSystemOperationRunner
//
OperationID CopyFileLocal(const FileSystemURL& src_url,
const FileSystemURL& dest_url,
+ CopyOrMoveOption option,
const CopyFileProgressCallback& progress_callback,
const StatusCallback& callback);
// Moves a local file from |src_url| to |dest_url|.
// This must be called for files that belong to the same filesystem
// (i.e. type() and origin() of the |src_url| and |dest_url| must match).
+ // For |option|, see file_system_operation.h for details.
//
// This returns:
// - PLATFORM_FILE_ERROR_NOT_FOUND if |src_url|
@@ -219,6 +228,7 @@ class WEBKIT_STORAGE_BROWSER_EXPORT FileSystemOperationRunner
//
OperationID MoveFileLocal(const FileSystemURL& src_url,
const FileSystemURL& dest_url,
+ CopyOrMoveOption option,
const StatusCallback& callback);
// This is called only by pepper plugin as of writing to synchronously get
@@ -263,8 +273,7 @@ class WEBKIT_STORAGE_BROWSER_EXPORT FileSystemOperationRunner
const OpenFileCallback& callback,
base::PlatformFileError rv,
base::PlatformFile file,
- const base::Closure& on_close_callback,
- base::ProcessHandle peer_handle);
+ const base::Closure& on_close_callback);
void DidCreateSnapshot(
const OperationHandle& handle,
const SnapshotFileCallback& callback,
diff --git a/chromium/webkit/browser/fileapi/file_system_operation_runner_unittest.cc b/chromium/webkit/browser/fileapi/file_system_operation_runner_unittest.cc
deleted file mode 100644
index 086c9999ad5..00000000000
--- a/chromium/webkit/browser/fileapi/file_system_operation_runner_unittest.cc
+++ /dev/null
@@ -1,162 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/basictypes.h"
-#include "base/files/file_path.h"
-#include "base/files/scoped_temp_dir.h"
-#include "base/platform_file.h"
-#include "base/run_loop.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "webkit/browser/fileapi/file_system_context.h"
-#include "webkit/browser/fileapi/file_system_operation_runner.h"
-#include "webkit/browser/fileapi/mock_file_system_context.h"
-
-namespace fileapi {
-
-void GetStatus(bool* done,
- base::PlatformFileError *status_out,
- base::PlatformFileError status) {
- ASSERT_FALSE(*done);
- *done = true;
- *status_out = status;
-}
-
-void GetCancelStatus(bool* operation_done,
- bool* cancel_done,
- base::PlatformFileError *status_out,
- base::PlatformFileError status) {
- // Cancel callback must be always called after the operation's callback.
- ASSERT_TRUE(*operation_done);
- ASSERT_FALSE(*cancel_done);
- *cancel_done = true;
- *status_out = status;
-}
-
-class FileSystemOperationRunnerTest : public testing::Test {
- protected:
- FileSystemOperationRunnerTest() {}
- virtual ~FileSystemOperationRunnerTest() {}
-
- virtual void SetUp() OVERRIDE {
- ASSERT_TRUE(base_.CreateUniqueTempDir());
- base::FilePath base_dir = base_.path();
- file_system_context_ =
- CreateFileSystemContextForTesting(NULL, base_dir);
- }
-
- virtual void TearDown() OVERRIDE {
- file_system_context_ = NULL;
- base::RunLoop().RunUntilIdle();
- }
-
- FileSystemURL URL(const std::string& path) {
- return file_system_context_->CreateCrackedFileSystemURL(
- GURL("http://example.com"), kFileSystemTypeTemporary,
- base::FilePath::FromUTF8Unsafe(path));
- }
-
- FileSystemOperationRunner* operation_runner() {
- return file_system_context_->operation_runner();
- }
-
- private:
- base::ScopedTempDir base_;
- base::MessageLoop message_loop_;
- scoped_refptr<FileSystemContext> file_system_context_;
-
- DISALLOW_COPY_AND_ASSIGN(FileSystemOperationRunnerTest);
-};
-
-TEST_F(FileSystemOperationRunnerTest, NotFoundError) {
- bool done = false;
- base::PlatformFileError status = base::PLATFORM_FILE_ERROR_FAILED;
-
- // Regular NOT_FOUND error, which is called asynchronously.
- operation_runner()->Truncate(URL("foo"), 0,
- base::Bind(&GetStatus, &done, &status));
- ASSERT_FALSE(done);
- base::RunLoop().RunUntilIdle();
- ASSERT_TRUE(done);
- ASSERT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, status);
-}
-
-TEST_F(FileSystemOperationRunnerTest, InvalidURLError) {
- bool done = false;
- base::PlatformFileError status = base::PLATFORM_FILE_ERROR_FAILED;
-
- // Invalid URL error, which calls DidFinish synchronously.
- operation_runner()->Truncate(FileSystemURL(), 0,
- base::Bind(&GetStatus, &done, &status));
- // The error call back shouldn't be fired synchronously.
- ASSERT_FALSE(done);
-
- base::RunLoop().RunUntilIdle();
- ASSERT_TRUE(done);
- ASSERT_EQ(base::PLATFORM_FILE_ERROR_INVALID_URL, status);
-}
-
-TEST_F(FileSystemOperationRunnerTest, NotFoundErrorAndCancel) {
- bool done = false;
- bool cancel_done = false;
- base::PlatformFileError status = base::PLATFORM_FILE_ERROR_FAILED;
- base::PlatformFileError cancel_status = base::PLATFORM_FILE_ERROR_FAILED;
-
- // Call Truncate with non-existent URL, and try to cancel it immediately
- // after that (before its callback is fired).
- FileSystemOperationRunner::OperationID id =
- operation_runner()->Truncate(URL("foo"), 0,
- base::Bind(&GetStatus, &done, &status));
- operation_runner()->Cancel(id, base::Bind(&GetCancelStatus,
- &done, &cancel_done,
- &cancel_status));
-
- ASSERT_FALSE(done);
- ASSERT_FALSE(cancel_done);
- base::RunLoop().RunUntilIdle();
-
- ASSERT_TRUE(done);
- ASSERT_TRUE(cancel_done);
- ASSERT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, status);
- ASSERT_EQ(base::PLATFORM_FILE_ERROR_INVALID_OPERATION, cancel_status);
-}
-
-TEST_F(FileSystemOperationRunnerTest, InvalidURLErrorAndCancel) {
- bool done = false;
- bool cancel_done = false;
- base::PlatformFileError status = base::PLATFORM_FILE_ERROR_FAILED;
- base::PlatformFileError cancel_status = base::PLATFORM_FILE_ERROR_FAILED;
-
- // Call Truncate with invalid URL, and try to cancel it immediately
- // after that (before its callback is fired).
- FileSystemOperationRunner::OperationID id =
- operation_runner()->Truncate(FileSystemURL(), 0,
- base::Bind(&GetStatus, &done, &status));
- operation_runner()->Cancel(id, base::Bind(&GetCancelStatus,
- &done, &cancel_done,
- &cancel_status));
-
- ASSERT_FALSE(done);
- ASSERT_FALSE(cancel_done);
- base::RunLoop().RunUntilIdle();
-
- ASSERT_TRUE(done);
- ASSERT_TRUE(cancel_done);
- ASSERT_EQ(base::PLATFORM_FILE_ERROR_INVALID_URL, status);
- ASSERT_EQ(base::PLATFORM_FILE_ERROR_INVALID_OPERATION, cancel_status);
-}
-
-TEST_F(FileSystemOperationRunnerTest, CancelWithInvalidId) {
- const FileSystemOperationRunner::OperationID kInvalidId = -1;
- bool done = true; // The operation is not running.
- bool cancel_done = false;
- base::PlatformFileError cancel_status = base::PLATFORM_FILE_ERROR_FAILED;
- operation_runner()->Cancel(kInvalidId, base::Bind(&GetCancelStatus,
- &done, &cancel_done,
- &cancel_status));
-
- ASSERT_TRUE(cancel_done);
- ASSERT_EQ(base::PLATFORM_FILE_ERROR_INVALID_OPERATION, cancel_status);
-}
-
-} // namespace fileapi
diff --git a/chromium/webkit/browser/fileapi/file_system_quota_client_unittest.cc b/chromium/webkit/browser/fileapi/file_system_quota_client_unittest.cc
deleted file mode 100644
index 1a9121c1a7a..00000000000
--- a/chromium/webkit/browser/fileapi/file_system_quota_client_unittest.cc
+++ /dev/null
@@ -1,561 +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 "base/basictypes.h"
-#include "base/bind.h"
-#include "base/file_util.h"
-#include "base/files/scoped_temp_dir.h"
-#include "base/message_loop/message_loop_proxy.h"
-#include "base/platform_file.h"
-#include "base/run_loop.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "url/gurl.h"
-#include "webkit/browser/fileapi/async_file_test_helper.h"
-#include "webkit/browser/fileapi/file_system_context.h"
-#include "webkit/browser/fileapi/file_system_quota_client.h"
-#include "webkit/browser/fileapi/file_system_usage_cache.h"
-#include "webkit/browser/fileapi/mock_file_system_context.h"
-#include "webkit/browser/fileapi/obfuscated_file_util.h"
-#include "webkit/common/fileapi/file_system_types.h"
-#include "webkit/common/fileapi/file_system_util.h"
-#include "webkit/common/quota/quota_types.h"
-
-namespace fileapi {
-namespace {
-
-const char kDummyURL1[] = "http://www.dummy.org";
-const char kDummyURL2[] = "http://www.example.com";
-const char kDummyURL3[] = "http://www.bleh";
-
-// Declared to shorten the variable names.
-const quota::StorageType kTemporary = quota::kStorageTypeTemporary;
-const quota::StorageType kPersistent = quota::kStorageTypePersistent;
-
-} // namespace
-
-class FileSystemQuotaClientTest : public testing::Test {
- public:
- FileSystemQuotaClientTest()
- : weak_factory_(this),
- additional_callback_count_(0),
- deletion_status_(quota::kQuotaStatusUnknown) {
- }
-
- virtual void SetUp() {
- ASSERT_TRUE(data_dir_.CreateUniqueTempDir());
- file_system_context_ = CreateFileSystemContextForTesting(
- NULL, data_dir_.path());
- }
-
- struct TestFile {
- bool isDirectory;
- const char* name;
- int64 size;
- const char* origin_url;
- quota::StorageType type;
- };
-
- protected:
- FileSystemQuotaClient* NewQuotaClient(bool is_incognito) {
- return new FileSystemQuotaClient(file_system_context_.get(), is_incognito);
- }
-
- void GetOriginUsageAsync(FileSystemQuotaClient* quota_client,
- const std::string& origin_url,
- quota::StorageType type) {
- quota_client->GetOriginUsage(
- GURL(origin_url), type,
- base::Bind(&FileSystemQuotaClientTest::OnGetUsage,
- weak_factory_.GetWeakPtr()));
- }
-
- int64 GetOriginUsage(FileSystemQuotaClient* quota_client,
- const std::string& origin_url,
- quota::StorageType type) {
- GetOriginUsageAsync(quota_client, origin_url, type);
- base::RunLoop().RunUntilIdle();
- return usage_;
- }
-
- const std::set<GURL>& GetOriginsForType(FileSystemQuotaClient* quota_client,
- quota::StorageType type) {
- origins_.clear();
- quota_client->GetOriginsForType(
- type,
- base::Bind(&FileSystemQuotaClientTest::OnGetOrigins,
- weak_factory_.GetWeakPtr()));
- base::RunLoop().RunUntilIdle();
- return origins_;
- }
-
- const std::set<GURL>& GetOriginsForHost(FileSystemQuotaClient* quota_client,
- quota::StorageType type,
- const std::string& host) {
- origins_.clear();
- quota_client->GetOriginsForHost(
- type, host,
- base::Bind(&FileSystemQuotaClientTest::OnGetOrigins,
- weak_factory_.GetWeakPtr()));
- base::RunLoop().RunUntilIdle();
- return origins_;
- }
-
- void RunAdditionalOriginUsageTask(FileSystemQuotaClient* quota_client,
- const std::string& origin_url,
- quota::StorageType type) {
- quota_client->GetOriginUsage(
- GURL(origin_url), type,
- base::Bind(&FileSystemQuotaClientTest::OnGetAdditionalUsage,
- weak_factory_.GetWeakPtr()));
- }
-
- bool CreateFileSystemDirectory(const base::FilePath& file_path,
- const std::string& origin_url,
- quota::StorageType storage_type) {
- FileSystemType type = QuotaStorageTypeToFileSystemType(storage_type);
- FileSystemURL url = file_system_context_->CreateCrackedFileSystemURL(
- GURL(origin_url), type, file_path);
-
- base::PlatformFileError result =
- AsyncFileTestHelper::CreateDirectory(file_system_context_, url);
- return result == base::PLATFORM_FILE_OK;
- }
-
- bool CreateFileSystemFile(const base::FilePath& file_path,
- int64 file_size,
- const std::string& origin_url,
- quota::StorageType storage_type) {
- if (file_path.empty())
- return false;
-
- FileSystemType type = QuotaStorageTypeToFileSystemType(storage_type);
- FileSystemURL url = file_system_context_->CreateCrackedFileSystemURL(
- GURL(origin_url), type, file_path);
-
- base::PlatformFileError result =
- AsyncFileTestHelper::CreateFile(file_system_context_, url);
- if (result != base::PLATFORM_FILE_OK)
- return false;
-
- result = AsyncFileTestHelper::TruncateFile(
- file_system_context_, url, file_size);
- return result == base::PLATFORM_FILE_OK;
- }
-
- void InitializeOriginFiles(FileSystemQuotaClient* quota_client,
- const TestFile* files,
- int num_files) {
- for (int i = 0; i < num_files; i++) {
- base::FilePath path = base::FilePath().AppendASCII(files[i].name);
- if (files[i].isDirectory) {
- ASSERT_TRUE(CreateFileSystemDirectory(
- path, files[i].origin_url, files[i].type));
- if (path.empty()) {
- // Create the usage cache.
- // HACK--we always create the root [an empty path] first. If we
- // create it later, this will fail due to a quota mismatch. If we
- // call this before we create the root, it succeeds, but hasn't
- // actually created the cache.
- ASSERT_EQ(0, GetOriginUsage(
- quota_client, files[i].origin_url, files[i].type));
- }
- } else {
- ASSERT_TRUE(CreateFileSystemFile(
- path, files[i].size, files[i].origin_url, files[i].type));
- }
- }
- }
-
- // This is a bit fragile--it depends on the test data always creating a
- // directory before adding a file or directory to it, so that we can just
- // count the basename of each addition. A recursive creation of a path, which
- // created more than one directory in a single shot, would break this.
- int64 ComputeFilePathsCostForOriginAndType(const TestFile* files,
- int num_files,
- const std::string& origin_url,
- quota::StorageType type) {
- int64 file_paths_cost = 0;
- for (int i = 0; i < num_files; i++) {
- if (files[i].type == type &&
- GURL(files[i].origin_url) == GURL(origin_url)) {
- base::FilePath path = base::FilePath().AppendASCII(files[i].name);
- if (!path.empty()) {
- file_paths_cost += ObfuscatedFileUtil::ComputeFilePathCost(path);
- }
- }
- }
- return file_paths_cost;
- }
-
- void DeleteOriginData(FileSystemQuotaClient* quota_client,
- const std::string& origin,
- quota::StorageType type) {
- deletion_status_ = quota::kQuotaStatusUnknown;
- quota_client->DeleteOriginData(
- GURL(origin), type,
- base::Bind(&FileSystemQuotaClientTest::OnDeleteOrigin,
- weak_factory_.GetWeakPtr()));
- }
-
- int64 usage() const { return usage_; }
- quota::QuotaStatusCode status() { return deletion_status_; }
- int additional_callback_count() const { return additional_callback_count_; }
- void set_additional_callback_count(int count) {
- additional_callback_count_ = count;
- }
-
- private:
- void OnGetUsage(int64 usage) {
- usage_ = usage;
- }
-
- void OnGetOrigins(const std::set<GURL>& origins) {
- origins_ = origins;
- }
-
- void OnGetAdditionalUsage(int64 usage_unused) {
- ++additional_callback_count_;
- }
-
- void OnDeleteOrigin(quota::QuotaStatusCode status) {
- deletion_status_ = status;
- }
-
- base::ScopedTempDir data_dir_;
- base::MessageLoop message_loop_;
- scoped_refptr<FileSystemContext> file_system_context_;
- base::WeakPtrFactory<FileSystemQuotaClientTest> weak_factory_;
- int64 usage_;
- int additional_callback_count_;
- std::set<GURL> origins_;
- quota::QuotaStatusCode deletion_status_;
-
- DISALLOW_COPY_AND_ASSIGN(FileSystemQuotaClientTest);
-};
-
-TEST_F(FileSystemQuotaClientTest, NoFileSystemTest) {
- scoped_ptr<FileSystemQuotaClient> quota_client(NewQuotaClient(false));
-
- EXPECT_EQ(0, GetOriginUsage(quota_client.get(), kDummyURL1, kTemporary));
-}
-
-TEST_F(FileSystemQuotaClientTest, NoFileTest) {
- scoped_ptr<FileSystemQuotaClient> quota_client(NewQuotaClient(false));
- const TestFile kFiles[] = {
- {true, NULL, 0, kDummyURL1, kTemporary},
- };
- InitializeOriginFiles(quota_client.get(), kFiles, ARRAYSIZE_UNSAFE(kFiles));
-
- for (int i = 0; i < 2; i++) {
- EXPECT_EQ(0, GetOriginUsage(quota_client.get(), kDummyURL1, kTemporary));
- }
-}
-
-TEST_F(FileSystemQuotaClientTest, OneFileTest) {
- scoped_ptr<FileSystemQuotaClient> quota_client(NewQuotaClient(false));
- const TestFile kFiles[] = {
- {true, NULL, 0, kDummyURL1, kTemporary},
- {false, "foo", 4921, kDummyURL1, kTemporary},
- };
- InitializeOriginFiles(quota_client.get(), kFiles, ARRAYSIZE_UNSAFE(kFiles));
- const int64 file_paths_cost = ComputeFilePathsCostForOriginAndType(
- kFiles, ARRAYSIZE_UNSAFE(kFiles), kDummyURL1, kTemporary);
-
- for (int i = 0; i < 2; i++) {
- EXPECT_EQ(4921 + file_paths_cost,
- GetOriginUsage(quota_client.get(), kDummyURL1, kTemporary));
- }
-}
-
-TEST_F(FileSystemQuotaClientTest, TwoFilesTest) {
- scoped_ptr<FileSystemQuotaClient> quota_client(NewQuotaClient(false));
- const TestFile kFiles[] = {
- {true, NULL, 0, kDummyURL1, kTemporary},
- {false, "foo", 10310, kDummyURL1, kTemporary},
- {false, "bar", 41, kDummyURL1, kTemporary},
- };
- InitializeOriginFiles(quota_client.get(), kFiles, ARRAYSIZE_UNSAFE(kFiles));
- const int64 file_paths_cost = ComputeFilePathsCostForOriginAndType(
- kFiles, ARRAYSIZE_UNSAFE(kFiles), kDummyURL1, kTemporary);
-
- for (int i = 0; i < 2; i++) {
- EXPECT_EQ(10310 + 41 + file_paths_cost,
- GetOriginUsage(quota_client.get(), kDummyURL1, kTemporary));
- }
-}
-
-TEST_F(FileSystemQuotaClientTest, EmptyFilesTest) {
- scoped_ptr<FileSystemQuotaClient> quota_client(NewQuotaClient(false));
- const TestFile kFiles[] = {
- {true, NULL, 0, kDummyURL1, kTemporary},
- {false, "foo", 0, kDummyURL1, kTemporary},
- {false, "bar", 0, kDummyURL1, kTemporary},
- {false, "baz", 0, kDummyURL1, kTemporary},
- };
- InitializeOriginFiles(quota_client.get(), kFiles, ARRAYSIZE_UNSAFE(kFiles));
- const int64 file_paths_cost = ComputeFilePathsCostForOriginAndType(
- kFiles, ARRAYSIZE_UNSAFE(kFiles), kDummyURL1, kTemporary);
-
- for (int i = 0; i < 2; i++) {
- EXPECT_EQ(file_paths_cost,
- GetOriginUsage(quota_client.get(), kDummyURL1, kTemporary));
- }
-}
-
-TEST_F(FileSystemQuotaClientTest, SubDirectoryTest) {
- scoped_ptr<FileSystemQuotaClient> quota_client(NewQuotaClient(false));
- const TestFile kFiles[] = {
- {true, NULL, 0, kDummyURL1, kTemporary},
- {true, "dirtest", 0, kDummyURL1, kTemporary},
- {false, "dirtest/foo", 11921, kDummyURL1, kTemporary},
- {false, "bar", 4814, kDummyURL1, kTemporary},
- };
- InitializeOriginFiles(quota_client.get(), kFiles, ARRAYSIZE_UNSAFE(kFiles));
- const int64 file_paths_cost = ComputeFilePathsCostForOriginAndType(
- kFiles, ARRAYSIZE_UNSAFE(kFiles), kDummyURL1, kTemporary);
-
- for (int i = 0; i < 2; i++) {
- EXPECT_EQ(11921 + 4814 + file_paths_cost,
- GetOriginUsage(quota_client.get(), kDummyURL1, kTemporary));
- }
-}
-
-TEST_F(FileSystemQuotaClientTest, MultiTypeTest) {
- scoped_ptr<FileSystemQuotaClient> quota_client(NewQuotaClient(false));
- const TestFile kFiles[] = {
- {true, NULL, 0, kDummyURL1, kTemporary},
- {true, "dirtest", 0, kDummyURL1, kTemporary},
- {false, "dirtest/foo", 133, kDummyURL1, kTemporary},
- {false, "bar", 14, kDummyURL1, kTemporary},
- {true, NULL, 0, kDummyURL1, kPersistent},
- {true, "dirtest", 0, kDummyURL1, kPersistent},
- {false, "dirtest/foo", 193, kDummyURL1, kPersistent},
- {false, "bar", 9, kDummyURL1, kPersistent},
- };
- InitializeOriginFiles(quota_client.get(), kFiles, ARRAYSIZE_UNSAFE(kFiles));
- const int64 file_paths_cost_temporary = ComputeFilePathsCostForOriginAndType(
- kFiles, ARRAYSIZE_UNSAFE(kFiles), kDummyURL1, kTemporary);
- const int64 file_paths_cost_persistent = ComputeFilePathsCostForOriginAndType(
- kFiles, ARRAYSIZE_UNSAFE(kFiles), kDummyURL1, kTemporary);
-
- for (int i = 0; i < 2; i++) {
- EXPECT_EQ(133 + 14 + file_paths_cost_temporary,
- GetOriginUsage(quota_client.get(), kDummyURL1, kTemporary));
- EXPECT_EQ(193 + 9 + file_paths_cost_persistent,
- GetOriginUsage(quota_client.get(), kDummyURL1, kPersistent));
- }
-}
-
-TEST_F(FileSystemQuotaClientTest, MultiDomainTest) {
- scoped_ptr<FileSystemQuotaClient> quota_client(NewQuotaClient(false));
- const TestFile kFiles[] = {
- {true, NULL, 0, kDummyURL1, kTemporary},
- {true, "dir1", 0, kDummyURL1, kTemporary},
- {false, "dir1/foo", 1331, kDummyURL1, kTemporary},
- {false, "bar", 134, kDummyURL1, kTemporary},
- {true, NULL, 0, kDummyURL1, kPersistent},
- {true, "dir2", 0, kDummyURL1, kPersistent},
- {false, "dir2/foo", 1903, kDummyURL1, kPersistent},
- {false, "bar", 19, kDummyURL1, kPersistent},
- {true, NULL, 0, kDummyURL2, kTemporary},
- {true, "dom", 0, kDummyURL2, kTemporary},
- {false, "dom/fan", 1319, kDummyURL2, kTemporary},
- {false, "bar", 113, kDummyURL2, kTemporary},
- {true, NULL, 0, kDummyURL2, kPersistent},
- {true, "dom", 0, kDummyURL2, kPersistent},
- {false, "dom/fan", 2013, kDummyURL2, kPersistent},
- {false, "baz", 18, kDummyURL2, kPersistent},
- };
- InitializeOriginFiles(quota_client.get(), kFiles, ARRAYSIZE_UNSAFE(kFiles));
- const int64 file_paths_cost_temporary1 = ComputeFilePathsCostForOriginAndType(
- kFiles, ARRAYSIZE_UNSAFE(kFiles), kDummyURL1, kTemporary);
- const int64 file_paths_cost_persistent1 =
- ComputeFilePathsCostForOriginAndType(kFiles, ARRAYSIZE_UNSAFE(kFiles),
- kDummyURL1, kPersistent);
- const int64 file_paths_cost_temporary2 = ComputeFilePathsCostForOriginAndType(
- kFiles, ARRAYSIZE_UNSAFE(kFiles), kDummyURL2, kTemporary);
- const int64 file_paths_cost_persistent2 =
- ComputeFilePathsCostForOriginAndType(kFiles, ARRAYSIZE_UNSAFE(kFiles),
- kDummyURL2, kPersistent);
-
- for (int i = 0; i < 2; i++) {
- EXPECT_EQ(1331 + 134 + file_paths_cost_temporary1,
- GetOriginUsage(quota_client.get(), kDummyURL1, kTemporary));
- EXPECT_EQ(1903 + 19 + file_paths_cost_persistent1,
- GetOriginUsage(quota_client.get(), kDummyURL1, kPersistent));
- EXPECT_EQ(1319 + 113 + file_paths_cost_temporary2,
- GetOriginUsage(quota_client.get(), kDummyURL2, kTemporary));
- EXPECT_EQ(2013 + 18 + file_paths_cost_persistent2,
- GetOriginUsage(quota_client.get(), kDummyURL2, kPersistent));
- }
-}
-
-TEST_F(FileSystemQuotaClientTest, GetUsage_MultipleTasks) {
- scoped_ptr<FileSystemQuotaClient> quota_client(NewQuotaClient(false));
- const TestFile kFiles[] = {
- {true, NULL, 0, kDummyURL1, kTemporary},
- {false, "foo", 11, kDummyURL1, kTemporary},
- {false, "bar", 22, kDummyURL1, kTemporary},
- };
- InitializeOriginFiles(quota_client.get(), kFiles, ARRAYSIZE_UNSAFE(kFiles));
- const int64 file_paths_cost = ComputeFilePathsCostForOriginAndType(
- kFiles, ARRAYSIZE_UNSAFE(kFiles), kDummyURL1, kTemporary);
-
- // Dispatching three GetUsage tasks.
- set_additional_callback_count(0);
- GetOriginUsageAsync(quota_client.get(), kDummyURL1, kTemporary);
- RunAdditionalOriginUsageTask(quota_client.get(), kDummyURL1, kTemporary);
- RunAdditionalOriginUsageTask(quota_client.get(), kDummyURL1, kTemporary);
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(11 + 22 + file_paths_cost, usage());
- EXPECT_EQ(2, additional_callback_count());
-
- // Once more, in a different order.
- set_additional_callback_count(0);
- RunAdditionalOriginUsageTask(quota_client.get(), kDummyURL1, kTemporary);
- GetOriginUsageAsync(quota_client.get(), kDummyURL1, kTemporary);
- RunAdditionalOriginUsageTask(quota_client.get(), kDummyURL1, kTemporary);
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(11 + 22 + file_paths_cost, usage());
- EXPECT_EQ(2, additional_callback_count());
-}
-
-TEST_F(FileSystemQuotaClientTest, GetOriginsForType) {
- scoped_ptr<FileSystemQuotaClient> quota_client(NewQuotaClient(false));
- const TestFile kFiles[] = {
- {true, NULL, 0, kDummyURL1, kTemporary},
- {true, NULL, 0, kDummyURL2, kTemporary},
- {true, NULL, 0, kDummyURL3, kPersistent},
- };
- InitializeOriginFiles(quota_client.get(), kFiles, ARRAYSIZE_UNSAFE(kFiles));
-
- std::set<GURL> origins = GetOriginsForType(quota_client.get(), kTemporary);
- EXPECT_EQ(2U, origins.size());
- EXPECT_TRUE(origins.find(GURL(kDummyURL1)) != origins.end());
- EXPECT_TRUE(origins.find(GURL(kDummyURL2)) != origins.end());
- EXPECT_TRUE(origins.find(GURL(kDummyURL3)) == origins.end());
-}
-
-TEST_F(FileSystemQuotaClientTest, GetOriginsForHost) {
- scoped_ptr<FileSystemQuotaClient> quota_client(NewQuotaClient(false));
- const char* kURL1 = "http://foo.com/";
- const char* kURL2 = "https://foo.com/";
- const char* kURL3 = "http://foo.com:1/";
- const char* kURL4 = "http://foo2.com/";
- const char* kURL5 = "http://foo.com:2/";
- const TestFile kFiles[] = {
- {true, NULL, 0, kURL1, kTemporary},
- {true, NULL, 0, kURL2, kTemporary},
- {true, NULL, 0, kURL3, kTemporary},
- {true, NULL, 0, kURL4, kTemporary},
- {true, NULL, 0, kURL5, kPersistent},
- };
- InitializeOriginFiles(quota_client.get(), kFiles, ARRAYSIZE_UNSAFE(kFiles));
-
- std::set<GURL> origins = GetOriginsForHost(
- quota_client.get(), kTemporary, "foo.com");
- EXPECT_EQ(3U, origins.size());
- EXPECT_TRUE(origins.find(GURL(kURL1)) != origins.end());
- EXPECT_TRUE(origins.find(GURL(kURL2)) != origins.end());
- EXPECT_TRUE(origins.find(GURL(kURL3)) != origins.end());
- EXPECT_TRUE(origins.find(GURL(kURL4)) == origins.end()); // Different host.
- EXPECT_TRUE(origins.find(GURL(kURL5)) == origins.end()); // Different type.
-}
-
-TEST_F(FileSystemQuotaClientTest, IncognitoTest) {
- scoped_ptr<FileSystemQuotaClient> quota_client(NewQuotaClient(true));
- const TestFile kFiles[] = {
- {true, NULL, 0, kDummyURL1, kTemporary},
- {false, "foo", 10, kDummyURL1, kTemporary},
- };
- InitializeOriginFiles(quota_client.get(), kFiles, ARRAYSIZE_UNSAFE(kFiles));
-
- // Having files in the usual directory wouldn't affect the result
- // queried in incognito mode.
- EXPECT_EQ(0, GetOriginUsage(quota_client.get(), kDummyURL1, kTemporary));
- EXPECT_EQ(0, GetOriginUsage(quota_client.get(), kDummyURL1, kPersistent));
-
- std::set<GURL> origins = GetOriginsForType(quota_client.get(), kTemporary);
- EXPECT_EQ(0U, origins.size());
- origins = GetOriginsForHost(quota_client.get(), kTemporary, "www.dummy.org");
- EXPECT_EQ(0U, origins.size());
-}
-
-TEST_F(FileSystemQuotaClientTest, DeleteOriginTest) {
- scoped_ptr<FileSystemQuotaClient> quota_client(NewQuotaClient(false));
- const TestFile kFiles[] = {
- {true, NULL, 0, "http://foo.com/", kTemporary},
- {false, "a", 1, "http://foo.com/", kTemporary},
- {true, NULL, 0, "https://foo.com/", kTemporary},
- {false, "b", 2, "https://foo.com/", kTemporary},
- {true, NULL, 0, "http://foo.com/", kPersistent},
- {false, "c", 4, "http://foo.com/", kPersistent},
- {true, NULL, 0, "http://bar.com/", kTemporary},
- {false, "d", 8, "http://bar.com/", kTemporary},
- {true, NULL, 0, "http://bar.com/", kPersistent},
- {false, "e", 16, "http://bar.com/", kPersistent},
- {true, NULL, 0, "https://bar.com/", kPersistent},
- {false, "f", 32, "https://bar.com/", kPersistent},
- {true, NULL, 0, "https://bar.com/", kTemporary},
- {false, "g", 64, "https://bar.com/", kTemporary},
- };
- InitializeOriginFiles(quota_client.get(), kFiles, ARRAYSIZE_UNSAFE(kFiles));
- const int64 file_paths_cost_temporary_foo_https =
- ComputeFilePathsCostForOriginAndType(kFiles, ARRAYSIZE_UNSAFE(kFiles),
- "https://foo.com/", kTemporary);
- const int64 file_paths_cost_persistent_foo =
- ComputeFilePathsCostForOriginAndType(kFiles, ARRAYSIZE_UNSAFE(kFiles),
- "http://foo.com/", kPersistent);
- const int64 file_paths_cost_temporary_bar =
- ComputeFilePathsCostForOriginAndType(kFiles, ARRAYSIZE_UNSAFE(kFiles),
- "http://bar.com/", kTemporary);
- const int64 file_paths_cost_temporary_bar_https =
- ComputeFilePathsCostForOriginAndType(kFiles, ARRAYSIZE_UNSAFE(kFiles),
- "https://bar.com/", kTemporary);
- const int64 file_paths_cost_persistent_bar_https =
- ComputeFilePathsCostForOriginAndType(kFiles, ARRAYSIZE_UNSAFE(kFiles),
- "https://bar.com/", kPersistent);
-
- DeleteOriginData(quota_client.get(), "http://foo.com/", kTemporary);
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(quota::kQuotaStatusOk, status());
-
- DeleteOriginData(quota_client.get(), "http://bar.com/", kPersistent);
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(quota::kQuotaStatusOk, status());
-
- DeleteOriginData(quota_client.get(), "http://buz.com/", kTemporary);
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(quota::kQuotaStatusOk, status());
-
- EXPECT_EQ(0, GetOriginUsage(
- quota_client.get(), "http://foo.com/", kTemporary));
- EXPECT_EQ(0, GetOriginUsage(
- quota_client.get(), "http://bar.com/", kPersistent));
- EXPECT_EQ(0, GetOriginUsage(
- quota_client.get(), "http://buz.com/", kTemporary));
-
- EXPECT_EQ(2 + file_paths_cost_temporary_foo_https,
- GetOriginUsage(quota_client.get(),
- "https://foo.com/",
- kTemporary));
- EXPECT_EQ(4 + file_paths_cost_persistent_foo,
- GetOriginUsage(quota_client.get(),
- "http://foo.com/",
- kPersistent));
- EXPECT_EQ(8 + file_paths_cost_temporary_bar,
- GetOriginUsage(quota_client.get(),
- "http://bar.com/",
- kTemporary));
- EXPECT_EQ(32 + file_paths_cost_persistent_bar_https,
- GetOriginUsage(quota_client.get(),
- "https://bar.com/",
- kPersistent));
- EXPECT_EQ(64 + file_paths_cost_temporary_bar_https,
- GetOriginUsage(quota_client.get(),
- "https://bar.com/",
- kTemporary));
-}
-
-} // namespace fileapi
diff --git a/chromium/webkit/browser/fileapi/file_system_quota_util.h b/chromium/webkit/browser/fileapi/file_system_quota_util.h
index 5f3c7dd77ae..e3930862f87 100644
--- a/chromium/webkit/browser/fileapi/file_system_quota_util.h
+++ b/chromium/webkit/browser/fileapi/file_system_quota_util.h
@@ -26,6 +26,7 @@ class QuotaManagerProxy;
namespace fileapi {
class FileSystemContext;
+class QuotaReservation;
// An abstract interface that provides common quota-related utility functions
// for file_system_quota_client.
@@ -56,6 +57,12 @@ class WEBKIT_STORAGE_BROWSER_EXPORT FileSystemQuotaUtil {
const GURL& origin_url,
fileapi::FileSystemType type) = 0;
+ // Creates new reservation object for the origin and the type.
+ virtual scoped_refptr<QuotaReservation>
+ CreateQuotaReservationOnFileTaskRunner(
+ const GURL& origin_url,
+ FileSystemType type) = 0;
+
virtual void AddFileUpdateObserver(
FileSystemType type,
FileUpdateObserver* observer,
diff --git a/chromium/webkit/browser/fileapi/file_system_url.cc b/chromium/webkit/browser/fileapi/file_system_url.cc
index 2f8875a701b..b045ed3f5d3 100644
--- a/chromium/webkit/browser/fileapi/file_system_url.cc
+++ b/chromium/webkit/browser/fileapi/file_system_url.cc
@@ -21,7 +21,8 @@ namespace {
FileSystemURL::FileSystemURL()
: is_valid_(false),
mount_type_(kFileSystemTypeUnknown),
- type_(kFileSystemTypeUnknown) {
+ type_(kFileSystemTypeUnknown),
+ mount_option_(COPY_SYNC_OPTION_NO_SYNC) {
}
// static
@@ -98,7 +99,8 @@ bool FileSystemURL::ParseFileSystemSchemeURL(
FileSystemURL::FileSystemURL(const GURL& url)
: mount_type_(kFileSystemTypeUnknown),
- type_(kFileSystemTypeUnknown) {
+ type_(kFileSystemTypeUnknown),
+ mount_option_(COPY_SYNC_OPTION_NO_SYNC) {
is_valid_ = ParseFileSystemSchemeURL(url, &origin_, &mount_type_,
&virtual_path_);
path_ = virtual_path_;
@@ -113,7 +115,8 @@ FileSystemURL::FileSystemURL(const GURL& origin,
mount_type_(mount_type),
virtual_path_(virtual_path.NormalizePathSeparators()),
type_(mount_type),
- path_(virtual_path.NormalizePathSeparators()) {
+ path_(virtual_path.NormalizePathSeparators()),
+ mount_option_(COPY_SYNC_OPTION_NO_SYNC) {
}
FileSystemURL::FileSystemURL(const GURL& origin,
@@ -122,7 +125,8 @@ FileSystemURL::FileSystemURL(const GURL& origin,
const std::string& mount_filesystem_id,
FileSystemType cracked_type,
const base::FilePath& cracked_path,
- const std::string& filesystem_id)
+ const std::string& filesystem_id,
+ const FileSystemMountOption& mount_option)
: is_valid_(true),
origin_(origin),
mount_type_(mount_type),
@@ -130,7 +134,8 @@ FileSystemURL::FileSystemURL(const GURL& origin,
mount_filesystem_id_(mount_filesystem_id),
type_(cracked_type),
path_(cracked_path.NormalizePathSeparators()),
- filesystem_id_(filesystem_id) {
+ filesystem_id_(filesystem_id),
+ mount_option_(mount_option) {
}
FileSystemURL::~FileSystemURL() {}
diff --git a/chromium/webkit/browser/fileapi/file_system_url.h b/chromium/webkit/browser/fileapi/file_system_url.h
index d6443e69189..c00231d80d3 100644
--- a/chromium/webkit/browser/fileapi/file_system_url.h
+++ b/chromium/webkit/browser/fileapi/file_system_url.h
@@ -11,6 +11,7 @@
#include "base/platform_file.h"
#include "url/gurl.h"
#include "webkit/browser/webkit_storage_browser_export.h"
+#include "webkit/common/fileapi/file_system_mount_option.h"
#include "webkit/common/fileapi/file_system_types.h"
namespace fileapi {
@@ -118,6 +119,8 @@ class WEBKIT_STORAGE_BROWSER_EXPORT FileSystemURL {
FileSystemType mount_type() const { return mount_type_; }
+ const FileSystemMountOption& mount_option() const { return mount_option_; }
+
// Returns the formatted URL of this instance.
GURL ToGURL() const;
@@ -154,7 +157,8 @@ class WEBKIT_STORAGE_BROWSER_EXPORT FileSystemURL {
const std::string& mount_filesystem_id,
FileSystemType cracked_type,
const base::FilePath& cracked_path,
- const std::string& filesystem_id);
+ const std::string& filesystem_id,
+ const FileSystemMountOption& mount_option);
bool is_valid_;
@@ -172,6 +176,7 @@ class WEBKIT_STORAGE_BROWSER_EXPORT FileSystemURL {
FileSystemType type_;
base::FilePath path_;
std::string filesystem_id_;
+ FileSystemMountOption mount_option_;
};
typedef std::set<FileSystemURL, FileSystemURL::Comparator> FileSystemURLSet;
diff --git a/chromium/webkit/browser/fileapi/file_system_url_request_job.cc b/chromium/webkit/browser/fileapi/file_system_url_request_job.cc
index 7d1f8613138..57db3006557 100644
--- a/chromium/webkit/browser/fileapi/file_system_url_request_job.cc
+++ b/chromium/webkit/browser/fileapi/file_system_url_request_job.cc
@@ -60,9 +60,9 @@ FileSystemURLRequestJob::FileSystemURLRequestJob(
FileSystemContext* file_system_context)
: URLRequestJob(request, network_delegate),
file_system_context_(file_system_context),
- weak_factory_(this),
is_directory_(false),
- remaining_bytes_(0) {
+ remaining_bytes_(0),
+ weak_factory_(this) {
}
FileSystemURLRequestJob::~FileSystemURLRequestJob() {}
diff --git a/chromium/webkit/browser/fileapi/file_system_url_request_job.h b/chromium/webkit/browser/fileapi/file_system_url_request_job.h
index 6b829e6e861..a784d629251 100644
--- a/chromium/webkit/browser/fileapi/file_system_url_request_job.h
+++ b/chromium/webkit/browser/fileapi/file_system_url_request_job.h
@@ -67,13 +67,13 @@ class WEBKIT_STORAGE_BROWSER_EXPORT_PRIVATE FileSystemURLRequestJob
void NotifyFailed(int rv);
FileSystemContext* file_system_context_;
- base::WeakPtrFactory<FileSystemURLRequestJob> weak_factory_;
scoped_ptr<webkit_blob::FileStreamReader> reader_;
FileSystemURL url_;
bool is_directory_;
scoped_ptr<net::HttpResponseInfo> response_info_;
int64 remaining_bytes_;
net::HttpByteRange byte_range_;
+ base::WeakPtrFactory<FileSystemURLRequestJob> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(FileSystemURLRequestJob);
};
diff --git a/chromium/webkit/browser/fileapi/file_system_url_request_job_unittest.cc b/chromium/webkit/browser/fileapi/file_system_url_request_job_unittest.cc
deleted file mode 100644
index 8f54e62b984..00000000000
--- a/chromium/webkit/browser/fileapi/file_system_url_request_job_unittest.cc
+++ /dev/null
@@ -1,365 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "webkit/browser/fileapi/file_system_url_request_job.h"
-
-#include <string>
-
-#include "base/bind.h"
-#include "base/file_util.h"
-#include "base/files/file_path.h"
-#include "base/files/scoped_temp_dir.h"
-#include "base/format_macros.h"
-#include "base/memory/weak_ptr.h"
-#include "base/message_loop/message_loop.h"
-#include "base/message_loop/message_loop_proxy.h"
-#include "base/platform_file.h"
-#include "base/rand_util.h"
-#include "base/run_loop.h"
-#include "base/strings/string_piece.h"
-#include "base/strings/stringprintf.h"
-#include "base/strings/utf_string_conversions.h"
-#include "net/base/load_flags.h"
-#include "net/base/mime_util.h"
-#include "net/base/net_errors.h"
-#include "net/base/net_util.h"
-#include "net/http/http_request_headers.h"
-#include "net/url_request/url_request.h"
-#include "net/url_request/url_request_context.h"
-#include "net/url_request/url_request_test_util.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "webkit/browser/fileapi/async_file_test_helper.h"
-#include "webkit/browser/fileapi/external_mount_points.h"
-#include "webkit/browser/fileapi/file_system_context.h"
-#include "webkit/browser/fileapi/file_system_file_util.h"
-#include "webkit/browser/fileapi/mock_file_system_context.h"
-
-namespace fileapi {
-namespace {
-
-// We always use the TEMPORARY FileSystem in this test.
-const char kFileSystemURLPrefix[] = "filesystem:http://remote/temporary/";
-const char kTestFileData[] = "0123456789";
-
-void FillBuffer(char* buffer, size_t len) {
- base::RandBytes(buffer, len);
-}
-
-} // namespace
-
-class FileSystemURLRequestJobTest : public testing::Test {
- protected:
- FileSystemURLRequestJobTest()
- : message_loop_(base::MessageLoop::TYPE_IO), // simulate an IO thread
- weak_factory_(this) {
- }
-
- virtual void SetUp() OVERRIDE {
- ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
-
- // We use the main thread so that we can get the root path synchronously.
- // TODO(adamk): Run this on the FILE thread we've created as well.
- file_system_context_ =
- CreateFileSystemContextForTesting(NULL, temp_dir_.path());
-
- file_system_context_->OpenFileSystem(
- GURL("http://remote/"), kFileSystemTypeTemporary,
- OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
- base::Bind(&FileSystemURLRequestJobTest::OnOpenFileSystem,
- weak_factory_.GetWeakPtr()));
- base::RunLoop().RunUntilIdle();
-
- net::URLRequest::Deprecated::RegisterProtocolFactory(
- "filesystem", &FileSystemURLRequestJobFactory);
- }
-
- virtual void TearDown() OVERRIDE {
- net::URLRequest::Deprecated::RegisterProtocolFactory("filesystem", NULL);
- ClearUnusedJob();
- if (pending_job_.get()) {
- pending_job_->Kill();
- pending_job_ = NULL;
- }
- // FileReader posts a task to close the file in destructor.
- base::RunLoop().RunUntilIdle();
- }
-
- void OnOpenFileSystem(base::PlatformFileError result,
- const std::string& name,
- const GURL& root_url) {
- ASSERT_EQ(base::PLATFORM_FILE_OK, result);
- }
-
- void TestRequestHelper(const GURL& url,
- const net::HttpRequestHeaders* headers,
- bool run_to_completion,
- FileSystemContext* file_system_context) {
- delegate_.reset(new net::TestDelegate());
- // Make delegate_ exit the MessageLoop when the request is done.
- delegate_->set_quit_on_complete(true);
- delegate_->set_quit_on_redirect(true);
- request_.reset(empty_context_.CreateRequest(url, delegate_.get()));
- if (headers)
- request_->SetExtraRequestHeaders(*headers);
- ASSERT_TRUE(!job_);
- job_ = new FileSystemURLRequestJob(
- request_.get(), NULL, file_system_context);
- pending_job_ = job_;
-
- request_->Start();
- ASSERT_TRUE(request_->is_pending()); // verify that we're starting async
- if (run_to_completion)
- base::MessageLoop::current()->Run();
- }
-
- void TestRequest(const GURL& url) {
- TestRequestHelper(url, NULL, true, file_system_context_.get());
- }
-
- void TestRequestWithContext(const GURL& url,
- FileSystemContext* file_system_context) {
- TestRequestHelper(url, NULL, true, file_system_context);
- }
-
- void TestRequestWithHeaders(const GURL& url,
- const net::HttpRequestHeaders* headers) {
- TestRequestHelper(url, headers, true, file_system_context_.get());
- }
-
- void TestRequestNoRun(const GURL& url) {
- TestRequestHelper(url, NULL, false, file_system_context_.get());
- }
-
- void CreateDirectory(const base::StringPiece& dir_name) {
- FileSystemURL url = file_system_context_->CreateCrackedFileSystemURL(
- GURL("http://remote"),
- kFileSystemTypeTemporary,
- base::FilePath().AppendASCII(dir_name));
- ASSERT_EQ(base::PLATFORM_FILE_OK, AsyncFileTestHelper::CreateDirectory(
- file_system_context_, url));
- }
-
- void WriteFile(const base::StringPiece& file_name,
- const char* buf, int buf_size) {
- FileSystemURL url = file_system_context_->CreateCrackedFileSystemURL(
- GURL("http://remote"),
- kFileSystemTypeTemporary,
- base::FilePath().AppendASCII(file_name));
- ASSERT_EQ(base::PLATFORM_FILE_OK,
- AsyncFileTestHelper::CreateFileWithData(
- file_system_context_, url, buf, buf_size));
- }
-
- GURL CreateFileSystemURL(const std::string& path) {
- return GURL(kFileSystemURLPrefix + path);
- }
-
- static net::URLRequestJob* FileSystemURLRequestJobFactory(
- net::URLRequest* request,
- net::NetworkDelegate* network_delegate,
- const std::string& scheme) {
- DCHECK(job_);
- net::URLRequestJob* temp = job_;
- job_ = NULL;
- return temp;
- }
-
- static void ClearUnusedJob() {
- if (job_) {
- scoped_refptr<net::URLRequestJob> deleter = job_;
- job_ = NULL;
- }
- }
-
- // Put the message loop at the top, so that it's the last thing deleted.
- base::MessageLoop message_loop_;
-
- base::ScopedTempDir temp_dir_;
- scoped_refptr<FileSystemContext> file_system_context_;
- base::WeakPtrFactory<FileSystemURLRequestJobTest> weak_factory_;
-
- net::URLRequestContext empty_context_;
-
- // NOTE: order matters, request must die before delegate
- scoped_ptr<net::TestDelegate> delegate_;
- scoped_ptr<net::URLRequest> request_;
-
- scoped_refptr<net::URLRequestJob> pending_job_;
- static net::URLRequestJob* job_;
-};
-
-// static
-net::URLRequestJob* FileSystemURLRequestJobTest::job_ = NULL;
-
-namespace {
-
-TEST_F(FileSystemURLRequestJobTest, FileTest) {
- WriteFile("file1.dat", kTestFileData, arraysize(kTestFileData) - 1);
- TestRequest(CreateFileSystemURL("file1.dat"));
-
- ASSERT_FALSE(request_->is_pending());
- EXPECT_EQ(1, delegate_->response_started_count());
- EXPECT_FALSE(delegate_->received_data_before_response());
- EXPECT_EQ(kTestFileData, delegate_->data_received());
- EXPECT_EQ(200, request_->GetResponseCode());
- std::string cache_control;
- request_->GetResponseHeaderByName("cache-control", &cache_control);
- EXPECT_EQ("no-cache", cache_control);
-}
-
-TEST_F(FileSystemURLRequestJobTest, FileTestFullSpecifiedRange) {
- const size_t buffer_size = 4000;
- scoped_ptr<char[]> buffer(new char[buffer_size]);
- FillBuffer(buffer.get(), buffer_size);
- WriteFile("bigfile", buffer.get(), buffer_size);
-
- const size_t first_byte_position = 500;
- const size_t last_byte_position = buffer_size - first_byte_position;
- std::string partial_buffer_string(buffer.get() + first_byte_position,
- buffer.get() + last_byte_position + 1);
-
- net::HttpRequestHeaders headers;
- headers.SetHeader(net::HttpRequestHeaders::kRange,
- base::StringPrintf(
- "bytes=%" PRIuS "-%" PRIuS,
- first_byte_position, last_byte_position));
- TestRequestWithHeaders(CreateFileSystemURL("bigfile"), &headers);
-
- ASSERT_FALSE(request_->is_pending());
- EXPECT_EQ(1, delegate_->response_started_count());
- EXPECT_FALSE(delegate_->received_data_before_response());
- EXPECT_TRUE(partial_buffer_string == delegate_->data_received());
-}
-
-TEST_F(FileSystemURLRequestJobTest, FileTestHalfSpecifiedRange) {
- const size_t buffer_size = 4000;
- scoped_ptr<char[]> buffer(new char[buffer_size]);
- FillBuffer(buffer.get(), buffer_size);
- WriteFile("bigfile", buffer.get(), buffer_size);
-
- const size_t first_byte_position = 500;
- std::string partial_buffer_string(buffer.get() + first_byte_position,
- buffer.get() + buffer_size);
-
- net::HttpRequestHeaders headers;
- headers.SetHeader(net::HttpRequestHeaders::kRange,
- base::StringPrintf("bytes=%" PRIuS "-",
- first_byte_position));
- TestRequestWithHeaders(CreateFileSystemURL("bigfile"), &headers);
- ASSERT_FALSE(request_->is_pending());
- EXPECT_EQ(1, delegate_->response_started_count());
- EXPECT_FALSE(delegate_->received_data_before_response());
- // Don't use EXPECT_EQ, it will print out a lot of garbage if check failed.
- EXPECT_TRUE(partial_buffer_string == delegate_->data_received());
-}
-
-
-TEST_F(FileSystemURLRequestJobTest, FileTestMultipleRangesNotSupported) {
- WriteFile("file1.dat", kTestFileData, arraysize(kTestFileData) - 1);
- net::HttpRequestHeaders headers;
- headers.SetHeader(net::HttpRequestHeaders::kRange,
- "bytes=0-5,10-200,200-300");
- TestRequestWithHeaders(CreateFileSystemURL("file1.dat"), &headers);
- EXPECT_TRUE(delegate_->request_failed());
- EXPECT_EQ(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE,
- request_->status().error());
-}
-
-TEST_F(FileSystemURLRequestJobTest, RangeOutOfBounds) {
- WriteFile("file1.dat", kTestFileData, arraysize(kTestFileData) - 1);
- net::HttpRequestHeaders headers;
- headers.SetHeader(net::HttpRequestHeaders::kRange, "bytes=500-1000");
- TestRequestWithHeaders(CreateFileSystemURL("file1.dat"), &headers);
-
- ASSERT_FALSE(request_->is_pending());
- EXPECT_TRUE(delegate_->request_failed());
- EXPECT_EQ(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE,
- request_->status().error());
-}
-
-TEST_F(FileSystemURLRequestJobTest, FileDirRedirect) {
- CreateDirectory("dir");
- TestRequest(CreateFileSystemURL("dir"));
-
- EXPECT_EQ(1, delegate_->received_redirect_count());
- EXPECT_TRUE(request_->status().is_success());
- EXPECT_FALSE(delegate_->request_failed());
-
- // We've deferred the redirect; now cancel the request to avoid following it.
- request_->Cancel();
- base::MessageLoop::current()->Run();
-}
-
-TEST_F(FileSystemURLRequestJobTest, InvalidURL) {
- TestRequest(GURL("filesystem:/foo/bar/baz"));
- ASSERT_FALSE(request_->is_pending());
- EXPECT_TRUE(delegate_->request_failed());
- EXPECT_EQ(net::ERR_INVALID_URL, request_->status().error());
-}
-
-TEST_F(FileSystemURLRequestJobTest, NoSuchRoot) {
- TestRequest(GURL("filesystem:http://remote/persistent/somefile"));
- ASSERT_FALSE(request_->is_pending());
- EXPECT_TRUE(delegate_->request_failed());
- EXPECT_EQ(net::ERR_FILE_NOT_FOUND, request_->status().error());
-}
-
-TEST_F(FileSystemURLRequestJobTest, NoSuchFile) {
- TestRequest(CreateFileSystemURL("somefile"));
- ASSERT_FALSE(request_->is_pending());
- EXPECT_TRUE(delegate_->request_failed());
- EXPECT_EQ(net::ERR_FILE_NOT_FOUND, request_->status().error());
-}
-
-TEST_F(FileSystemURLRequestJobTest, Cancel) {
- WriteFile("file1.dat", kTestFileData, arraysize(kTestFileData) - 1);
- TestRequestNoRun(CreateFileSystemURL("file1.dat"));
-
- // Run StartAsync() and only StartAsync().
- base::MessageLoop::current()->DeleteSoon(FROM_HERE, request_.release());
- base::RunLoop().RunUntilIdle();
- // If we get here, success! we didn't crash!
-}
-
-TEST_F(FileSystemURLRequestJobTest, GetMimeType) {
- const char kFilename[] = "hoge.html";
-
- std::string mime_type_direct;
- base::FilePath::StringType extension =
- base::FilePath().AppendASCII(kFilename).Extension();
- if (!extension.empty())
- extension = extension.substr(1);
- EXPECT_TRUE(net::GetWellKnownMimeTypeFromExtension(
- extension, &mime_type_direct));
-
- TestRequest(CreateFileSystemURL(kFilename));
-
- std::string mime_type_from_job;
- request_->GetMimeType(&mime_type_from_job);
- EXPECT_EQ(mime_type_direct, mime_type_from_job);
-}
-
-TEST_F(FileSystemURLRequestJobTest, Incognito) {
- WriteFile("file", kTestFileData, arraysize(kTestFileData) - 1);
-
- // Creates a new filesystem context for incognito mode.
- scoped_refptr<FileSystemContext> file_system_context =
- CreateIncognitoFileSystemContextForTesting(NULL, temp_dir_.path());
-
- // The request should return NOT_FOUND error if it's in incognito mode.
- TestRequestWithContext(CreateFileSystemURL("file"),
- file_system_context.get());
- ASSERT_FALSE(request_->is_pending());
- EXPECT_TRUE(delegate_->request_failed());
- EXPECT_EQ(net::ERR_FILE_NOT_FOUND, request_->status().error());
-
- // Make sure it returns success with regular (non-incognito) context.
- TestRequest(CreateFileSystemURL("file"));
- ASSERT_FALSE(request_->is_pending());
- EXPECT_EQ(kTestFileData, delegate_->data_received());
- EXPECT_EQ(200, request_->GetResponseCode());
-}
-
-} // namespace
-} // namespace fileapi
diff --git a/chromium/webkit/browser/fileapi/file_system_usage_cache.cc b/chromium/webkit/browser/fileapi/file_system_usage_cache.cc
index c1896fb1f95..56b1fb43566 100644
--- a/chromium/webkit/browser/fileapi/file_system_usage_cache.cc
+++ b/chromium/webkit/browser/fileapi/file_system_usage_cache.cc
@@ -23,8 +23,8 @@ const size_t kMaxHandleCacheSize = 2;
FileSystemUsageCache::FileSystemUsageCache(
base::SequencedTaskRunner* task_runner)
- : weak_factory_(this),
- task_runner_(task_runner) {
+ : task_runner_(task_runner),
+ weak_factory_(this) {
}
FileSystemUsageCache::~FileSystemUsageCache() {
diff --git a/chromium/webkit/browser/fileapi/file_system_usage_cache.h b/chromium/webkit/browser/fileapi/file_system_usage_cache.h
index b4d8464884b..c3950a58561 100644
--- a/chromium/webkit/browser/fileapi/file_system_usage_cache.h
+++ b/chromium/webkit/browser/fileapi/file_system_usage_cache.h
@@ -93,10 +93,11 @@ class WEBKIT_STORAGE_BROWSER_EXPORT_PRIVATE FileSystemUsageCache {
scoped_ptr<TimedTaskHelper> timer_;
std::map<base::FilePath, base::PlatformFile> cache_files_;
- base::WeakPtrFactory<FileSystemUsageCache> weak_factory_;
scoped_refptr<base::SequencedTaskRunner> task_runner_;
+ base::WeakPtrFactory<FileSystemUsageCache> weak_factory_;
+
DISALLOW_COPY_AND_ASSIGN(FileSystemUsageCache);
};
diff --git a/chromium/webkit/browser/fileapi/file_writer_delegate.cc b/chromium/webkit/browser/fileapi/file_writer_delegate.cc
index 7a0094ee4d5..295cd642ab1 100644
--- a/chromium/webkit/browser/fileapi/file_writer_delegate.cc
+++ b/chromium/webkit/browser/fileapi/file_writer_delegate.cc
@@ -14,31 +14,12 @@
#include "net/base/net_errors.h"
#include "webkit/browser/fileapi/file_stream_writer.h"
#include "webkit/browser/fileapi/file_system_context.h"
+#include "webkit/common/fileapi/file_system_util.h"
namespace fileapi {
static const int kReadBufSize = 32768;
-namespace {
-
-base::PlatformFileError NetErrorToPlatformFileError(int error) {
-// TODO(kinuko): Move this static method to more convenient place.
- switch (error) {
- case net::OK:
- return base::PLATFORM_FILE_OK;
- case net::ERR_FILE_NO_SPACE:
- return base::PLATFORM_FILE_ERROR_NO_SPACE;
- case net::ERR_FILE_NOT_FOUND:
- return base::PLATFORM_FILE_ERROR_NOT_FOUND;
- case net::ERR_ACCESS_DENIED:
- return base::PLATFORM_FILE_ERROR_ACCESS_DENIED;
- default:
- return base::PLATFORM_FILE_ERROR_FAILED;
- }
-}
-
-} // namespace
-
FileWriterDelegate::FileWriterDelegate(
scoped_ptr<FileStreamWriter> file_stream_writer)
: file_stream_writer_(file_stream_writer.Pass()),
diff --git a/chromium/webkit/browser/fileapi/file_writer_delegate.h b/chromium/webkit/browser/fileapi/file_writer_delegate.h
index ae63e7f01de..f7ce16dfb6f 100644
--- a/chromium/webkit/browser/fileapi/file_writer_delegate.h
+++ b/chromium/webkit/browser/fileapi/file_writer_delegate.h
@@ -34,7 +34,7 @@ class WEBKIT_STORAGE_BROWSER_EXPORT_PRIVATE FileWriterDelegate
WriteProgressStatus write_status)>
DelegateWriteCallback;
- FileWriterDelegate(scoped_ptr<FileStreamWriter> file_writer);
+ explicit FileWriterDelegate(scoped_ptr<FileStreamWriter> file_writer);
virtual ~FileWriterDelegate();
void Start(scoped_ptr<net::URLRequest> request,
diff --git a/chromium/webkit/browser/fileapi/file_writer_delegate_unittest.cc b/chromium/webkit/browser/fileapi/file_writer_delegate_unittest.cc
deleted file mode 100644
index 28c93e8a0db..00000000000
--- a/chromium/webkit/browser/fileapi/file_writer_delegate_unittest.cc
+++ /dev/null
@@ -1,454 +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 <string>
-#include <vector>
-
-#include "base/basictypes.h"
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/files/scoped_temp_dir.h"
-#include "base/run_loop.h"
-#include "net/base/io_buffer.h"
-#include "net/url_request/url_request.h"
-#include "net/url_request/url_request_context.h"
-#include "net/url_request/url_request_job.h"
-#include "net/url_request/url_request_status.h"
-#include "testing/platform_test.h"
-#include "url/gurl.h"
-#include "webkit/browser/fileapi/async_file_test_helper.h"
-#include "webkit/browser/fileapi/file_system_context.h"
-#include "webkit/browser/fileapi/file_system_quota_util.h"
-#include "webkit/browser/fileapi/file_writer_delegate.h"
-#include "webkit/browser/fileapi/mock_file_system_context.h"
-#include "webkit/browser/fileapi/sandbox_file_stream_writer.h"
-
-namespace fileapi {
-
-namespace {
-
-const GURL kOrigin("http://example.com");
-const FileSystemType kFileSystemType = kFileSystemTypeTest;
-
-const char kData[] = "The quick brown fox jumps over the lazy dog.\n";
-const int kDataSize = ARRAYSIZE_UNSAFE(kData) - 1;
-
-class Result {
- public:
- Result()
- : status_(base::PLATFORM_FILE_OK),
- bytes_written_(0),
- write_status_(FileWriterDelegate::SUCCESS_IO_PENDING) {}
-
- base::PlatformFileError status() const { return status_; }
- int64 bytes_written() const { return bytes_written_; }
- FileWriterDelegate::WriteProgressStatus write_status() const {
- return write_status_;
- }
-
- void DidWrite(base::PlatformFileError status, int64 bytes,
- FileWriterDelegate::WriteProgressStatus write_status) {
- write_status_ = write_status;
- if (status == base::PLATFORM_FILE_OK) {
- bytes_written_ += bytes;
- if (write_status_ != FileWriterDelegate::SUCCESS_IO_PENDING)
- base::MessageLoop::current()->Quit();
- } else {
- EXPECT_EQ(base::PLATFORM_FILE_OK, status_);
- status_ = status;
- base::MessageLoop::current()->Quit();
- }
- }
-
- private:
- // For post-operation status.
- base::PlatformFileError status_;
- int64 bytes_written_;
- FileWriterDelegate::WriteProgressStatus write_status_;
-};
-
-} // namespace (anonymous)
-
-class FileWriterDelegateTest : public PlatformTest {
- public:
- FileWriterDelegateTest()
- : loop_(base::MessageLoop::TYPE_IO) {}
-
- protected:
- virtual void SetUp() OVERRIDE;
- virtual void TearDown() OVERRIDE;
-
- int64 usage() {
- return file_system_context_->GetQuotaUtil(kFileSystemType)
- ->GetOriginUsageOnFileThread(
- file_system_context_.get(), kOrigin, kFileSystemType);
- }
-
- int64 GetFileSizeOnDisk(const char* test_file_path) {
- // There might be in-flight flush/write.
- base::MessageLoop::current()->PostTask(
- FROM_HERE, base::Bind(&base::DoNothing));
- base::RunLoop().RunUntilIdle();
-
- FileSystemURL url = GetFileSystemURL(test_file_path);
- base::PlatformFileInfo file_info;
- EXPECT_EQ(base::PLATFORM_FILE_OK,
- AsyncFileTestHelper::GetMetadata(
- file_system_context_, url, &file_info));
- return file_info.size;
- }
-
- FileSystemURL GetFileSystemURL(const char* file_name) const {
- return file_system_context_->CreateCrackedFileSystemURL(
- kOrigin, kFileSystemType, base::FilePath().FromUTF8Unsafe(file_name));
- }
-
- FileWriterDelegate* CreateWriterDelegate(
- const char* test_file_path,
- int64 offset,
- int64 allowed_growth) {
- SandboxFileStreamWriter* writer = new SandboxFileStreamWriter(
- file_system_context_.get(),
- GetFileSystemURL(test_file_path),
- offset,
- *file_system_context_->GetUpdateObservers(kFileSystemType));
- writer->set_default_quota(allowed_growth);
- return new FileWriterDelegate(scoped_ptr<FileStreamWriter>(writer));
- }
-
- FileWriterDelegate::DelegateWriteCallback GetWriteCallback(Result* result) {
- return base::Bind(&Result::DidWrite, base::Unretained(result));
- }
-
- // Creates and sets up a FileWriterDelegate for writing the given |blob_url|,
- // and creates a new FileWriterDelegate for the file.
- void PrepareForWrite(const char* test_file_path,
- const GURL& blob_url,
- int64 offset,
- int64 allowed_growth) {
- file_writer_delegate_.reset(
- CreateWriterDelegate(test_file_path, offset, allowed_growth));
- request_.reset(empty_context_.CreateRequest(
- blob_url, file_writer_delegate_.get()));
- }
-
- static net::URLRequest::ProtocolFactory Factory;
-
- // This should be alive until the very end of this instance.
- base::MessageLoop loop_;
-
- scoped_refptr<FileSystemContext> file_system_context_;
-
- net::URLRequestContext empty_context_;
- scoped_ptr<FileWriterDelegate> file_writer_delegate_;
- scoped_ptr<net::URLRequest> request_;
-
- base::ScopedTempDir dir_;
-
- static const char* content_;
-};
-
-const char* FileWriterDelegateTest::content_ = NULL;
-
-namespace {
-
-static std::string g_content;
-
-class FileWriterDelegateTestJob : public net::URLRequestJob {
- public:
- FileWriterDelegateTestJob(net::URLRequest* request,
- net::NetworkDelegate* network_delegate,
- const std::string& content)
- : net::URLRequestJob(request, network_delegate),
- content_(content),
- remaining_bytes_(content.length()),
- cursor_(0) {
- }
-
- virtual void Start() OVERRIDE {
- base::MessageLoop::current()->PostTask(
- FROM_HERE,
- base::Bind(&FileWriterDelegateTestJob::NotifyHeadersComplete, this));
- }
-
- virtual bool ReadRawData(net::IOBuffer* buf,
- int buf_size,
- int *bytes_read) OVERRIDE {
- if (remaining_bytes_ < buf_size)
- buf_size = static_cast<int>(remaining_bytes_);
-
- for (int i = 0; i < buf_size; ++i)
- buf->data()[i] = content_[cursor_++];
- remaining_bytes_ -= buf_size;
-
- SetStatus(net::URLRequestStatus());
- *bytes_read = buf_size;
- return true;
- }
-
- virtual int GetResponseCode() const OVERRIDE {
- return 200;
- }
-
- protected:
- virtual ~FileWriterDelegateTestJob() {}
-
- private:
- std::string content_;
- int remaining_bytes_;
- int cursor_;
-};
-
-} // namespace (anonymous)
-
-// static
-net::URLRequestJob* FileWriterDelegateTest::Factory(
- net::URLRequest* request,
- net::NetworkDelegate* network_delegate,
- const std::string& scheme) {
- return new FileWriterDelegateTestJob(
- request, network_delegate, FileWriterDelegateTest::content_);
-}
-
-void FileWriterDelegateTest::SetUp() {
- ASSERT_TRUE(dir_.CreateUniqueTempDir());
-
- file_system_context_ = CreateFileSystemContextForTesting(
- NULL, dir_.path());
- ASSERT_EQ(base::PLATFORM_FILE_OK,
- AsyncFileTestHelper::CreateFile(
- file_system_context_, GetFileSystemURL("test")));
- net::URLRequest::Deprecated::RegisterProtocolFactory("blob", &Factory);
-}
-
-void FileWriterDelegateTest::TearDown() {
- net::URLRequest::Deprecated::RegisterProtocolFactory("blob", NULL);
- file_system_context_ = NULL;
- base::RunLoop().RunUntilIdle();
-}
-
-TEST_F(FileWriterDelegateTest, WriteSuccessWithoutQuotaLimit) {
- const GURL kBlobURL("blob:nolimit");
- content_ = kData;
-
- PrepareForWrite("test", kBlobURL, 0, kint64max);
-
- Result result;
- ASSERT_EQ(0, usage());
- file_writer_delegate_->Start(request_.Pass(), GetWriteCallback(&result));
- base::MessageLoop::current()->Run();
-
- ASSERT_EQ(FileWriterDelegate::SUCCESS_COMPLETED, result.write_status());
- file_writer_delegate_.reset();
-
- ASSERT_EQ(kDataSize, usage());
- EXPECT_EQ(GetFileSizeOnDisk("test"), usage());
- EXPECT_EQ(kDataSize, result.bytes_written());
- EXPECT_EQ(base::PLATFORM_FILE_OK, result.status());
-}
-
-TEST_F(FileWriterDelegateTest, WriteSuccessWithJustQuota) {
- const GURL kBlobURL("blob:just");
- content_ = kData;
- const int64 kAllowedGrowth = kDataSize;
- PrepareForWrite("test", kBlobURL, 0, kAllowedGrowth);
-
- Result result;
- ASSERT_EQ(0, usage());
- file_writer_delegate_->Start(request_.Pass(), GetWriteCallback(&result));
- base::MessageLoop::current()->Run();
- ASSERT_EQ(FileWriterDelegate::SUCCESS_COMPLETED, result.write_status());
- file_writer_delegate_.reset();
-
- ASSERT_EQ(kAllowedGrowth, usage());
- EXPECT_EQ(GetFileSizeOnDisk("test"), usage());
-
- EXPECT_EQ(kAllowedGrowth, result.bytes_written());
- EXPECT_EQ(base::PLATFORM_FILE_OK, result.status());
-}
-
-TEST_F(FileWriterDelegateTest, DISABLED_WriteFailureByQuota) {
- const GURL kBlobURL("blob:failure");
- content_ = kData;
- const int64 kAllowedGrowth = kDataSize - 1;
- PrepareForWrite("test", kBlobURL, 0, kAllowedGrowth);
-
- Result result;
- ASSERT_EQ(0, usage());
- file_writer_delegate_->Start(request_.Pass(), GetWriteCallback(&result));
- base::MessageLoop::current()->Run();
- ASSERT_EQ(FileWriterDelegate::ERROR_WRITE_STARTED, result.write_status());
- file_writer_delegate_.reset();
-
- ASSERT_EQ(kAllowedGrowth, usage());
- EXPECT_EQ(GetFileSizeOnDisk("test"), usage());
-
- EXPECT_EQ(kAllowedGrowth, result.bytes_written());
- EXPECT_EQ(base::PLATFORM_FILE_ERROR_NO_SPACE, result.status());
- ASSERT_EQ(FileWriterDelegate::ERROR_WRITE_STARTED, result.write_status());
-}
-
-TEST_F(FileWriterDelegateTest, WriteZeroBytesSuccessfullyWithZeroQuota) {
- const GURL kBlobURL("blob:zero");
- content_ = "";
- int64 kAllowedGrowth = 0;
- PrepareForWrite("test", kBlobURL, 0, kAllowedGrowth);
-
- Result result;
- ASSERT_EQ(0, usage());
- file_writer_delegate_->Start(request_.Pass(), GetWriteCallback(&result));
- base::MessageLoop::current()->Run();
- ASSERT_EQ(FileWriterDelegate::SUCCESS_COMPLETED, result.write_status());
- file_writer_delegate_.reset();
-
- ASSERT_EQ(kAllowedGrowth, usage());
- EXPECT_EQ(GetFileSizeOnDisk("test"), usage());
-
- EXPECT_EQ(kAllowedGrowth, result.bytes_written());
- EXPECT_EQ(base::PLATFORM_FILE_OK, result.status());
- ASSERT_EQ(FileWriterDelegate::SUCCESS_COMPLETED, result.write_status());
-}
-
-TEST_F(FileWriterDelegateTest, WriteSuccessWithoutQuotaLimitConcurrent) {
- scoped_ptr<FileWriterDelegate> file_writer_delegate2;
- scoped_ptr<net::URLRequest> request2;
-
- ASSERT_EQ(base::PLATFORM_FILE_OK,
- AsyncFileTestHelper::CreateFile(
- file_system_context_, GetFileSystemURL("test2")));
-
- const GURL kBlobURL("blob:nolimitconcurrent");
- const GURL kBlobURL2("blob:nolimitconcurrent2");
- content_ = kData;
-
- PrepareForWrite("test", kBlobURL, 0, kint64max);
-
- // Credate another FileWriterDelegate for concurrent write.
- file_writer_delegate2.reset(CreateWriterDelegate("test2", 0, kint64max));
- request2.reset(empty_context_.CreateRequest(
- kBlobURL2, file_writer_delegate2.get()));
-
- Result result, result2;
- ASSERT_EQ(0, usage());
- file_writer_delegate_->Start(request_.Pass(), GetWriteCallback(&result));
- file_writer_delegate2->Start(request2.Pass(), GetWriteCallback(&result2));
- base::MessageLoop::current()->Run();
- if (result.write_status() == FileWriterDelegate::SUCCESS_IO_PENDING ||
- result2.write_status() == FileWriterDelegate::SUCCESS_IO_PENDING)
- base::MessageLoop::current()->Run();
-
- ASSERT_EQ(FileWriterDelegate::SUCCESS_COMPLETED, result.write_status());
- ASSERT_EQ(FileWriterDelegate::SUCCESS_COMPLETED, result2.write_status());
- file_writer_delegate_.reset();
- file_writer_delegate2.reset();
-
- ASSERT_EQ(kDataSize * 2, usage());
- EXPECT_EQ(GetFileSizeOnDisk("test") + GetFileSizeOnDisk("test2"), usage());
-
- EXPECT_EQ(kDataSize, result.bytes_written());
- EXPECT_EQ(base::PLATFORM_FILE_OK, result.status());
- EXPECT_EQ(kDataSize, result2.bytes_written());
- EXPECT_EQ(base::PLATFORM_FILE_OK, result2.status());
-}
-
-TEST_F(FileWriterDelegateTest, WritesWithQuotaAndOffset) {
- const GURL kBlobURL("blob:failure-with-updated-quota");
- content_ = kData;
-
- // Writing kDataSize (=45) bytes data while allowed_growth is 100.
- int64 offset = 0;
- int64 allowed_growth = 100;
- ASSERT_LT(kDataSize, allowed_growth);
- PrepareForWrite("test", kBlobURL, offset, allowed_growth);
-
- {
- Result result;
- ASSERT_EQ(0, usage());
- file_writer_delegate_->Start(request_.Pass(), GetWriteCallback(&result));
- base::MessageLoop::current()->Run();
- ASSERT_EQ(FileWriterDelegate::SUCCESS_COMPLETED, result.write_status());
- file_writer_delegate_.reset();
-
- ASSERT_EQ(kDataSize, usage());
- EXPECT_EQ(GetFileSizeOnDisk("test"), usage());
- EXPECT_EQ(kDataSize, result.bytes_written());
- EXPECT_EQ(base::PLATFORM_FILE_OK, result.status());
- }
-
- // Trying to overwrite kDataSize bytes data while allowed_growth is 20.
- offset = 0;
- allowed_growth = 20;
- PrepareForWrite("test", kBlobURL, offset, allowed_growth);
-
- {
- Result result;
- file_writer_delegate_->Start(request_.Pass(), GetWriteCallback(&result));
- base::MessageLoop::current()->Run();
- EXPECT_EQ(kDataSize, usage());
- EXPECT_EQ(GetFileSizeOnDisk("test"), usage());
- EXPECT_EQ(kDataSize, result.bytes_written());
- EXPECT_EQ(base::PLATFORM_FILE_OK, result.status());
- ASSERT_EQ(FileWriterDelegate::SUCCESS_COMPLETED, result.write_status());
- }
-
- // Trying to write kDataSize bytes data from offset 25 while
- // allowed_growth is 55.
- offset = 25;
- allowed_growth = 55;
- PrepareForWrite("test", kBlobURL, offset, allowed_growth);
-
- {
- Result result;
- file_writer_delegate_->Start(request_.Pass(), GetWriteCallback(&result));
- base::MessageLoop::current()->Run();
- ASSERT_EQ(FileWriterDelegate::SUCCESS_COMPLETED, result.write_status());
- file_writer_delegate_.reset();
-
- EXPECT_EQ(offset + kDataSize, usage());
- EXPECT_EQ(GetFileSizeOnDisk("test"), usage());
- EXPECT_EQ(kDataSize, result.bytes_written());
- EXPECT_EQ(base::PLATFORM_FILE_OK, result.status());
- }
-
- // Trying to overwrite 45 bytes data while allowed_growth is -20.
- offset = 0;
- allowed_growth = -20;
- PrepareForWrite("test", kBlobURL, offset, allowed_growth);
- int64 pre_write_usage = GetFileSizeOnDisk("test");
-
- {
- Result result;
- file_writer_delegate_->Start(request_.Pass(), GetWriteCallback(&result));
- base::MessageLoop::current()->Run();
- ASSERT_EQ(FileWriterDelegate::SUCCESS_COMPLETED, result.write_status());
- file_writer_delegate_.reset();
-
- EXPECT_EQ(pre_write_usage, usage());
- EXPECT_EQ(GetFileSizeOnDisk("test"), usage());
- EXPECT_EQ(kDataSize, result.bytes_written());
- EXPECT_EQ(base::PLATFORM_FILE_OK, result.status());
- }
-
- // Trying to overwrite 45 bytes data with offset pre_write_usage - 20,
- // while allowed_growth is 10.
- const int kOverlap = 20;
- offset = pre_write_usage - kOverlap;
- allowed_growth = 10;
- PrepareForWrite("test", kBlobURL, offset, allowed_growth);
-
- {
- Result result;
- file_writer_delegate_->Start(request_.Pass(), GetWriteCallback(&result));
- base::MessageLoop::current()->Run();
- ASSERT_EQ(FileWriterDelegate::ERROR_WRITE_STARTED, result.write_status());
- file_writer_delegate_.reset();
-
- EXPECT_EQ(pre_write_usage + allowed_growth, usage());
- EXPECT_EQ(GetFileSizeOnDisk("test"), usage());
- EXPECT_EQ(kOverlap + allowed_growth, result.bytes_written());
- EXPECT_EQ(base::PLATFORM_FILE_ERROR_NO_SPACE, result.status());
- }
-}
-
-} // namespace fileapi
diff --git a/chromium/webkit/browser/fileapi/isolated_context.cc b/chromium/webkit/browser/fileapi/isolated_context.cc
index d10438aa046..74716104154 100644
--- a/chromium/webkit/browser/fileapi/isolated_context.cc
+++ b/chromium/webkit/browser/fileapi/isolated_context.cc
@@ -26,8 +26,8 @@ base::FilePath::StringType GetRegisterNameForPath(const base::FilePath& path) {
#if defined(FILE_PATH_USES_DRIVE_LETTERS)
base::FilePath::StringType name;
for (size_t i = 0;
- i < path.value().size() && !base::FilePath::IsSeparator(path.value()[i]);
- ++i) {
+ i < path.value().size() && !base::FilePath::IsSeparator(path.value()[i]);
+ ++i) {
if (path.value()[i] == L':') {
name.append(L"_drive");
break;
@@ -78,8 +78,10 @@ bool IsolatedContext::FileInfoSet::AddPath(
fileset_.insert(MountPointInfo(utf8name, normalized_path)).second;
if (!inserted) {
int suffix = 1;
- std::string basepart = base::FilePath(name).RemoveExtension().AsUTF8Unsafe();
- std::string ext = base::FilePath(base::FilePath(name).Extension()).AsUTF8Unsafe();
+ std::string basepart =
+ base::FilePath(name).RemoveExtension().AsUTF8Unsafe();
+ std::string ext =
+ base::FilePath(base::FilePath(name).Extension()).AsUTF8Unsafe();
while (!inserted) {
utf8name = base::StringPrintf("%s (%d)", basepart.c_str(), suffix++);
if (!ext.empty())
@@ -286,10 +288,12 @@ bool IsolatedContext::GetRegisteredPath(
return true;
}
-bool IsolatedContext::CrackVirtualPath(const base::FilePath& virtual_path,
- std::string* id_or_name,
- FileSystemType* type,
- base::FilePath* path) const {
+bool IsolatedContext::CrackVirtualPath(
+ const base::FilePath& virtual_path,
+ std::string* id_or_name,
+ FileSystemType* type,
+ base::FilePath* path,
+ FileSystemMountOption* mount_option) const {
DCHECK(id_or_name);
DCHECK(path);
@@ -297,6 +301,9 @@ bool IsolatedContext::CrackVirtualPath(const base::FilePath& virtual_path,
if (virtual_path.ReferencesParent())
return false;
+ // Set the default mount option.
+ *mount_option = FileSystemMountOption();
+
// The virtual_path should comprise <id_or_name> and <relative_path> parts.
std::vector<base::FilePath::StringType> components;
virtual_path.GetComponents(&components);
@@ -426,13 +433,16 @@ FileSystemURL IsolatedContext::CrackFileSystemURL(
std::string mount_name;
FileSystemType cracked_type;
base::FilePath cracked_path;
- if (!CrackVirtualPath(url.path(), &mount_name, &cracked_type, &cracked_path))
+ FileSystemMountOption cracked_mount_option;
+ if (!CrackVirtualPath(url.path(), &mount_name, &cracked_type,
+ &cracked_path, &cracked_mount_option)) {
return FileSystemURL();
+ }
return FileSystemURL(
url.origin(), url.mount_type(), url.virtual_path(),
!url.filesystem_id().empty() ? url.filesystem_id() : mount_name,
- cracked_type, cracked_path, mount_name);
+ cracked_type, cracked_path, mount_name, cracked_mount_option);
}
bool IsolatedContext::UnregisterFileSystem(const std::string& filesystem_id) {
diff --git a/chromium/webkit/browser/fileapi/isolated_context.h b/chromium/webkit/browser/fileapi/isolated_context.h
index 6b3f85ad98e..2a4ae47dd0d 100644
--- a/chromium/webkit/browser/fileapi/isolated_context.h
+++ b/chromium/webkit/browser/fileapi/isolated_context.h
@@ -144,10 +144,12 @@ class WEBKIT_STORAGE_BROWSER_EXPORT IsolatedContext : public MountPoints {
virtual bool RevokeFileSystem(const std::string& filesystem_id) OVERRIDE;
virtual bool GetRegisteredPath(const std::string& filesystem_id,
base::FilePath* path) const OVERRIDE;
- virtual bool CrackVirtualPath(const base::FilePath& virtual_path,
- std::string* filesystem_id,
- FileSystemType* type,
- base::FilePath* path) const OVERRIDE;
+ virtual bool CrackVirtualPath(
+ const base::FilePath& virtual_path,
+ std::string* filesystem_id,
+ FileSystemType* type,
+ base::FilePath* path,
+ FileSystemMountOption* mount_option) const OVERRIDE;
virtual FileSystemURL CrackURL(const GURL& url) const OVERRIDE;
virtual FileSystemURL CreateCrackedFileSystemURL(
const GURL& origin,
diff --git a/chromium/webkit/browser/fileapi/isolated_context_unittest.cc b/chromium/webkit/browser/fileapi/isolated_context_unittest.cc
index 36073ca5f81..156181d6210 100644
--- a/chromium/webkit/browser/fileapi/isolated_context_unittest.cc
+++ b/chromium/webkit/browser/fileapi/isolated_context_unittest.cc
@@ -96,8 +96,10 @@ TEST_F(IsolatedContextTest, RegisterAndRevokeTest) {
std::string cracked_id;
base::FilePath cracked_path;
FileSystemType cracked_type;
+ FileSystemMountOption cracked_option;
ASSERT_TRUE(isolated_context()->CrackVirtualPath(
- virtual_path, &cracked_id, &cracked_type, &cracked_path));
+ virtual_path, &cracked_id, &cracked_type, &cracked_path,
+ &cracked_option));
ASSERT_EQ(kTestPaths[i].NormalizePathSeparators().value(),
cracked_path.value());
ASSERT_EQ(id_, cracked_id);
@@ -186,18 +188,22 @@ TEST_F(IsolatedContextTest, CrackWithRelativePaths) {
for (size_t j = 0; j < ARRAYSIZE_UNSAFE(relatives); ++j) {
SCOPED_TRACE(testing::Message() << "Testing "
<< kTestPaths[i].value() << " " << relatives[j].path);
- base::FilePath virtual_path = isolated_context()->CreateVirtualRootPath(id_)
- .AppendASCII(names_[i]).Append(relatives[j].path);
+ base::FilePath virtual_path =
+ isolated_context()->CreateVirtualRootPath(id_).AppendASCII(
+ names_[i]).Append(relatives[j].path);
std::string cracked_id;
base::FilePath cracked_path;
FileSystemType cracked_type;
+ FileSystemMountOption cracked_option;
if (!relatives[j].valid) {
ASSERT_FALSE(isolated_context()->CrackVirtualPath(
- virtual_path, &cracked_id, &cracked_type, &cracked_path));
+ virtual_path, &cracked_id, &cracked_type, &cracked_path,
+ &cracked_option));
continue;
}
ASSERT_TRUE(isolated_context()->CrackVirtualPath(
- virtual_path, &cracked_id, &cracked_type, &cracked_path));
+ virtual_path, &cracked_id, &cracked_type, &cracked_path,
+ &cracked_option));
ASSERT_EQ(kTestPaths[i].Append(relatives[j].path)
.NormalizePathSeparators().value(),
cracked_path.value());
@@ -230,8 +236,9 @@ TEST_F(IsolatedContextTest, CrackURLWithRelativePaths) {
for (size_t j = 0; j < ARRAYSIZE_UNSAFE(relatives); ++j) {
SCOPED_TRACE(testing::Message() << "Testing "
<< kTestPaths[i].value() << " " << relatives[j].path);
- base::FilePath virtual_path = isolated_context()->CreateVirtualRootPath(id_)
- .AppendASCII(names_[i]).Append(relatives[j].path);
+ base::FilePath virtual_path =
+ isolated_context()->CreateVirtualRootPath(id_).AppendASCII(
+ names_[i]).Append(relatives[j].path);
FileSystemURL cracked = isolated_context()->CreateCrackedFileSystemURL(
GURL("http://chromium.org"), kFileSystemTypeIsolated, virtual_path);
@@ -255,13 +262,14 @@ TEST_F(IsolatedContextTest, CrackURLWithRelativePaths) {
TEST_F(IsolatedContextTest, TestWithVirtualRoot) {
std::string cracked_id;
base::FilePath cracked_path;
+ FileSystemMountOption cracked_option;
// Trying to crack virtual root "/" returns true but with empty cracked path
// as "/" of the isolated filesystem is a pure virtual directory
// that has no corresponding platform directory.
base::FilePath virtual_path = isolated_context()->CreateVirtualRootPath(id_);
ASSERT_TRUE(isolated_context()->CrackVirtualPath(
- virtual_path, &cracked_id, NULL, &cracked_path));
+ virtual_path, &cracked_id, NULL, &cracked_path, &cracked_option));
ASSERT_EQ(FPL(""), cracked_path.value());
ASSERT_EQ(id_, cracked_id);
@@ -270,7 +278,7 @@ TEST_F(IsolatedContextTest, TestWithVirtualRoot) {
virtual_path = isolated_context()->CreateVirtualRootPath(
id_).AppendASCII("foo");
ASSERT_FALSE(isolated_context()->CrackVirtualPath(
- virtual_path, &cracked_id, NULL, &cracked_path));
+ virtual_path, &cracked_id, NULL, &cracked_path, &cracked_option));
}
TEST_F(IsolatedContextTest, CanHandleURL) {
@@ -327,8 +335,9 @@ TEST_F(IsolatedContextTest, VirtualFileSystemTests) {
std::string cracked_id;
base::FilePath cracked_path;
+ FileSystemMountOption cracked_option;
ASSERT_TRUE(isolated_context()->CrackVirtualPath(
- whole_virtual_path, &cracked_id, NULL, &cracked_path));
+ whole_virtual_path, &cracked_id, NULL, &cracked_path, &cracked_option));
ASSERT_EQ(database_fsid, cracked_id);
ASSERT_EQ(test_virtual_path, cracked_path);
}
diff --git a/chromium/webkit/browser/fileapi/local_file_stream_writer.cc b/chromium/webkit/browser/fileapi/local_file_stream_writer.cc
index 75c2cad8bae..1796de5f4e8 100644
--- a/chromium/webkit/browser/fileapi/local_file_stream_writer.cc
+++ b/chromium/webkit/browser/fileapi/local_file_stream_writer.cc
@@ -84,9 +84,9 @@ LocalFileStreamWriter::LocalFileStreamWriter(base::TaskRunner* task_runner,
int64 initial_offset)
: file_path_(file_path),
initial_offset_(initial_offset),
+ task_runner_(task_runner),
has_pending_operation_(false),
- weak_factory_(this),
- task_runner_(task_runner) {}
+ weak_factory_(this) {}
int LocalFileStreamWriter::InitiateOpen(
const net::CompletionCallback& error_callback,
diff --git a/chromium/webkit/browser/fileapi/local_file_stream_writer_unittest.cc b/chromium/webkit/browser/fileapi/local_file_stream_writer_unittest.cc
index cf3c06a18cd..96bccf64b26 100644
--- a/chromium/webkit/browser/fileapi/local_file_stream_writer_unittest.cc
+++ b/chromium/webkit/browser/fileapi/local_file_stream_writer_unittest.cc
@@ -23,8 +23,7 @@ namespace fileapi {
class LocalFileStreamWriterTest : public testing::Test {
public:
LocalFileStreamWriterTest()
- : message_loop_(base::MessageLoop::TYPE_IO),
- file_thread_("FileUtilProxyTestFileThread") {}
+ : file_thread_("FileUtilProxyTestFileThread") {}
virtual void SetUp() OVERRIDE {
ASSERT_TRUE(file_thread_.Start());
@@ -85,7 +84,7 @@ class LocalFileStreamWriterTest : public testing::Test {
}
private:
- base::MessageLoop message_loop_;
+ base::MessageLoopForIO message_loop_;
base::Thread file_thread_;
base::ScopedTempDir temp_dir_;
};
diff --git a/chromium/webkit/browser/fileapi/local_file_util.cc b/chromium/webkit/browser/fileapi/local_file_util.cc
index d2d653ac78c..8f47859a187 100644
--- a/chromium/webkit/browser/fileapi/local_file_util.cc
+++ b/chromium/webkit/browser/fileapi/local_file_util.cc
@@ -51,7 +51,7 @@ class LocalFileEnumerator : public FileSystemFileUtil::AbstractFileEnumerator {
base::FilePath LocalFileEnumerator::Next() {
base::FilePath next = file_enum_.Next();
// Don't return symlinks.
- while (!next.empty() && file_util::IsLink(next))
+ while (!next.empty() && base::IsLink(next))
next = file_enum_.Next();
if (next.empty())
return next;
@@ -88,7 +88,7 @@ PlatformFileError LocalFileUtil::CreateOrOpen(
if (error != base::PLATFORM_FILE_OK)
return error;
// Disallow opening files in symlinked paths.
- if (file_util::IsLink(file_path))
+ if (base::IsLink(file_path))
return base::PLATFORM_FILE_ERROR_NOT_FOUND;
return NativeFileUtil::CreateOrOpen(
file_path, file_flags, file_handle, created);
@@ -132,7 +132,7 @@ PlatformFileError LocalFileUtil::GetFileInfo(
if (error != base::PLATFORM_FILE_OK)
return error;
// We should not follow symbolic links in sandboxed file system.
- if (file_util::IsLink(file_path))
+ if (base::IsLink(file_path))
return base::PLATFORM_FILE_ERROR_NOT_FOUND;
error = NativeFileUtil::GetFileInfo(file_path, file_info);
if (error == base::PLATFORM_FILE_OK)
@@ -197,6 +197,7 @@ PlatformFileError LocalFileUtil::CopyOrMoveFile(
FileSystemOperationContext* context,
const FileSystemURL& src_url,
const FileSystemURL& dest_url,
+ CopyOrMoveOption option,
bool copy) {
base::FilePath src_file_path;
PlatformFileError error = GetLocalFilePath(context, src_url, &src_file_path);
@@ -208,7 +209,9 @@ PlatformFileError LocalFileUtil::CopyOrMoveFile(
if (error != base::PLATFORM_FILE_OK)
return error;
- return NativeFileUtil::CopyOrMoveFile(src_file_path, dest_file_path, copy);
+ return NativeFileUtil::CopyOrMoveFile(
+ src_file_path, dest_file_path, option,
+ fileapi::NativeFileUtil::CopyOrMoveModeForDestination(dest_url, copy));
}
PlatformFileError LocalFileUtil::CopyInForeignFile(
@@ -223,7 +226,10 @@ PlatformFileError LocalFileUtil::CopyInForeignFile(
GetLocalFilePath(context, dest_url, &dest_file_path);
if (error != base::PLATFORM_FILE_OK)
return error;
- return NativeFileUtil::CopyOrMoveFile(src_file_path, dest_file_path, true);
+ return NativeFileUtil::CopyOrMoveFile(
+ src_file_path, dest_file_path, FileSystemOperation::OPTION_NONE,
+ fileapi::NativeFileUtil::CopyOrMoveModeForDestination(dest_url,
+ true /* copy */));
}
PlatformFileError LocalFileUtil::DeleteFile(
diff --git a/chromium/webkit/browser/fileapi/local_file_util.h b/chromium/webkit/browser/fileapi/local_file_util.h
index 38f285a6b04..21efc72ffe4 100644
--- a/chromium/webkit/browser/fileapi/local_file_util.h
+++ b/chromium/webkit/browser/fileapi/local_file_util.h
@@ -72,6 +72,7 @@ class WEBKIT_STORAGE_BROWSER_EXPORT LocalFileUtil
FileSystemOperationContext* context,
const FileSystemURL& src_url,
const FileSystemURL& dest_url,
+ CopyOrMoveOption option,
bool copy) OVERRIDE;
virtual base::PlatformFileError CopyInForeignFile(
FileSystemOperationContext* context,
diff --git a/chromium/webkit/browser/fileapi/local_file_util_unittest.cc b/chromium/webkit/browser/fileapi/local_file_util_unittest.cc
deleted file mode 100644
index bdd2d879925..00000000000
--- a/chromium/webkit/browser/fileapi/local_file_util_unittest.cc
+++ /dev/null
@@ -1,388 +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 <string>
-
-#include "base/file_util.h"
-#include "base/files/file_path.h"
-#include "base/files/scoped_temp_dir.h"
-#include "base/message_loop/message_loop_proxy.h"
-#include "base/platform_file.h"
-#include "base/run_loop.h"
-#include "base/strings/sys_string_conversions.h"
-#include "base/strings/utf_string_conversions.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "webkit/browser/fileapi/async_file_test_helper.h"
-#include "webkit/browser/fileapi/async_file_util_adapter.h"
-#include "webkit/browser/fileapi/file_system_context.h"
-#include "webkit/browser/fileapi/file_system_file_util.h"
-#include "webkit/browser/fileapi/file_system_operation_context.h"
-#include "webkit/browser/fileapi/local_file_util.h"
-#include "webkit/browser/fileapi/mock_file_system_context.h"
-#include "webkit/browser/fileapi/native_file_util.h"
-#include "webkit/common/fileapi/file_system_types.h"
-
-namespace fileapi {
-
-namespace {
-
-const GURL kOrigin("http://foo/");
-const FileSystemType kFileSystemType = kFileSystemTypeTest;
-
-} // namespace
-
-class LocalFileUtilTest : public testing::Test {
- public:
- LocalFileUtilTest() {}
-
- virtual void SetUp() {
- ASSERT_TRUE(data_dir_.CreateUniqueTempDir());
- file_system_context_ = CreateFileSystemContextForTesting(
- NULL, data_dir_.path());
- }
-
- virtual void TearDown() {
- file_system_context_ = NULL;
- base::RunLoop().RunUntilIdle();
- }
-
- protected:
- FileSystemOperationContext* NewContext() {
- FileSystemOperationContext* context =
- new FileSystemOperationContext(file_system_context_.get());
- context->set_update_observers(
- *file_system_context_->GetUpdateObservers(kFileSystemType));
- return context;
- }
-
- LocalFileUtil* file_util() {
- AsyncFileUtilAdapter* adapter = static_cast<AsyncFileUtilAdapter*>(
- file_system_context_->GetAsyncFileUtil(kFileSystemType));
- return static_cast<LocalFileUtil*>(adapter->sync_file_util());
- }
-
- FileSystemURL CreateURL(const std::string& file_name) {
- return file_system_context_->CreateCrackedFileSystemURL(
- kOrigin, kFileSystemType, base::FilePath().FromUTF8Unsafe(file_name));
- }
-
- base::FilePath LocalPath(const char *file_name) {
- base::FilePath path;
- scoped_ptr<FileSystemOperationContext> context(NewContext());
- file_util()->GetLocalFilePath(context.get(), CreateURL(file_name), &path);
- return path;
- }
-
- bool FileExists(const char *file_name) {
- return base::PathExists(LocalPath(file_name)) &&
- !base::DirectoryExists(LocalPath(file_name));
- }
-
- bool DirectoryExists(const char *file_name) {
- return base::DirectoryExists(LocalPath(file_name));
- }
-
- int64 GetSize(const char *file_name) {
- base::PlatformFileInfo info;
- file_util::GetFileInfo(LocalPath(file_name), &info);
- return info.size;
- }
-
- 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 file_util()->CreateOrOpen(
- context.get(),
- CreateURL(file_name),
- file_flags, file_handle, created);
- }
-
- base::PlatformFileError EnsureFileExists(const char* file_name,
- bool* created) {
- scoped_ptr<FileSystemOperationContext> context(NewContext());
- return file_util()->EnsureFileExists(
- context.get(),
- CreateURL(file_name), created);
- }
-
- FileSystemContext* file_system_context() {
- return file_system_context_.get();
- }
-
- private:
- base::MessageLoop message_loop_;
- scoped_refptr<FileSystemContext> file_system_context_;
- base::ScopedTempDir data_dir_;
-
- DISALLOW_COPY_AND_ASSIGN(LocalFileUtilTest);
-};
-
-TEST_F(LocalFileUtilTest, 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);
-
- EXPECT_TRUE(FileExists(file_name));
- EXPECT_EQ(0, GetSize(file_name));
-
- scoped_ptr<FileSystemOperationContext> context(NewContext());
- EXPECT_EQ(base::PLATFORM_FILE_OK,
- file_util()->Close(context.get(), file_handle));
-}
-
-// file_util::CreateSymbolicLink is only supported on POSIX.
-#if defined(OS_POSIX)
-TEST_F(LocalFileUtilTest, CreateFailForSymlink) {
- // Create symlink target file.
- const char *target_name = "symlink_target";
- base::PlatformFile target_handle;
- bool symlink_target_created = false;
- ASSERT_EQ(base::PLATFORM_FILE_OK,
- CreateFile(target_name, &target_handle, &symlink_target_created));
- ASSERT_TRUE(symlink_target_created);
- base::FilePath target_path = LocalPath(target_name);
-
- // Create symlink where target must be real file.
- const char *symlink_name = "symlink_file";
- base::FilePath symlink_path = LocalPath(symlink_name);
- ASSERT_TRUE(file_util::CreateSymbolicLink(target_path, symlink_path));
- ASSERT_TRUE(FileExists(symlink_name));
-
- // Try to open the symlink file which should fail.
- scoped_ptr<FileSystemOperationContext> context(NewContext());
- FileSystemURL url = CreateURL(symlink_name);
- int file_flags = base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ;
- base::PlatformFile file_handle;
- bool created = false;
- EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, file_util()->CreateOrOpen(
- context.get(), url, file_flags, &file_handle, &created));
- EXPECT_FALSE(created);
-}
-#endif
-
-TEST_F(LocalFileUtilTest, EnsureFileExists) {
- const char *file_name = "foobar";
- bool created;
- ASSERT_EQ(base::PLATFORM_FILE_OK, EnsureFileExists(file_name, &created));
- ASSERT_TRUE(created);
-
- EXPECT_TRUE(FileExists(file_name));
- EXPECT_EQ(0, GetSize(file_name));
-
- ASSERT_EQ(base::PLATFORM_FILE_OK, EnsureFileExists(file_name, &created));
- EXPECT_FALSE(created);
-}
-
-TEST_F(LocalFileUtilTest, TouchFile) {
- 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());
-
- base::PlatformFileInfo info;
- ASSERT_TRUE(file_util::GetFileInfo(LocalPath(file_name), &info));
- const base::Time new_accessed =
- info.last_accessed + base::TimeDelta::FromHours(10);
- const base::Time new_modified =
- info.last_modified + base::TimeDelta::FromHours(5);
-
- EXPECT_EQ(base::PLATFORM_FILE_OK,
- file_util()->Touch(context.get(), CreateURL(file_name),
- new_accessed, new_modified));
-
- ASSERT_TRUE(file_util::GetFileInfo(LocalPath(file_name), &info));
- EXPECT_EQ(new_accessed, info.last_accessed);
- EXPECT_EQ(new_modified, info.last_modified);
-
- EXPECT_EQ(base::PLATFORM_FILE_OK,
- file_util()->Close(context.get(), file_handle));
-}
-
-TEST_F(LocalFileUtilTest, TouchDirectory) {
- const char *dir_name = "test_dir";
- scoped_ptr<FileSystemOperationContext> context(NewContext());
- ASSERT_EQ(base::PLATFORM_FILE_OK,
- file_util()->CreateDirectory(context.get(),
- CreateURL(dir_name),
- false /* exclusive */,
- false /* recursive */));
-
- base::PlatformFileInfo info;
- ASSERT_TRUE(file_util::GetFileInfo(LocalPath(dir_name), &info));
- const base::Time new_accessed =
- info.last_accessed + base::TimeDelta::FromHours(10);
- const base::Time new_modified =
- info.last_modified + base::TimeDelta::FromHours(5);
-
- EXPECT_EQ(base::PLATFORM_FILE_OK,
- file_util()->Touch(context.get(), CreateURL(dir_name),
- new_accessed, new_modified));
-
- ASSERT_TRUE(file_util::GetFileInfo(LocalPath(dir_name), &info));
- EXPECT_EQ(new_accessed, info.last_accessed);
- EXPECT_EQ(new_modified, info.last_modified);
-}
-
-TEST_F(LocalFileUtilTest, Truncate) {
- const char *file_name = "truncated";
- bool created;
- ASSERT_EQ(base::PLATFORM_FILE_OK, EnsureFileExists(file_name, &created));
- ASSERT_TRUE(created);
-
- scoped_ptr<FileSystemOperationContext> context;
-
- context.reset(NewContext());
- ASSERT_EQ(base::PLATFORM_FILE_OK,
- file_util()->Truncate(context.get(), CreateURL(file_name), 1020));
-
- EXPECT_TRUE(FileExists(file_name));
- EXPECT_EQ(1020, GetSize(file_name));
-}
-
-TEST_F(LocalFileUtilTest, CopyFile) {
- const char *from_file = "fromfile";
- 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);
-
- scoped_ptr<FileSystemOperationContext> context;
- context.reset(NewContext());
- ASSERT_EQ(base::PLATFORM_FILE_OK,
- file_util()->Truncate(context.get(), CreateURL(from_file), 1020));
-
- EXPECT_TRUE(FileExists(from_file));
- EXPECT_EQ(1020, GetSize(from_file));
-
- ASSERT_EQ(base::PLATFORM_FILE_OK,
- AsyncFileTestHelper::Copy(file_system_context(),
- CreateURL(from_file),
- CreateURL(to_file1)));
-
- context.reset(NewContext());
- ASSERT_EQ(base::PLATFORM_FILE_OK,
- AsyncFileTestHelper::Copy(file_system_context(),
- CreateURL(from_file),
- CreateURL(to_file2)));
-
- EXPECT_TRUE(FileExists(from_file));
- EXPECT_EQ(1020, GetSize(from_file));
- EXPECT_TRUE(FileExists(to_file1));
- EXPECT_EQ(1020, GetSize(to_file1));
- EXPECT_TRUE(FileExists(to_file2));
- EXPECT_EQ(1020, GetSize(to_file2));
-}
-
-TEST_F(LocalFileUtilTest, CopyDirectory) {
- const char *from_dir = "fromdir";
- const char *from_file = "fromdir/fromfile";
- const char *to_dir = "todir";
- const char *to_file = "todir/fromfile";
- bool created;
- scoped_ptr<FileSystemOperationContext> context;
-
- context.reset(NewContext());
- ASSERT_EQ(base::PLATFORM_FILE_OK,
- file_util()->CreateDirectory(context.get(), CreateURL(from_dir),
- false, false));
- ASSERT_EQ(base::PLATFORM_FILE_OK, EnsureFileExists(from_file, &created));
- ASSERT_TRUE(created);
-
- context.reset(NewContext());
- ASSERT_EQ(base::PLATFORM_FILE_OK,
- file_util()->Truncate(context.get(), CreateURL(from_file), 1020));
-
- EXPECT_TRUE(DirectoryExists(from_dir));
- EXPECT_TRUE(FileExists(from_file));
- EXPECT_EQ(1020, GetSize(from_file));
- EXPECT_FALSE(DirectoryExists(to_dir));
-
- context.reset(NewContext());
- ASSERT_EQ(base::PLATFORM_FILE_OK,
- AsyncFileTestHelper::Copy(file_system_context(),
- CreateURL(from_dir), CreateURL(to_dir)));
-
- EXPECT_TRUE(DirectoryExists(from_dir));
- EXPECT_TRUE(FileExists(from_file));
- EXPECT_EQ(1020, GetSize(from_file));
- EXPECT_TRUE(DirectoryExists(to_dir));
- EXPECT_TRUE(FileExists(to_file));
- EXPECT_EQ(1020, GetSize(to_file));
-}
-
-TEST_F(LocalFileUtilTest, MoveFile) {
- const char *from_file = "fromfile";
- 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());
- ASSERT_EQ(base::PLATFORM_FILE_OK,
- file_util()->Truncate(context.get(), CreateURL(from_file), 1020));
-
- EXPECT_TRUE(FileExists(from_file));
- EXPECT_EQ(1020, GetSize(from_file));
-
- context.reset(NewContext());
- ASSERT_EQ(base::PLATFORM_FILE_OK,
- AsyncFileTestHelper::Move(file_system_context(),
- CreateURL(from_file),
- CreateURL(to_file)));
-
- EXPECT_FALSE(FileExists(from_file));
- EXPECT_TRUE(FileExists(to_file));
- EXPECT_EQ(1020, GetSize(to_file));
-}
-
-TEST_F(LocalFileUtilTest, MoveDirectory) {
- const char *from_dir = "fromdir";
- const char *from_file = "fromdir/fromfile";
- const char *to_dir = "todir";
- const char *to_file = "todir/fromfile";
- bool created;
- scoped_ptr<FileSystemOperationContext> context;
-
- context.reset(NewContext());
- ASSERT_EQ(base::PLATFORM_FILE_OK,
- file_util()->CreateDirectory(context.get(), CreateURL(from_dir),
- false, false));
- ASSERT_EQ(base::PLATFORM_FILE_OK, EnsureFileExists(from_file, &created));
- ASSERT_TRUE(created);
-
- context.reset(NewContext());
- ASSERT_EQ(base::PLATFORM_FILE_OK,
- file_util()->Truncate(context.get(), CreateURL(from_file), 1020));
-
- EXPECT_TRUE(DirectoryExists(from_dir));
- EXPECT_TRUE(FileExists(from_file));
- EXPECT_EQ(1020, GetSize(from_file));
- EXPECT_FALSE(DirectoryExists(to_dir));
-
- context.reset(NewContext());
- ASSERT_EQ(base::PLATFORM_FILE_OK,
- AsyncFileTestHelper::Move(file_system_context(),
- CreateURL(from_dir),
- CreateURL(to_dir)));
-
- EXPECT_FALSE(DirectoryExists(from_dir));
- EXPECT_TRUE(DirectoryExists(to_dir));
- EXPECT_TRUE(FileExists(to_file));
- EXPECT_EQ(1020, GetSize(to_file));
-}
-
-} // namespace fileapi
diff --git a/chromium/webkit/browser/fileapi/mock_file_system_context.cc b/chromium/webkit/browser/fileapi/mock_file_system_context.cc
deleted file mode 100644
index ed1715c2bbe..00000000000
--- a/chromium/webkit/browser/fileapi/mock_file_system_context.cc
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "webkit/browser/fileapi/mock_file_system_context.h"
-
-#include "base/memory/scoped_vector.h"
-#include "webkit/browser/fileapi/external_mount_points.h"
-#include "webkit/browser/fileapi/file_system_backend.h"
-#include "webkit/browser/fileapi/file_system_context.h"
-#include "webkit/browser/fileapi/mock_file_system_options.h"
-#include "webkit/browser/fileapi/test_file_system_backend.h"
-#include "webkit/browser/quota/mock_special_storage_policy.h"
-
-namespace fileapi {
-
-FileSystemContext* CreateFileSystemContextForTesting(
- quota::QuotaManagerProxy* quota_manager_proxy,
- const base::FilePath& base_path) {
- ScopedVector<FileSystemBackend> additional_providers;
- additional_providers.push_back(new TestFileSystemBackend(
- base::MessageLoopProxy::current().get(), base_path));
- return CreateFileSystemContextWithAdditionalProvidersForTesting(
- quota_manager_proxy, additional_providers.Pass(), base_path);
-}
-
-FileSystemContext* CreateFileSystemContextWithAdditionalProvidersForTesting(
- quota::QuotaManagerProxy* quota_manager_proxy,
- ScopedVector<FileSystemBackend> additional_providers,
- const base::FilePath& base_path) {
- return new FileSystemContext(
- base::MessageLoopProxy::current().get(),
- base::MessageLoopProxy::current().get(),
- ExternalMountPoints::CreateRefCounted().get(),
- make_scoped_refptr(new quota::MockSpecialStoragePolicy()).get(),
- quota_manager_proxy,
- additional_providers.Pass(),
- base_path,
- CreateAllowFileAccessOptions());
-}
-
-FileSystemContext* CreateIncognitoFileSystemContextForTesting(
- quota::QuotaManagerProxy* quota_manager_proxy,
- const base::FilePath& base_path) {
- ScopedVector<FileSystemBackend> additional_providers;
- return new FileSystemContext(
- base::MessageLoopProxy::current().get(),
- base::MessageLoopProxy::current().get(),
- ExternalMountPoints::CreateRefCounted().get(),
- make_scoped_refptr(new quota::MockSpecialStoragePolicy()).get(),
- quota_manager_proxy,
- additional_providers.Pass(),
- base_path,
- CreateIncognitoFileSystemOptions());
-}
-
-} // namespace fileapi
diff --git a/chromium/webkit/browser/fileapi/mock_file_system_context.h b/chromium/webkit/browser/fileapi/mock_file_system_context.h
deleted file mode 100644
index 83b904d6fde..00000000000
--- a/chromium/webkit/browser/fileapi/mock_file_system_context.h
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef WEBKIT_BROWSER_FILEAPI_MOCK_FILE_SYSTEM_CONTEXT_H_
-#define WEBKIT_BROWSER_FILEAPI_MOCK_FILE_SYSTEM_CONTEXT_H_
-
-#include "base/files/file_path.h"
-#include "base/memory/scoped_vector.h"
-
-namespace quota {
-class QuotaManagerProxy;
-class SpecialStoragePolicy;
-}
-
-namespace fileapi {
-
-class FileSystemContext;
-class FileSystemBackend;
-
-FileSystemContext* CreateFileSystemContextForTesting(
- quota::QuotaManagerProxy* quota_manager_proxy,
- const base::FilePath& base_path);
-
-// The caller is responsible for including TestFileSystemBackend in
-// |additional_providers| if needed.
-FileSystemContext* CreateFileSystemContextWithAdditionalProvidersForTesting(
- quota::QuotaManagerProxy* quota_manager_proxy,
- ScopedVector<FileSystemBackend> additional_providers,
- const base::FilePath& base_path);
-
-FileSystemContext* CreateIncognitoFileSystemContextForTesting(
- quota::QuotaManagerProxy* quota_manager_proxy,
- const base::FilePath& base_path);
-
-} // namespace fileapi
-
-#endif // WEBKIT_BROWSER_FILEAPI_MOCK_FILE_SYSTEM_CONTEXT_H_
diff --git a/chromium/webkit/browser/fileapi/mock_file_system_options.cc b/chromium/webkit/browser/fileapi/mock_file_system_options.cc
deleted file mode 100644
index 06fbc27c20d..00000000000
--- a/chromium/webkit/browser/fileapi/mock_file_system_options.cc
+++ /dev/null
@@ -1,40 +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/browser/fileapi/mock_file_system_options.h"
-
-#include <string>
-#include <vector>
-
-namespace fileapi {
-
-FileSystemOptions CreateIncognitoFileSystemOptions() {
- std::vector<std::string> additional_allowed_schemes;
-#if defined(OS_CHROMEOS)
- additional_allowed_schemes.push_back("chrome-extension");
-#endif
- return FileSystemOptions(FileSystemOptions::PROFILE_MODE_INCOGNITO,
- additional_allowed_schemes);
-};
-
-FileSystemOptions CreateAllowFileAccessOptions() {
- std::vector<std::string> additional_allowed_schemes;
- additional_allowed_schemes.push_back("file");
-#if defined(OS_CHROMEOS)
- additional_allowed_schemes.push_back("chrome-extension");
-#endif
- return FileSystemOptions(FileSystemOptions::PROFILE_MODE_NORMAL,
- additional_allowed_schemes);
-};
-
-FileSystemOptions CreateDisallowFileAccessOptions() {
- std::vector<std::string> additional_allowed_schemes;
-#if defined(OS_CHROMEOS)
- additional_allowed_schemes.push_back("chrome-extension");
-#endif
- return FileSystemOptions(FileSystemOptions::PROFILE_MODE_NORMAL,
- additional_allowed_schemes);
-};
-
-} // namespace fileapi
diff --git a/chromium/webkit/browser/fileapi/mock_file_system_options.h b/chromium/webkit/browser/fileapi/mock_file_system_options.h
deleted file mode 100644
index f46f6354611..00000000000
--- a/chromium/webkit/browser/fileapi/mock_file_system_options.h
+++ /dev/null
@@ -1,23 +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_BROWSER_FILEAPI_MOCK_FILE_SYSTEM_OPTIONS_H_
-#define WEBKIT_BROWSER_FILEAPI_MOCK_FILE_SYSTEM_OPTIONS_H_
-
-#include "webkit/browser/fileapi/file_system_options.h"
-
-namespace fileapi {
-
-// Returns Filesystem options for incognito mode.
-FileSystemOptions CreateIncognitoFileSystemOptions();
-
-// Returns Filesystem options that allow file access.
-FileSystemOptions CreateAllowFileAccessOptions();
-
-// Returns Filesystem options that disallow file access.
-FileSystemOptions CreateDisallowFileAccessOptions();
-
-} // namespace fileapi
-
-#endif // WEBKIT_BROWSER_FILEAPI_MOCK_FILE_SYSTEM_OPTIONS_H_
diff --git a/chromium/webkit/browser/fileapi/mount_points.h b/chromium/webkit/browser/fileapi/mount_points.h
index 5ec67b95a9c..4ebf6e7ec3b 100644
--- a/chromium/webkit/browser/fileapi/mount_points.h
+++ b/chromium/webkit/browser/fileapi/mount_points.h
@@ -16,6 +16,7 @@
class GURL;
namespace fileapi {
+class FileSystemMountOption;
class FileSystemURL;
}
@@ -86,7 +87,8 @@ class WEBKIT_STORAGE_BROWSER_EXPORT MountPoints {
virtual bool CrackVirtualPath(const base::FilePath& virtual_path,
std::string* mount_name,
FileSystemType* type,
- base::FilePath* path) const = 0;
+ base::FilePath* path,
+ FileSystemMountOption* mount_option) const = 0;
protected:
friend class FileSystemContext;
diff --git a/chromium/webkit/browser/fileapi/native_file_util.cc b/chromium/webkit/browser/fileapi/native_file_util.cc
index 32e9467091c..9754d6c64a8 100644
--- a/chromium/webkit/browser/fileapi/native_file_util.cc
+++ b/chromium/webkit/browser/fileapi/native_file_util.cc
@@ -7,7 +7,9 @@
#include "base/file_util.h"
#include "base/files/file_enumerator.h"
#include "base/memory/scoped_ptr.h"
+#include "net/base/file_stream.h"
#include "webkit/browser/fileapi/file_system_operation_context.h"
+#include "webkit/browser/fileapi/file_system_url.h"
namespace fileapi {
@@ -32,6 +34,42 @@ bool SetPlatformSpecificDirectoryPermissions(const base::FilePath& dir_path) {
return true;
}
+// Copies a file |from| to |to|, and ensure the written content is synced to
+// the disk. This is essentially base::CopyFile followed by fsync().
+bool CopyFileAndSync(const base::FilePath& from, const base::FilePath& to) {
+ net::FileStream infile(NULL);
+ if (infile.OpenSync(from,
+ base::PLATFORM_FILE_OPEN | base:: PLATFORM_FILE_READ) < 0) {
+ return false;
+ }
+
+ net::FileStream outfile(NULL);
+ if (outfile.OpenSync(to,
+ base::PLATFORM_FILE_CREATE_ALWAYS | base:: PLATFORM_FILE_WRITE) < 0) {
+ return false;
+ }
+
+ const int kBufferSize = 32768;
+ std::vector<char> buffer(kBufferSize);
+
+ for (;;) {
+ int bytes_read = infile.ReadSync(&buffer[0], kBufferSize);
+ if (bytes_read < 0)
+ return false;
+ if (bytes_read == 0)
+ break;
+ for (int bytes_written = 0; bytes_written < bytes_read; ) {
+ int bytes_written_partial = outfile.WriteSync(&buffer[bytes_written],
+ bytes_read - bytes_written);
+ if (bytes_written_partial < 0)
+ return false;
+ bytes_written += bytes_written_partial;
+ }
+ }
+
+ return outfile.FlushSync() >= 0;
+}
+
} // namespace
using base::PlatformFile;
@@ -76,6 +114,15 @@ bool NativeFileEnumerator::IsDirectory() {
return file_util_info_.IsDirectory();
}
+NativeFileUtil::CopyOrMoveMode NativeFileUtil::CopyOrMoveModeForDestination(
+ const FileSystemURL& dest_url, bool copy) {
+ if (copy) {
+ return dest_url.mount_option().copy_sync_option() == COPY_SYNC_OPTION_SYNC ?
+ COPY_SYNC : COPY_NOSYNC;
+ }
+ return MOVE;
+}
+
PlatformFileError NativeFileUtil::CreateOrOpen(
const base::FilePath& path, int file_flags,
PlatformFile* file_handle, bool* created) {
@@ -137,11 +184,15 @@ PlatformFileError NativeFileUtil::CreateDirectory(
if (path_exists && !base::DirectoryExists(path))
return base::PLATFORM_FILE_ERROR_EXISTS;
- if (!file_util::CreateDirectory(path))
+ if (!base::CreateDirectory(path))
return base::PLATFORM_FILE_ERROR_FAILED;
- if (!SetPlatformSpecificDirectoryPermissions(path))
- return base::PLATFORM_FILE_ERROR_FAILED;
+ if (!SetPlatformSpecificDirectoryPermissions(path)) {
+ // Since some file systems don't support permission setting, we do not treat
+ // an error from the function as the failure of copying. Just log it.
+ LOG(WARNING) << "Setting directory permission failed: "
+ << path.AsUTF8Unsafe();
+ }
return base::PLATFORM_FILE_OK;
}
@@ -151,7 +202,7 @@ PlatformFileError NativeFileUtil::GetFileInfo(
base::PlatformFileInfo* file_info) {
if (!base::PathExists(path))
return base::PLATFORM_FILE_ERROR_NOT_FOUND;
- if (!file_util::GetFileInfo(path, file_info))
+ if (!base::GetFileInfo(path, file_info))
return base::PLATFORM_FILE_ERROR_FAILED;
return base::PLATFORM_FILE_OK;
}
@@ -169,8 +220,7 @@ PlatformFileError NativeFileUtil::Touch(
const base::FilePath& path,
const base::Time& last_access_time,
const base::Time& last_modified_time) {
- if (!file_util::TouchFile(
- path, last_access_time, last_modified_time))
+ if (!base::TouchFile(path, last_access_time, last_modified_time))
return base::PLATFORM_FILE_ERROR_FAILED;
return base::PLATFORM_FILE_OK;
}
@@ -205,13 +255,15 @@ bool NativeFileUtil::DirectoryExists(const base::FilePath& path) {
PlatformFileError NativeFileUtil::CopyOrMoveFile(
const base::FilePath& src_path,
const base::FilePath& dest_path,
- bool copy) {
+ FileSystemOperation::CopyOrMoveOption option,
+ CopyOrMoveMode mode) {
base::PlatformFileInfo info;
base::PlatformFileError error = NativeFileUtil::GetFileInfo(src_path, &info);
if (error != base::PLATFORM_FILE_OK)
return error;
if (info.is_directory)
return base::PLATFORM_FILE_ERROR_NOT_A_FILE;
+ base::Time last_modified = info.last_modified;
error = NativeFileUtil::GetFileInfo(dest_path, &info);
if (error != base::PLATFORM_FILE_OK &&
@@ -227,14 +279,27 @@ PlatformFileError NativeFileUtil::CopyOrMoveFile(
return base::PLATFORM_FILE_ERROR_NOT_FOUND;
}
- if (copy) {
- if (base::CopyFile(src_path, dest_path))
- return base::PLATFORM_FILE_OK;
- } else {
- if (base::Move(src_path, dest_path))
- return base::PLATFORM_FILE_OK;
+ switch (mode) {
+ case COPY_NOSYNC:
+ if (!base::CopyFile(src_path, dest_path))
+ return base::PLATFORM_FILE_ERROR_FAILED;
+ break;
+ case COPY_SYNC:
+ if (!CopyFileAndSync(src_path, dest_path))
+ return base::PLATFORM_FILE_ERROR_FAILED;
+ break;
+ case MOVE:
+ if (!base::Move(src_path, dest_path))
+ return base::PLATFORM_FILE_ERROR_FAILED;
+ break;
}
- return base::PLATFORM_FILE_ERROR_FAILED;
+
+ // Preserve the last modified time. Do not return error here even if
+ // the setting is failed, because the copy itself is successfully done.
+ if (option == FileSystemOperation::OPTION_PRESERVE_LAST_MODIFIED)
+ base::TouchFile(dest_path, last_modified, last_modified);
+
+ return base::PLATFORM_FILE_OK;
}
PlatformFileError NativeFileUtil::DeleteFile(const base::FilePath& path) {
@@ -252,7 +317,7 @@ PlatformFileError NativeFileUtil::DeleteDirectory(const base::FilePath& path) {
return base::PLATFORM_FILE_ERROR_NOT_FOUND;
if (!base::DirectoryExists(path))
return base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY;
- if (!file_util::IsDirectoryEmpty(path))
+ if (!base::IsDirectoryEmpty(path))
return base::PLATFORM_FILE_ERROR_NOT_EMPTY;
if (!base::DeleteFile(path, false))
return base::PLATFORM_FILE_ERROR_FAILED;
diff --git a/chromium/webkit/browser/fileapi/native_file_util.h b/chromium/webkit/browser/fileapi/native_file_util.h
index 425e7421597..4c36e5ff951 100644
--- a/chromium/webkit/browser/fileapi/native_file_util.h
+++ b/chromium/webkit/browser/fileapi/native_file_util.h
@@ -30,6 +30,14 @@ namespace fileapi {
// inherit from FileSystemFileUtil.
class WEBKIT_STORAGE_BROWSER_EXPORT_PRIVATE NativeFileUtil {
public:
+ enum CopyOrMoveMode {
+ COPY_NOSYNC,
+ COPY_SYNC,
+ MOVE
+ };
+ static CopyOrMoveMode CopyOrMoveModeForDestination(
+ const FileSystemURL& dest_url, bool copy);
+
static base::PlatformFileError CreateOrOpen(
const base::FilePath& path,
int file_flags,
@@ -53,9 +61,11 @@ class WEBKIT_STORAGE_BROWSER_EXPORT_PRIVATE NativeFileUtil {
int64 length);
static bool PathExists(const base::FilePath& path);
static bool DirectoryExists(const base::FilePath& path);
- static base::PlatformFileError CopyOrMoveFile(const base::FilePath& src_path,
- const base::FilePath& dest_path,
- bool copy);
+ static base::PlatformFileError CopyOrMoveFile(
+ const base::FilePath& src_path,
+ const base::FilePath& dest_path,
+ FileSystemOperation::CopyOrMoveOption option,
+ CopyOrMoveMode mode);
static base::PlatformFileError DeleteFile(const base::FilePath& path);
static base::PlatformFileError DeleteDirectory(const base::FilePath& path);
diff --git a/chromium/webkit/browser/fileapi/native_file_util_unittest.cc b/chromium/webkit/browser/fileapi/native_file_util_unittest.cc
index 1ed699e2e44..73b3e257025 100644
--- a/chromium/webkit/browser/fileapi/native_file_util_unittest.cc
+++ b/chromium/webkit/browser/fileapi/native_file_util_unittest.cc
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <set>
+
#include "base/file_util.h"
#include "base/files/file_path.h"
#include "base/files/scoped_temp_dir.h"
@@ -35,7 +37,7 @@ class NativeFileUtilTest : public testing::Test {
int64 GetSize(const base::FilePath& path) {
base::PlatformFileInfo info;
- file_util::GetFileInfo(path, &info);
+ base::GetFileInfo(path, &info);
return info.size;
}
@@ -124,7 +126,7 @@ TEST_F(NativeFileUtilTest, TouchFileAndGetFileInfo) {
ASSERT_TRUE(created);
base::PlatformFileInfo info;
- ASSERT_TRUE(file_util::GetFileInfo(file_name, &info));
+ ASSERT_TRUE(base::GetFileInfo(file_name, &info));
ASSERT_EQ(base::PLATFORM_FILE_OK,
NativeFileUtil::GetFileInfo(file_name, &native_info));
ASSERT_EQ(info.size, native_info.size);
@@ -143,7 +145,7 @@ TEST_F(NativeFileUtilTest, TouchFileAndGetFileInfo) {
NativeFileUtil::Touch(file_name,
new_accessed, new_modified));
- ASSERT_TRUE(file_util::GetFileInfo(file_name, &info));
+ ASSERT_TRUE(base::GetFileInfo(file_name, &info));
EXPECT_EQ(new_accessed, info.last_accessed);
EXPECT_EQ(new_modified, info.last_modified);
}
@@ -213,6 +215,8 @@ TEST_F(NativeFileUtilTest, CopyFile) {
base::FilePath from_file = Path("fromfile");
base::FilePath to_file1 = Path("tofile1");
base::FilePath to_file2 = Path("tofile2");
+ const NativeFileUtil::CopyOrMoveMode nosync = NativeFileUtil::COPY_NOSYNC;
+ const NativeFileUtil::CopyOrMoveMode sync = NativeFileUtil::COPY_SYNC;
bool created = false;
ASSERT_EQ(base::PLATFORM_FILE_OK,
NativeFileUtil::EnsureFileExists(from_file, &created));
@@ -225,10 +229,12 @@ TEST_F(NativeFileUtilTest, CopyFile) {
EXPECT_EQ(1020, GetSize(from_file));
ASSERT_EQ(base::PLATFORM_FILE_OK,
- NativeFileUtil::CopyOrMoveFile(from_file, to_file1, true));
+ NativeFileUtil::CopyOrMoveFile(
+ from_file, to_file1, FileSystemOperation::OPTION_NONE, nosync));
ASSERT_EQ(base::PLATFORM_FILE_OK,
- NativeFileUtil::CopyOrMoveFile(from_file, to_file2, true));
+ NativeFileUtil::CopyOrMoveFile(
+ from_file, to_file2, FileSystemOperation::OPTION_NONE, sync));
EXPECT_TRUE(FileExists(from_file));
EXPECT_EQ(1020, GetSize(from_file));
@@ -243,37 +249,43 @@ TEST_F(NativeFileUtilTest, CopyFile) {
ASSERT_TRUE(base::DirectoryExists(dir));
base::FilePath to_dir_file = dir.AppendASCII("file");
ASSERT_EQ(base::PLATFORM_FILE_OK,
- NativeFileUtil::CopyOrMoveFile(from_file, to_dir_file, true));
+ NativeFileUtil::CopyOrMoveFile(
+ from_file, to_dir_file,
+ FileSystemOperation::OPTION_NONE, nosync));
EXPECT_TRUE(FileExists(to_dir_file));
EXPECT_EQ(1020, GetSize(to_dir_file));
// Following tests are error checking.
// Source doesn't exist.
EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND,
- NativeFileUtil::CopyOrMoveFile(Path("nonexists"), Path("file"),
- true));
+ NativeFileUtil::CopyOrMoveFile(
+ Path("nonexists"), Path("file"),
+ FileSystemOperation::OPTION_NONE, nosync));
// Source is not a file.
EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_A_FILE,
- NativeFileUtil::CopyOrMoveFile(dir, Path("file"), true));
+ NativeFileUtil::CopyOrMoveFile(
+ dir, Path("file"), FileSystemOperation::OPTION_NONE, nosync));
// Destination is not a file.
EXPECT_EQ(base::PLATFORM_FILE_ERROR_INVALID_OPERATION,
- NativeFileUtil::CopyOrMoveFile(from_file, dir, true));
+ NativeFileUtil::CopyOrMoveFile(
+ from_file, dir, FileSystemOperation::OPTION_NONE, nosync));
// Destination's parent doesn't exist.
EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND,
- NativeFileUtil::CopyOrMoveFile(from_file,
- Path("nodir").AppendASCII("file"),
- true));
+ NativeFileUtil::CopyOrMoveFile(
+ from_file, Path("nodir").AppendASCII("file"),
+ FileSystemOperation::OPTION_NONE, nosync));
// Destination's parent is a file.
EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND,
- NativeFileUtil::CopyOrMoveFile(from_file,
- Path("tofile1").AppendASCII("file"),
- true));
+ NativeFileUtil::CopyOrMoveFile(
+ from_file, Path("tofile1").AppendASCII("file"),
+ FileSystemOperation::OPTION_NONE, nosync));
}
TEST_F(NativeFileUtilTest, MoveFile) {
base::FilePath from_file = Path("fromfile");
base::FilePath to_file = Path("tofile");
+ const NativeFileUtil::CopyOrMoveMode move = NativeFileUtil::MOVE;
bool created = false;
ASSERT_EQ(base::PLATFORM_FILE_OK,
NativeFileUtil::EnsureFileExists(from_file, &created));
@@ -285,7 +297,8 @@ TEST_F(NativeFileUtilTest, MoveFile) {
EXPECT_EQ(1020, GetSize(from_file));
ASSERT_EQ(base::PLATFORM_FILE_OK,
- NativeFileUtil::CopyOrMoveFile(from_file, to_file, false));
+ NativeFileUtil::CopyOrMoveFile(
+ from_file, to_file, FileSystemOperation::OPTION_NONE, move));
EXPECT_FALSE(FileExists(from_file));
EXPECT_TRUE(FileExists(to_file));
@@ -302,7 +315,9 @@ TEST_F(NativeFileUtilTest, MoveFile) {
ASSERT_TRUE(base::DirectoryExists(dir));
base::FilePath to_dir_file = dir.AppendASCII("file");
ASSERT_EQ(base::PLATFORM_FILE_OK,
- NativeFileUtil::CopyOrMoveFile(from_file, to_dir_file, false));
+ NativeFileUtil::CopyOrMoveFile(
+ from_file, to_dir_file,
+ FileSystemOperation::OPTION_NONE, move));
EXPECT_FALSE(FileExists(from_file));
EXPECT_TRUE(FileExists(to_dir_file));
EXPECT_EQ(1020, GetSize(to_dir_file));
@@ -310,32 +325,88 @@ TEST_F(NativeFileUtilTest, MoveFile) {
// Following is error checking.
// Source doesn't exist.
EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND,
- NativeFileUtil::CopyOrMoveFile(Path("nonexists"), Path("file"),
- false));
+ NativeFileUtil::CopyOrMoveFile(
+ Path("nonexists"), Path("file"),
+ FileSystemOperation::OPTION_NONE, move));
// Source is not a file.
EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_A_FILE,
- NativeFileUtil::CopyOrMoveFile(dir, Path("file"), false));
+ NativeFileUtil::CopyOrMoveFile(
+ dir, Path("file"), FileSystemOperation::OPTION_NONE, move));
ASSERT_EQ(base::PLATFORM_FILE_OK,
NativeFileUtil::EnsureFileExists(from_file, &created));
ASSERT_TRUE(FileExists(from_file));
// Destination is not a file.
EXPECT_EQ(base::PLATFORM_FILE_ERROR_INVALID_OPERATION,
- NativeFileUtil::CopyOrMoveFile(from_file, dir, false));
+ NativeFileUtil::CopyOrMoveFile(
+ from_file, dir, FileSystemOperation::OPTION_NONE, move));
ASSERT_EQ(base::PLATFORM_FILE_OK,
NativeFileUtil::EnsureFileExists(from_file, &created));
ASSERT_TRUE(FileExists(from_file));
// Destination's parent doesn't exist.
EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND,
- NativeFileUtil::CopyOrMoveFile(from_file,
- Path("nodir").AppendASCII("file"),
- false));
+ NativeFileUtil::CopyOrMoveFile(
+ from_file, Path("nodir").AppendASCII("file"),
+ FileSystemOperation::OPTION_NONE, move));
// Destination's parent is a file.
EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND,
- NativeFileUtil::CopyOrMoveFile(from_file,
- Path("tofile1").AppendASCII("file"),
- false));
+ NativeFileUtil::CopyOrMoveFile(
+ from_file, Path("tofile1").AppendASCII("file"),
+ FileSystemOperation::OPTION_NONE, move));
+}
+
+TEST_F(NativeFileUtilTest, PreserveLastModified) {
+ base::FilePath from_file = Path("fromfile");
+ base::FilePath to_file1 = Path("tofile1");
+ base::FilePath to_file2 = Path("tofile2");
+ base::FilePath to_file3 = Path("tofile3");
+ bool created = false;
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ NativeFileUtil::EnsureFileExists(from_file, &created));
+ ASSERT_TRUE(created);
+ EXPECT_TRUE(FileExists(from_file));
+
+ base::PlatformFileInfo file_info1;
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ NativeFileUtil::GetFileInfo(from_file, &file_info1));
+
+ // Test for copy (nosync).
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ NativeFileUtil::CopyOrMoveFile(
+ from_file, to_file1,
+ FileSystemOperation::OPTION_PRESERVE_LAST_MODIFIED,
+ NativeFileUtil::COPY_NOSYNC));
+
+ base::PlatformFileInfo file_info2;
+ ASSERT_TRUE(FileExists(to_file1));
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ NativeFileUtil::GetFileInfo(to_file1, &file_info2));
+ EXPECT_EQ(file_info1.last_modified, file_info2.last_modified);
+
+ // Test for copy (sync).
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ NativeFileUtil::CopyOrMoveFile(
+ from_file, to_file2,
+ FileSystemOperation::OPTION_PRESERVE_LAST_MODIFIED,
+ NativeFileUtil::COPY_SYNC));
+
+ ASSERT_TRUE(FileExists(to_file2));
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ NativeFileUtil::GetFileInfo(to_file1, &file_info2));
+ EXPECT_EQ(file_info1.last_modified, file_info2.last_modified);
+
+ // Test for move.
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ NativeFileUtil::CopyOrMoveFile(
+ from_file, to_file3,
+ FileSystemOperation::OPTION_PRESERVE_LAST_MODIFIED,
+ NativeFileUtil::MOVE));
+
+ ASSERT_TRUE(FileExists(to_file3));
+ ASSERT_EQ(base::PLATFORM_FILE_OK,
+ NativeFileUtil::GetFileInfo(to_file2, &file_info2));
+ EXPECT_EQ(file_info1.last_modified, file_info2.last_modified);
}
} // namespace fileapi
diff --git a/chromium/webkit/browser/fileapi/obfuscated_file_util.cc b/chromium/webkit/browser/fileapi/obfuscated_file_util.cc
index 341f7d0a8bb..c324f10800a 100644
--- a/chromium/webkit/browser/fileapi/obfuscated_file_util.cc
+++ b/chromium/webkit/browser/fileapi/obfuscated_file_util.cc
@@ -28,6 +28,7 @@
#include "webkit/browser/fileapi/sandbox_file_system_backend.h"
#include "webkit/browser/fileapi/sandbox_isolated_origin_database.h"
#include "webkit/browser/fileapi/sandbox_origin_database.h"
+#include "webkit/browser/fileapi/sandbox_prioritized_origin_database.h"
#include "webkit/browser/fileapi/timed_task_helper.h"
#include "webkit/browser/quota/quota_manager.h"
#include "webkit/common/database/database_identifier.h"
@@ -60,9 +61,9 @@ void InitFileInfo(
// Costs computed as per crbug.com/86114, based on the LevelDB implementation of
// path storage under Linux. It's not clear if that will differ on Windows, on
-// which base::FilePath uses wide chars [since they're converted to UTF-8 for storage
-// anyway], but as long as the cost is high enough that one can't cheat on quota
-// by storing data in paths, it doesn't need to be all that accurate.
+// which base::FilePath uses wide chars [since they're converted to UTF-8 for
+// storage anyway], but as long as the cost is high enough that one can't cheat
+// on quota by storing data in paths, it doesn't need to be all that accurate.
const int64 kPathCreationQuotaCost = 146; // Bytes per inode, basically.
const int64 kPathByteQuotaCost = 2; // Bytes per byte of path length in UTF-8.
@@ -96,10 +97,6 @@ void TouchDirectory(SandboxDirectoryDatabase* db, FileId dir_id) {
NOTREACHED();
}
-const base::FilePath::CharType kTemporaryDirectoryName[] = FILE_PATH_LITERAL("t");
-const base::FilePath::CharType kPersistentDirectoryName[] = FILE_PATH_LITERAL("p");
-const base::FilePath::CharType kSyncableDirectoryName[] = FILE_PATH_LITERAL("s");
-
enum IsolatedOriginStatus {
kIsolatedOriginMatch,
kIsolatedOriginDontMatch,
@@ -123,8 +120,7 @@ class ObfuscatedFileEnumerator
: db_(db),
context_(context),
obfuscated_file_util_(obfuscated_file_util),
- origin_(root_url.origin()),
- type_(root_url.type()),
+ root_url_(root_url),
recursive_(recursive),
current_file_id_(0) {
base::FilePath root_virtual_path = root_url.path();
@@ -151,7 +147,7 @@ class ObfuscatedFileEnumerator
base::FilePath platform_file_path;
base::PlatformFileError error =
obfuscated_file_util_->GetFileInfoInternal(
- db_, context_, origin_, type_, current_file_id_,
+ db_, context_, root_url_, current_file_id_,
&file_info, &current_platform_file_info_, &platform_file_path);
if (error != base::PLATFORM_FILE_OK)
return Next();
@@ -201,8 +197,7 @@ class ObfuscatedFileEnumerator
SandboxDirectoryDatabase* db_;
FileSystemOperationContext* context_;
ObfuscatedFileUtil* obfuscated_file_util_;
- GURL origin_;
- FileSystemType type_;
+ FileSystemURL root_url_;
bool recursive_;
std::queue<FileRecord> recurse_queue_;
@@ -239,17 +234,15 @@ class ObfuscatedOriginEnumerator
}
// Returns the current origin's information.
- virtual bool HasFileSystemType(FileSystemType type) const OVERRIDE {
+ virtual bool HasTypeDirectory(const std::string& type_string) const OVERRIDE {
if (current_.path.empty())
return false;
- base::FilePath::StringType type_string =
- ObfuscatedFileUtil::GetDirectoryNameForType(type);
if (type_string.empty()) {
NOTREACHED();
return false;
}
base::FilePath path =
- base_file_path_.Append(current_.path).Append(type_string);
+ base_file_path_.Append(current_.path).AppendASCII(type_string);
return base::DirectoryExists(path);
}
@@ -262,11 +255,17 @@ class ObfuscatedOriginEnumerator
ObfuscatedFileUtil::ObfuscatedFileUtil(
quota::SpecialStoragePolicy* special_storage_policy,
const base::FilePath& file_system_directory,
- base::SequencedTaskRunner* file_task_runner)
+ base::SequencedTaskRunner* file_task_runner,
+ const GetTypeStringForURLCallback& get_type_string_for_url,
+ const std::set<std::string>& known_type_strings,
+ SandboxFileSystemBackendDelegate* sandbox_delegate)
: special_storage_policy_(special_storage_policy),
file_system_directory_(file_system_directory),
- db_flush_delay_seconds_(10 * 60), // 10 mins.
- file_task_runner_(file_task_runner) {
+ db_flush_delay_seconds_(10 * 60), // 10 mins.
+ file_task_runner_(file_task_runner),
+ get_type_string_for_url_(get_type_string_for_url),
+ known_type_strings_(known_type_strings),
+ sandbox_delegate_(sandbox_delegate) {
}
ObfuscatedFileUtil::~ObfuscatedFileUtil() {
@@ -281,10 +280,10 @@ PlatformFileError ObfuscatedFileUtil::CreateOrOpen(
file_handle, created);
if (*file_handle != base::kInvalidPlatformFileValue &&
file_flags & base::PLATFORM_FILE_WRITE &&
- context->quota_limit_type() == quota::kQuotaLimitTypeUnlimited) {
+ context->quota_limit_type() == quota::kQuotaLimitTypeUnlimited &&
+ sandbox_delegate_) {
DCHECK_EQ(base::PLATFORM_FILE_OK, error);
- context->file_system_context()->sandbox_delegate()->
- StickyInvalidateUsageCache(url.origin(), url.type());
+ sandbox_delegate_->StickyInvalidateUsageCache(url.origin(), url.type());
}
return error;
}
@@ -299,8 +298,7 @@ PlatformFileError ObfuscatedFileUtil::EnsureFileExists(
FileSystemOperationContext* context,
const FileSystemURL& url,
bool* created) {
- SandboxDirectoryDatabase* db = GetDirectoryDatabase(
- url.origin(), url.type(), true);
+ SandboxDirectoryDatabase* db = GetDirectoryDatabase(url, true);
if (!db)
return base::PLATFORM_FILE_ERROR_FAILED;
@@ -329,7 +327,7 @@ PlatformFileError ObfuscatedFileUtil::EnsureFileExists(
if (!AllocateQuota(context, growth))
return base::PLATFORM_FILE_ERROR_NO_SPACE;
PlatformFileError error = CreateFile(
- context, base::FilePath(), url.origin(), url.type(), &file_info, 0, NULL);
+ context, base::FilePath(), url, &file_info, 0, NULL);
if (created && base::PLATFORM_FILE_OK == error) {
*created = true;
UpdateUsage(context, url, growth);
@@ -344,8 +342,7 @@ PlatformFileError ObfuscatedFileUtil::CreateDirectory(
const FileSystemURL& url,
bool exclusive,
bool recursive) {
- SandboxDirectoryDatabase* db = GetDirectoryDatabase(
- url.origin(), url.type(), true);
+ SandboxDirectoryDatabase* db = GetDirectoryDatabase(url, true);
if (!db)
return base::PLATFORM_FILE_ERROR_FAILED;
@@ -374,6 +371,8 @@ PlatformFileError ObfuscatedFileUtil::CreateDirectory(
if (!db->GetChildWithName(parent_id, name, &parent_id))
break;
}
+ if (!db->IsDirectory(parent_id))
+ return base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY;
if (!recursive && components.size() - index > 1)
return base::PLATFORM_FILE_ERROR_NOT_FOUND;
bool first = true;
@@ -406,16 +405,14 @@ PlatformFileError ObfuscatedFileUtil::GetFileInfo(
const FileSystemURL& url,
base::PlatformFileInfo* file_info,
base::FilePath* platform_file_path) {
- SandboxDirectoryDatabase* db = GetDirectoryDatabase(
- url.origin(), url.type(), false);
+ SandboxDirectoryDatabase* db = GetDirectoryDatabase(url, false);
if (!db)
return base::PLATFORM_FILE_ERROR_NOT_FOUND;
FileId file_id;
if (!db->GetFileWithPath(url.path(), &file_id))
return base::PLATFORM_FILE_ERROR_NOT_FOUND;
FileInfo local_info;
- return GetFileInfoInternal(db, context,
- url.origin(), url.type(),
+ return GetFileInfoInternal(db, context, url,
file_id, &local_info,
file_info, platform_file_path);
}
@@ -431,8 +428,7 @@ PlatformFileError ObfuscatedFileUtil::GetLocalFilePath(
FileSystemOperationContext* context,
const FileSystemURL& url,
base::FilePath* local_path) {
- SandboxDirectoryDatabase* db = GetDirectoryDatabase(
- url.origin(), url.type(), false);
+ SandboxDirectoryDatabase* db = GetDirectoryDatabase(url, false);
if (!db)
return base::PLATFORM_FILE_ERROR_NOT_FOUND;
FileId file_id;
@@ -444,8 +440,7 @@ PlatformFileError ObfuscatedFileUtil::GetLocalFilePath(
// Directories have no local file path.
return base::PLATFORM_FILE_ERROR_NOT_FOUND;
}
- *local_path = DataPathToLocalPath(
- url.origin(), url.type(), file_info.data_path);
+ *local_path = DataPathToLocalPath(url, file_info.data_path);
if (local_path->empty())
return base::PLATFORM_FILE_ERROR_NOT_FOUND;
@@ -457,8 +452,7 @@ PlatformFileError ObfuscatedFileUtil::Touch(
const FileSystemURL& url,
const base::Time& last_access_time,
const base::Time& last_modified_time) {
- SandboxDirectoryDatabase* db = GetDirectoryDatabase(
- url.origin(), url.type(), false);
+ SandboxDirectoryDatabase* db = GetDirectoryDatabase(url, false);
if (!db)
return base::PLATFORM_FILE_ERROR_NOT_FOUND;
FileId file_id;
@@ -475,10 +469,9 @@ PlatformFileError ObfuscatedFileUtil::Touch(
return base::PLATFORM_FILE_ERROR_FAILED;
return base::PLATFORM_FILE_OK;
}
- base::FilePath local_path = DataPathToLocalPath(
- url.origin(), url.type(), file_info.data_path);
return NativeFileUtil::Touch(
- local_path, last_access_time, last_modified_time);
+ DataPathToLocalPath(url, file_info.data_path),
+ last_access_time, last_modified_time);
}
PlatformFileError ObfuscatedFileUtil::Truncate(
@@ -508,13 +501,13 @@ PlatformFileError ObfuscatedFileUtil::CopyOrMoveFile(
FileSystemOperationContext* context,
const FileSystemURL& src_url,
const FileSystemURL& dest_url,
+ CopyOrMoveOption option,
bool copy) {
// Cross-filesystem copies and moves should be handled via CopyInForeignFile.
DCHECK(src_url.origin() == dest_url.origin());
DCHECK(src_url.type() == dest_url.type());
- SandboxDirectoryDatabase* db = GetDirectoryDatabase(
- src_url.origin(), src_url.type(), true);
+ SandboxDirectoryDatabase* db = GetDirectoryDatabase(src_url, true);
if (!db)
return base::PLATFORM_FILE_ERROR_FAILED;
@@ -530,7 +523,7 @@ PlatformFileError ObfuscatedFileUtil::CopyOrMoveFile(
base::PlatformFileInfo src_platform_file_info;
base::FilePath src_local_path;
base::PlatformFileError error = GetFileInfoInternal(
- db, context, src_url.origin(), src_url.type(), src_file_id,
+ db, context, src_url, src_file_id,
&src_file_info, &src_platform_file_info, &src_local_path);
if (error != base::PLATFORM_FILE_OK)
return error;
@@ -542,7 +535,7 @@ PlatformFileError ObfuscatedFileUtil::CopyOrMoveFile(
base::FilePath dest_local_path; // overwrite case only
if (overwrite) {
base::PlatformFileError error = GetFileInfoInternal(
- db, context, dest_url.origin(), dest_url.type(), dest_file_id,
+ db, context, dest_url, dest_file_id,
&dest_file_info, &dest_platform_file_info, &dest_local_path);
if (error == base::PLATFORM_FILE_ERROR_NOT_FOUND)
overwrite = false; // fallback to non-overwrite case
@@ -596,11 +589,12 @@ PlatformFileError ObfuscatedFileUtil::CopyOrMoveFile(
error = NativeFileUtil::CopyOrMoveFile(
src_local_path,
dest_local_path,
- true /* copy */);
+ option,
+ fileapi::NativeFileUtil::CopyOrMoveModeForDestination(
+ dest_url, true /* copy */));
} else { // non-overwrite
error = CreateFile(context, src_local_path,
- dest_url.origin(), dest_url.type(),
- &dest_file_info, 0, NULL);
+ dest_url, &dest_file_info, 0, NULL);
}
} else {
if (overwrite) {
@@ -649,13 +643,12 @@ PlatformFileError ObfuscatedFileUtil::CopyInForeignFile(
FileSystemOperationContext* context,
const base::FilePath& src_file_path,
const FileSystemURL& dest_url) {
- SandboxDirectoryDatabase* db = GetDirectoryDatabase(
- dest_url.origin(), dest_url.type(), true);
+ SandboxDirectoryDatabase* db = GetDirectoryDatabase(dest_url, 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))
+ if (!base::GetFileInfo(src_file_path, &src_platform_file_info))
return base::PLATFORM_FILE_ERROR_NOT_FOUND;
FileId dest_file_id;
@@ -667,7 +660,7 @@ PlatformFileError ObfuscatedFileUtil::CopyInForeignFile(
if (overwrite) {
base::FilePath dest_local_path;
base::PlatformFileError error = GetFileInfoInternal(
- db, context, dest_url.origin(), dest_url.type(), dest_file_id,
+ db, context, dest_url, dest_file_id,
&dest_file_info, &dest_platform_file_info, &dest_local_path);
if (error == base::PLATFORM_FILE_ERROR_NOT_FOUND)
overwrite = false; // fallback to non-overwrite case
@@ -698,14 +691,16 @@ PlatformFileError ObfuscatedFileUtil::CopyInForeignFile(
base::PlatformFileError error;
if (overwrite) {
- base::FilePath dest_local_path = DataPathToLocalPath(
- dest_url.origin(), dest_url.type(), dest_file_info.data_path);
+ base::FilePath dest_local_path =
+ DataPathToLocalPath(dest_url, dest_file_info.data_path);
error = NativeFileUtil::CopyOrMoveFile(
- src_file_path, dest_local_path, true);
+ src_file_path, dest_local_path,
+ FileSystemOperation::OPTION_NONE,
+ fileapi::NativeFileUtil::CopyOrMoveModeForDestination(dest_url,
+ true /* copy */));
} else {
error = CreateFile(context, src_file_path,
- dest_url.origin(), dest_url.type(),
- &dest_file_info, 0, NULL);
+ dest_url, &dest_file_info, 0, NULL);
}
if (error != base::PLATFORM_FILE_OK)
@@ -727,8 +722,7 @@ PlatformFileError ObfuscatedFileUtil::CopyInForeignFile(
PlatformFileError ObfuscatedFileUtil::DeleteFile(
FileSystemOperationContext* context,
const FileSystemURL& url) {
- SandboxDirectoryDatabase* db = GetDirectoryDatabase(
- url.origin(), url.type(), true);
+ SandboxDirectoryDatabase* db = GetDirectoryDatabase(url, true);
if (!db)
return base::PLATFORM_FILE_ERROR_FAILED;
FileId file_id;
@@ -739,8 +733,7 @@ PlatformFileError ObfuscatedFileUtil::DeleteFile(
base::PlatformFileInfo platform_file_info;
base::FilePath local_path;
base::PlatformFileError error = GetFileInfoInternal(
- db, context, url.origin(), url.type(), file_id,
- &file_info, &platform_file_info, &local_path);
+ db, context, url, file_id, &file_info, &platform_file_info, &local_path);
if (error != base::PLATFORM_FILE_ERROR_NOT_FOUND &&
error != base::PLATFORM_FILE_OK)
return error;
@@ -772,8 +765,7 @@ PlatformFileError ObfuscatedFileUtil::DeleteFile(
PlatformFileError ObfuscatedFileUtil::DeleteDirectory(
FileSystemOperationContext* context,
const FileSystemURL& url) {
- SandboxDirectoryDatabase* db = GetDirectoryDatabase(
- url.origin(), url.type(), true);
+ SandboxDirectoryDatabase* db = GetDirectoryDatabase(url, true);
if (!db)
return base::PLATFORM_FILE_ERROR_FAILED;
@@ -818,8 +810,7 @@ scoped_ptr<FileSystemFileUtil::AbstractFileEnumerator>
FileSystemOperationContext* context,
const FileSystemURL& root_url,
bool recursive) {
- SandboxDirectoryDatabase* db = GetDirectoryDatabase(
- root_url.origin(), root_url.type(), false);
+ SandboxDirectoryDatabase* db = GetDirectoryDatabase(root_url, false);
if (!db) {
return scoped_ptr<AbstractFileEnumerator>(new EmptyFileEnumerator());
}
@@ -830,8 +821,7 @@ scoped_ptr<FileSystemFileUtil::AbstractFileEnumerator>
bool ObfuscatedFileUtil::IsDirectoryEmpty(
FileSystemOperationContext* context,
const FileSystemURL& url) {
- SandboxDirectoryDatabase* db = GetDirectoryDatabase(
- url.origin(), url.type(), false);
+ SandboxDirectoryDatabase* db = GetDirectoryDatabase(url, false);
if (!db)
return true; // Not a great answer, but it's what others do.
FileId file_id;
@@ -854,24 +844,18 @@ bool ObfuscatedFileUtil::IsDirectoryEmpty(
base::FilePath ObfuscatedFileUtil::GetDirectoryForOriginAndType(
const GURL& origin,
- FileSystemType type,
+ const std::string& type_string,
bool create,
base::PlatformFileError* error_code) {
base::FilePath origin_dir = GetDirectoryForOrigin(origin, create, error_code);
if (origin_dir.empty())
return base::FilePath();
- base::FilePath::StringType type_string = GetDirectoryNameForType(type);
- if (type_string.empty()) {
- LOG(WARNING) << "Unknown filesystem type requested:" << type;
-
- if (error_code)
- *error_code = base::PLATFORM_FILE_ERROR_INVALID_URL;
- return base::FilePath();
- }
- base::FilePath path = origin_dir.Append(type_string);
+ if (type_string.empty())
+ return origin_dir;
+ base::FilePath path = origin_dir.AppendASCII(type_string);
base::PlatformFileError error = base::PLATFORM_FILE_OK;
if (!base::DirectoryExists(path) &&
- (!create || !file_util::CreateDirectory(path))) {
+ (!create || !base::CreateDirectory(path))) {
error = create ?
base::PLATFORM_FILE_ERROR_FAILED :
base::PLATFORM_FILE_ERROR_NOT_FOUND;
@@ -883,20 +867,21 @@ base::FilePath ObfuscatedFileUtil::GetDirectoryForOriginAndType(
}
bool ObfuscatedFileUtil::DeleteDirectoryForOriginAndType(
- const GURL& origin, FileSystemType type) {
+ const GURL& origin,
+ const std::string& type_string) {
base::PlatformFileError error = base::PLATFORM_FILE_OK;
base::FilePath origin_type_path = GetDirectoryForOriginAndType(
- origin, type, false, &error);
+ origin, type_string, false, &error);
if (origin_type_path.empty())
return true;
-
if (error != base::PLATFORM_FILE_ERROR_NOT_FOUND) {
// TODO(dmikurube): Consider the return value of DestroyDirectoryDatabase.
// We ignore its error now since 1) it doesn't matter the final result, and
// 2) it always returns false in Windows because of LevelDB's
// implementation.
// Information about failure would be useful for debugging.
- DestroyDirectoryDatabase(origin, type);
+ if (!type_string.empty())
+ DestroyDirectoryDatabase(origin, type_string);
if (!base::DeleteFile(origin_type_path, true /* recursive */))
return false;
}
@@ -905,28 +890,24 @@ bool ObfuscatedFileUtil::DeleteDirectoryForOriginAndType(
DCHECK_EQ(origin_path.value(),
GetDirectoryForOrigin(origin, false, NULL).value());
- // At this point we are sure we had successfully deleted the origin/type
- // directory (i.e. we're ready to just return true).
- // See if we have other directories in this origin directory.
- std::vector<FileSystemType> other_types;
- if (type != kFileSystemTypeTemporary)
- other_types.push_back(kFileSystemTypeTemporary);
- if (type != kFileSystemTypePersistent)
- other_types.push_back(kFileSystemTypePersistent);
- if (type != kFileSystemTypeSyncable)
- other_types.push_back(kFileSystemTypeSyncable);
- DCHECK(type != kFileSystemTypeSyncableForInternalSync);
-
- for (size_t i = 0; i < other_types.size(); ++i) {
- if (base::DirectoryExists(
- origin_path.Append(GetDirectoryNameForType(other_types[i])))) {
- // Other type's directory exists; just return true here.
- return true;
+ if (!type_string.empty()) {
+ // At this point we are sure we had successfully deleted the origin/type
+ // directory (i.e. we're ready to just return true).
+ // See if we have other directories in this origin directory.
+ for (std::set<std::string>::iterator iter = known_type_strings_.begin();
+ iter != known_type_strings_.end();
+ ++iter) {
+ if (*iter == type_string)
+ continue;
+ if (base::DirectoryExists(origin_path.AppendASCII(*iter))) {
+ // Other type's directory exists; just return true here.
+ return true;
+ }
}
}
// No other directories seem exist. Try deleting the entire origin directory.
- InitOriginDatabase(false);
+ InitOriginDatabase(origin, false);
if (origin_database_) {
origin_database_->RemovePathForOrigin(
webkit_database::GetIdentifierFromOrigin(origin));
@@ -937,35 +918,19 @@ bool ObfuscatedFileUtil::DeleteDirectoryForOriginAndType(
return true;
}
-// static
-base::FilePath::StringType ObfuscatedFileUtil::GetDirectoryNameForType(
- FileSystemType type) {
- switch (type) {
- case kFileSystemTypeTemporary:
- return kTemporaryDirectoryName;
- case kFileSystemTypePersistent:
- return kPersistentDirectoryName;
- case kFileSystemTypeSyncable:
- case kFileSystemTypeSyncableForInternalSync:
- return kSyncableDirectoryName;
- case kFileSystemTypeUnknown:
- default:
- return base::FilePath::StringType();
- }
-}
-
ObfuscatedFileUtil::AbstractOriginEnumerator*
ObfuscatedFileUtil::CreateOriginEnumerator() {
std::vector<SandboxOriginDatabase::OriginRecord> origins;
- InitOriginDatabase(false);
+ InitOriginDatabase(GURL(), false);
return new ObfuscatedOriginEnumerator(
origin_database_.get(), file_system_directory_);
}
bool ObfuscatedFileUtil::DestroyDirectoryDatabase(
- const GURL& origin, FileSystemType type) {
- std::string key = GetDirectoryDatabaseKey(origin, type);
+ const GURL& origin,
+ const std::string& type_string) {
+ std::string key = GetDirectoryDatabaseKey(origin, type_string);
if (key.empty())
return true;
DirectoryMap::iterator iter = directories_.find(key);
@@ -977,7 +942,7 @@ bool ObfuscatedFileUtil::DestroyDirectoryDatabase(
PlatformFileError error = base::PLATFORM_FILE_OK;
base::FilePath path = GetDirectoryForOriginAndType(
- origin, type, false, &error);
+ origin, type_string, false, &error);
if (path.empty() || error == base::PLATFORM_FILE_ERROR_NOT_FOUND)
return true;
return SandboxDirectoryDatabase::DestroyDatabase(path);
@@ -988,31 +953,29 @@ int64 ObfuscatedFileUtil::ComputeFilePathCost(const base::FilePath& path) {
return UsageForPath(VirtualPath::BaseName(path).value().size());
}
-void ObfuscatedFileUtil::MaybePrepopulateDatabase() {
- // Always disable this for now. crbug.com/264429
- return;
-
- base::FilePath isolated_origin_dir = file_system_directory_.Append(
- SandboxIsolatedOriginDatabase::kOriginDirectory);
- if (!base::DirectoryExists(isolated_origin_dir))
+void ObfuscatedFileUtil::MaybePrepopulateDatabase(
+ const std::vector<std::string>& type_strings_to_prepopulate) {
+ SandboxPrioritizedOriginDatabase database(file_system_directory_);
+ std::string origin_string = database.GetPrimaryOrigin();
+ if (origin_string.empty() || !database.HasOriginPath(origin_string))
return;
-
- const FileSystemType kPrepopulateTypes[] = {
- kFileSystemTypePersistent, kFileSystemTypeTemporary
- };
-
- // Prepulate the directory database(s) if and only if this instance is
- // initialized for isolated storage dedicated for a single origin.
- for (size_t i = 0; i < arraysize(kPrepopulateTypes); ++i) {
- const FileSystemType type = kPrepopulateTypes[i];
- base::FilePath::StringType type_string = GetDirectoryNameForType(type);
- DCHECK(!type_string.empty());
- base::FilePath path = isolated_origin_dir.Append(type_string);
- if (!base::DirectoryExists(path))
+ const GURL origin = webkit_database::GetOriginFromIdentifier(origin_string);
+
+ // Prepopulate the directory database(s) if and only if this instance
+ // has primary origin and the directory database is already there.
+ for (size_t i = 0; i < type_strings_to_prepopulate.size(); ++i) {
+ const std::string type_string = type_strings_to_prepopulate[i];
+ // Only handles known types.
+ if (!ContainsKey(known_type_strings_, type_string))
+ continue;
+ PlatformFileError error = base::PLATFORM_FILE_ERROR_FAILED;
+ base::FilePath path = GetDirectoryForOriginAndType(
+ origin, type_string, false, &error);
+ if (error != base::PLATFORM_FILE_OK)
continue;
scoped_ptr<SandboxDirectoryDatabase> db(new SandboxDirectoryDatabase(path));
if (db->Init(SandboxDirectoryDatabase::FAIL_ON_CORRUPTION)) {
- directories_[GetFileSystemTypeString(type)] = db.release();
+ directories_[GetDirectoryDatabaseKey(origin, type_string)] = db.release();
MarkUsed();
// Don't populate more than one database, as it may rather hurt
// performance.
@@ -1021,11 +984,24 @@ void ObfuscatedFileUtil::MaybePrepopulateDatabase() {
}
}
+base::FilePath ObfuscatedFileUtil::GetDirectoryForURL(
+ const FileSystemURL& url,
+ bool create,
+ base::PlatformFileError* error_code) {
+ return GetDirectoryForOriginAndType(
+ url.origin(), CallGetTypeStringForURL(url), create, error_code);
+}
+
+std::string ObfuscatedFileUtil::CallGetTypeStringForURL(
+ const FileSystemURL& url) {
+ DCHECK(!get_type_string_for_url_.is_null());
+ return get_type_string_for_url_.Run(url);
+}
+
PlatformFileError ObfuscatedFileUtil::GetFileInfoInternal(
SandboxDirectoryDatabase* db,
FileSystemOperationContext* context,
- const GURL& origin,
- FileSystemType type,
+ const FileSystemURL& url,
FileId file_id,
FileInfo* local_info,
base::PlatformFileInfo* file_info,
@@ -1051,12 +1027,11 @@ PlatformFileError ObfuscatedFileUtil::GetFileInfoInternal(
}
if (local_info->data_path.empty())
return base::PLATFORM_FILE_ERROR_INVALID_OPERATION;
- base::FilePath local_path = DataPathToLocalPath(
- origin, type, local_info->data_path);
+ base::FilePath local_path = DataPathToLocalPath(url, local_info->data_path);
base::PlatformFileError error = NativeFileUtil::GetFileInfo(
local_path, file_info);
// We should not follow symbolic links in sandboxed file system.
- if (file_util::IsLink(local_path)) {
+ if (base::IsLink(local_path)) {
LOG(WARNING) << "Found a symbolic file.";
error = base::PLATFORM_FILE_ERROR_NOT_FOUND;
}
@@ -1064,7 +1039,7 @@ PlatformFileError ObfuscatedFileUtil::GetFileInfoInternal(
*platform_file_path = local_path;
} else if (error == base::PLATFORM_FILE_ERROR_NOT_FOUND) {
LOG(WARNING) << "Lost a backing file.";
- InvalidateUsageCache(context, origin, type);
+ InvalidateUsageCache(context, url.origin(), url.type());
if (!db->RemoveFileInfo(file_id))
return base::PLATFORM_FILE_ERROR_FAILED;
}
@@ -1074,23 +1049,19 @@ PlatformFileError ObfuscatedFileUtil::GetFileInfoInternal(
PlatformFileError ObfuscatedFileUtil::CreateFile(
FileSystemOperationContext* context,
const base::FilePath& src_file_path,
- const GURL& dest_origin,
- FileSystemType dest_type,
+ const FileSystemURL& dest_url,
FileInfo* dest_file_info, int file_flags, PlatformFile* handle) {
if (handle)
*handle = base::kInvalidPlatformFileValue;
- SandboxDirectoryDatabase* db = GetDirectoryDatabase(
- dest_origin, dest_type, true);
+ SandboxDirectoryDatabase* db = GetDirectoryDatabase(dest_url, true);
PlatformFileError error = base::PLATFORM_FILE_OK;
- base::FilePath root = GetDirectoryForOriginAndType(
- dest_origin, dest_type, false, &error);
+ base::FilePath root = GetDirectoryForURL(dest_url, false, &error);
if (error != base::PLATFORM_FILE_OK)
return error;
base::FilePath dest_local_path;
- error = GenerateNewLocalPath(db, context, dest_origin, dest_type,
- &dest_local_path);
+ error = GenerateNewLocalPath(db, context, dest_url, &dest_local_path);
if (error != base::PLATFORM_FILE_OK)
return error;
@@ -1099,7 +1070,10 @@ PlatformFileError ObfuscatedFileUtil::CreateFile(
DCHECK(!file_flags);
DCHECK(!handle);
error = NativeFileUtil::CopyOrMoveFile(
- src_file_path, dest_local_path, true /* copy */);
+ src_file_path, dest_local_path,
+ FileSystemOperation::OPTION_NONE,
+ fileapi::NativeFileUtil::CopyOrMoveModeForDestination(dest_url,
+ true /* copy */));
created = true;
} else {
if (base::PathExists(dest_local_path)) {
@@ -1108,7 +1082,7 @@ PlatformFileError ObfuscatedFileUtil::CreateFile(
return base::PLATFORM_FILE_ERROR_FAILED;
}
LOG(WARNING) << "A stray file detected";
- InvalidateUsageCache(context, dest_origin, dest_type);
+ InvalidateUsageCache(context, dest_url.origin(), dest_url.type());
}
if (handle) {
@@ -1156,27 +1130,21 @@ PlatformFileError ObfuscatedFileUtil::CreateFile(
}
base::FilePath ObfuscatedFileUtil::DataPathToLocalPath(
- const GURL& origin, FileSystemType type, const base::FilePath& data_path) {
+ const FileSystemURL& url, const base::FilePath& data_path) {
PlatformFileError error = base::PLATFORM_FILE_OK;
- base::FilePath root = GetDirectoryForOriginAndType(
- origin, type, false, &error);
+ base::FilePath root = GetDirectoryForURL(url, false, &error);
if (error != base::PLATFORM_FILE_OK)
return base::FilePath();
return root.Append(data_path);
}
std::string ObfuscatedFileUtil::GetDirectoryDatabaseKey(
- const GURL& origin, FileSystemType type) {
- std::string type_string = GetFileSystemTypeString(type);
+ const GURL& origin, const std::string& type_string) {
if (type_string.empty()) {
- LOG(WARNING) << "Unknown filesystem type requested:" << type;
+ LOG(WARNING) << "Unknown filesystem type requested:" << type_string;
return std::string();
}
// For isolated origin we just use a type string as a key.
- if (HasIsolatedStorage(origin)) {
- CHECK_EQ(isolated_origin_.spec(), origin.spec());
- return type_string;
- }
return webkit_database::GetIdentifierFromOrigin(origin) +
type_string;
}
@@ -1186,8 +1154,9 @@ std::string ObfuscatedFileUtil::GetDirectoryDatabaseKey(
// Ah, in that case don't even get here?
// Still doesn't answer the quota issue, though.
SandboxDirectoryDatabase* ObfuscatedFileUtil::GetDirectoryDatabase(
- const GURL& origin, FileSystemType type, bool create) {
- std::string key = GetDirectoryDatabaseKey(origin, type);
+ const FileSystemURL& url, bool create) {
+ std::string key = GetDirectoryDatabaseKey(
+ url.origin(), CallGetTypeStringForURL(url));
if (key.empty())
return NULL;
@@ -1198,10 +1167,10 @@ SandboxDirectoryDatabase* ObfuscatedFileUtil::GetDirectoryDatabase(
}
PlatformFileError error = base::PLATFORM_FILE_OK;
- base::FilePath path = GetDirectoryForOriginAndType(
- origin, type, create, &error);
+ base::FilePath path = GetDirectoryForURL(url, create, &error);
if (error != base::PLATFORM_FILE_OK) {
- LOG(WARNING) << "Failed to get origin+type directory: " << path.value();
+ LOG(WARNING) << "Failed to get origin+type directory: "
+ << url.DebugString() << " error:" << error;
return NULL;
}
MarkUsed();
@@ -1212,11 +1181,7 @@ SandboxDirectoryDatabase* ObfuscatedFileUtil::GetDirectoryDatabase(
base::FilePath ObfuscatedFileUtil::GetDirectoryForOrigin(
const GURL& origin, bool create, base::PlatformFileError* error_code) {
- if (HasIsolatedStorage(origin)) {
- CHECK_EQ(isolated_origin_.spec(), origin.spec());
- }
-
- if (!InitOriginDatabase(create)) {
+ if (!InitOriginDatabase(origin, create)) {
if (error_code) {
*error_code = create ?
base::PLATFORM_FILE_ERROR_FAILED :
@@ -1251,7 +1216,7 @@ base::FilePath ObfuscatedFileUtil::GetDirectoryForOrigin(
}
if (!exists_in_fs) {
- if (!create || !file_util::CreateDirectory(path)) {
+ if (!create || !base::CreateDirectory(path)) {
if (error_code)
*error_code = create ?
base::PLATFORM_FILE_ERROR_FAILED :
@@ -1270,8 +1235,8 @@ void ObfuscatedFileUtil::InvalidateUsageCache(
FileSystemOperationContext* context,
const GURL& origin,
FileSystemType type) {
- context->file_system_context()->sandbox_delegate()->
- InvalidateUsageCache(origin, type);
+ if (sandbox_delegate_)
+ sandbox_delegate_->InvalidateUsageCache(origin, type);
}
void ObfuscatedFileUtil::MarkUsed() {
@@ -1296,39 +1261,50 @@ void ObfuscatedFileUtil::DropDatabases() {
timer_.reset();
}
-bool ObfuscatedFileUtil::InitOriginDatabase(bool create) {
+bool ObfuscatedFileUtil::InitOriginDatabase(const GURL& origin_hint,
+ bool create) {
if (origin_database_)
return true;
if (!create && !base::DirectoryExists(file_system_directory_))
return false;
- if (!file_util::CreateDirectory(file_system_directory_)) {
+ if (!base::CreateDirectory(file_system_directory_)) {
LOG(WARNING) << "Failed to create FileSystem directory: " <<
file_system_directory_.value();
return false;
}
- origin_database_.reset(
- new SandboxOriginDatabase(file_system_directory_));
+ SandboxPrioritizedOriginDatabase* prioritized_origin_database =
+ new SandboxPrioritizedOriginDatabase(file_system_directory_);
+ origin_database_.reset(prioritized_origin_database);
+
+ if (origin_hint.is_empty() || !HasIsolatedStorage(origin_hint))
+ return true;
+
+ const std::string isolated_origin_string =
+ webkit_database::GetIdentifierFromOrigin(origin_hint);
+ // TODO(kinuko): Deprecate this after a few release cycles, e.g. around M33.
base::FilePath isolated_origin_dir = file_system_directory_.Append(
- SandboxIsolatedOriginDatabase::kOriginDirectory);
+ SandboxIsolatedOriginDatabase::kObsoleteOriginDirectory);
if (base::DirectoryExists(isolated_origin_dir) &&
- !isolated_origin_.is_empty()) {
- SandboxIsolatedOriginDatabase::MigrateBackDatabase(
- webkit_database::GetIdentifierFromOrigin(isolated_origin_),
+ prioritized_origin_database->GetSandboxOriginDatabase()) {
+ SandboxIsolatedOriginDatabase::MigrateBackFromObsoleteOriginDatabase(
+ isolated_origin_string,
file_system_directory_,
- static_cast<SandboxOriginDatabase*>(origin_database_.get()));
+ prioritized_origin_database->GetSandboxOriginDatabase());
}
+ prioritized_origin_database->InitializePrimaryOrigin(
+ isolated_origin_string);
+
return true;
}
PlatformFileError ObfuscatedFileUtil::GenerateNewLocalPath(
SandboxDirectoryDatabase* db,
FileSystemOperationContext* context,
- const GURL& origin,
- FileSystemType type,
+ const FileSystemURL& url,
base::FilePath* local_path) {
DCHECK(local_path);
int64 number;
@@ -1336,8 +1312,7 @@ PlatformFileError ObfuscatedFileUtil::GenerateNewLocalPath(
return base::PLATFORM_FILE_ERROR_FAILED;
PlatformFileError error = base::PLATFORM_FILE_OK;
- base::FilePath new_local_path = GetDirectoryForOriginAndType(
- origin, type, false, &error);
+ base::FilePath new_local_path = GetDirectoryForURL(url, false, &error);
if (error != base::PLATFORM_FILE_OK)
return base::PLATFORM_FILE_ERROR_FAILED;
@@ -1363,8 +1338,7 @@ PlatformFileError ObfuscatedFileUtil::CreateOrOpenInternal(
DCHECK(!(file_flags & (base::PLATFORM_FILE_DELETE_ON_CLOSE |
base::PLATFORM_FILE_HIDDEN | base::PLATFORM_FILE_EXCLUSIVE_READ |
base::PLATFORM_FILE_EXCLUSIVE_WRITE)));
- SandboxDirectoryDatabase* db = GetDirectoryDatabase(
- url.origin(), url.type(), true);
+ SandboxDirectoryDatabase* db = GetDirectoryDatabase(url, true);
if (!db)
return base::PLATFORM_FILE_ERROR_FAILED;
FileId file_id;
@@ -1386,8 +1360,7 @@ PlatformFileError ObfuscatedFileUtil::CreateOrOpenInternal(
return base::PLATFORM_FILE_ERROR_NO_SPACE;
PlatformFileError error = CreateFile(
context, base::FilePath(),
- url.origin(), url.type(), &file_info,
- file_flags, file_handle);
+ url, &file_info, file_flags, file_handle);
if (created && base::PLATFORM_FILE_OK == error) {
*created = true;
UpdateUsage(context, url, growth);
@@ -1404,8 +1377,7 @@ PlatformFileError ObfuscatedFileUtil::CreateOrOpenInternal(
base::FilePath local_path;
FileInfo file_info;
base::PlatformFileError error = GetFileInfoInternal(
- db, context, url.origin(), url.type(), file_id,
- &file_info, &platform_file_info, &local_path);
+ db, context, url, file_id, &file_info, &platform_file_info, &local_path);
if (error != base::PLATFORM_FILE_OK)
return error;
if (file_info.is_directory())
@@ -1439,24 +1411,8 @@ PlatformFileError ObfuscatedFileUtil::CreateOrOpenInternal(
}
bool ObfuscatedFileUtil::HasIsolatedStorage(const GURL& origin) {
- if (special_storage_policy_.get() &&
- special_storage_policy_->HasIsolatedStorage(origin)) {
- if (isolated_origin_.is_empty())
- isolated_origin_ = origin;
- // Record isolated_origin_, but always disable for now.
- // crbug.com/264429
- if (isolated_origin_ != origin) {
- UMA_HISTOGRAM_ENUMERATION("FileSystem.IsolatedOriginStatus",
- kIsolatedOriginDontMatch,
- kIsolatedOriginStatusMax);
- } else {
- UMA_HISTOGRAM_ENUMERATION("FileSystem.IsolatedOriginStatus",
- kIsolatedOriginMatch,
- kIsolatedOriginStatusMax);
- }
- return false;
- }
- return false;
+ return special_storage_policy_.get() &&
+ special_storage_policy_->HasIsolatedStorage(origin);
}
} // namespace fileapi
diff --git a/chromium/webkit/browser/fileapi/obfuscated_file_util.h b/chromium/webkit/browser/fileapi/obfuscated_file_util.h
index 0d9750d1fb5..05d55308d84 100644
--- a/chromium/webkit/browser/fileapi/obfuscated_file_util.h
+++ b/chromium/webkit/browser/fileapi/obfuscated_file_util.h
@@ -6,8 +6,11 @@
#define WEBKIT_BROWSER_FILEAPI_OBFUSCATED_FILE_UTIL_H_
#include <map>
+#include <set>
#include <string>
+#include <vector>
+#include "base/callback_forward.h"
#include "base/files/file_path.h"
#include "base/files/file_util_proxy.h"
#include "base/gtest_prod_util.h"
@@ -16,6 +19,7 @@
#include "webkit/browser/fileapi/file_system_file_util.h"
#include "webkit/browser/fileapi/file_system_url.h"
#include "webkit/browser/fileapi/sandbox_directory_database.h"
+#include "webkit/browser/fileapi/sandbox_file_system_backend_delegate.h"
#include "webkit/browser/webkit_storage_browser_export.h"
#include "webkit/common/blob/shareable_file_reference.h"
#include "webkit/common/fileapi/file_system_types.h"
@@ -37,6 +41,21 @@ class FileSystemOperationContext;
class SandboxOriginDatabaseInterface;
class TimedTaskHelper;
+// This file util stores directory information in LevelDB to obfuscate
+// and to neutralize virtual file paths given by arbitrary apps.
+// Files are stored with two-level isolation: per-origin and per-type.
+// The isolation is done by storing data in separate directory partitions.
+// For example, a file in Temporary file system for origin 'www.example.com'
+// is stored in a different partition for a file in Persistent file system
+// for the same origin, or for Temporary file system for another origin.
+//
+// * Per-origin directory name information is stored in a separate LevelDB,
+// which is maintained by SandboxOriginDatabase.
+// * Per-type directory name information is given by
+// GetTypeStringForURLCallback that is given in CTOR.
+// We use a small static mapping (e.g. 't' for Temporary type) for
+// regular sandbox filesystems.
+//
// The overall implementation philosophy of this class is that partial failures
// should leave us with an intact database; we'd prefer to leak the occasional
// backing file than have a database entry whose backing file is missing. When
@@ -58,13 +77,32 @@ class WEBKIT_STORAGE_BROWSER_EXPORT_PRIVATE ObfuscatedFileUtil
virtual GURL Next() = 0;
// Returns the current origin's information.
- virtual bool HasFileSystemType(FileSystemType type) const = 0;
+ // |type_string| must be ascii string.
+ virtual bool HasTypeDirectory(const std::string& type_string) const = 0;
};
+ typedef base::Callback<std::string(const FileSystemURL&)>
+ GetTypeStringForURLCallback;
+
+ // |get_type_string_for_url| is user-defined callback that should return
+ // a type string for the given FileSystemURL. The type string is used
+ // to provide per-type isolation in the sandboxed filesystem directory.
+ // Note that this method is called on file_task_runner.
+ //
+ // |known_type_strings| are known type string names that this file system
+ // should care about.
+ // This info is used to determine whether we could delete the entire
+ // origin directory or not in DeleteDirectoryForOriginAndType. If no directory
+ // for any known type exists the origin directory may get deleted when
+ // one origin/type pair is deleted.
+ //
ObfuscatedFileUtil(
quota::SpecialStoragePolicy* special_storage_policy,
const base::FilePath& file_system_directory,
- base::SequencedTaskRunner* file_task_runner);
+ base::SequencedTaskRunner* file_task_runner,
+ const GetTypeStringForURLCallback& get_type_string_for_url,
+ const std::set<std::string>& known_type_strings,
+ SandboxFileSystemBackendDelegate* sandbox_delegate);
virtual ~ObfuscatedFileUtil();
// FileSystemFileUtil overrides.
@@ -110,6 +148,7 @@ class WEBKIT_STORAGE_BROWSER_EXPORT_PRIVATE ObfuscatedFileUtil
FileSystemOperationContext* context,
const FileSystemURL& src_url,
const FileSystemURL& dest_url,
+ CopyOrMoveOption option,
bool copy) OVERRIDE;
virtual base::PlatformFileError CopyInForeignFile(
FileSystemOperationContext* context,
@@ -142,26 +181,24 @@ class WEBKIT_STORAGE_BROWSER_EXPORT_PRIVATE ObfuscatedFileUtil
// Gets the topmost directory specific to this origin and type. This will
// contain both the directory database's files and all the backing file
// subdirectories.
- // Returns an empty path if the directory is undefined (e.g. because |type|
- // is invalid). If the directory is defined, it will be returned, even if
+ // Returns the topmost origin directory if |type_string| is empty.
+ // Returns an empty path if the directory is undefined.
+ // If the directory is defined, it will be returned, even if
// there is a file system error (e.g. the directory doesn't exist on disk and
// |create| is false). Callers should always check |error_code| to make sure
// the returned path is usable.
base::FilePath GetDirectoryForOriginAndType(
const GURL& origin,
- FileSystemType type,
+ const std::string& type_string,
bool create,
base::PlatformFileError* error_code);
// Deletes the topmost directory specific to this origin and type. This will
// delete its directory database.
- bool DeleteDirectoryForOriginAndType(const GURL& origin, FileSystemType type);
-
- // TODO(ericu): This doesn't really feel like it belongs in this class.
- // The previous version lives in FileSystemPathManager, but perhaps
- // SandboxFileSystemBackend would be better?
- static base::FilePath::StringType GetDirectoryNameForType(
- FileSystemType type);
+ // Deletes the topmost origin directory if |type_string| is empty.
+ bool DeleteDirectoryForOriginAndType(
+ const GURL& origin,
+ const std::string& type_string);
// This method and all methods of its returned class must be called only on
// the FILE thread. The caller is responsible for deleting the returned
@@ -170,7 +207,8 @@ class WEBKIT_STORAGE_BROWSER_EXPORT_PRIVATE ObfuscatedFileUtil
// Deletes a directory database from the database list in the ObfuscatedFSFU
// and destroys the database on the disk.
- bool DestroyDirectoryDatabase(const GURL& origin, FileSystemType type);
+ bool DestroyDirectoryDatabase(const GURL& origin,
+ const std::string& type_string);
// Computes a cost for storing a given file in the obfuscated FSFU.
// As the cost of a file is independent of the cost of its parent directories,
@@ -179,13 +217,20 @@ class WEBKIT_STORAGE_BROWSER_EXPORT_PRIVATE ObfuscatedFileUtil
// on each path segment and add the results.
static int64 ComputeFilePathCost(const base::FilePath& path);
- void MaybePrepopulateDatabase();
+ // Tries to prepopulate directory database for the given type strings.
+ // This tries from the first one in the given type_strings and stops
+ // once it succeeds to do so for one database (i.e. it prepopulates
+ // at most one database).
+ void MaybePrepopulateDatabase(
+ const std::vector<std::string>& type_strings_to_prepopulate);
private:
typedef SandboxDirectoryDatabase::FileId FileId;
typedef SandboxDirectoryDatabase::FileInfo FileInfo;
friend class ObfuscatedFileEnumerator;
+ friend class ObfuscatedFileUtilTest;
+ friend class QuotaBackendImplTest;
FRIEND_TEST_ALL_PREFIXES(ObfuscatedFileUtilTest, MaybeDropDatabasesAliveCase);
FRIEND_TEST_ALL_PREFIXES(ObfuscatedFileUtilTest,
MaybeDropDatabasesAlreadyDeletedCase);
@@ -196,11 +241,26 @@ class WEBKIT_STORAGE_BROWSER_EXPORT_PRIVATE ObfuscatedFileUtil
FRIEND_TEST_ALL_PREFIXES(ObfuscatedFileUtilTest,
MigrationBackFromIsolated);
+ // Helper method to create an obfuscated file util for regular
+ // (temporary, persistent) file systems. Used only for testing.
+ // Note: this is implemented in sandbox_file_system_backend_delegate.cc.
+ static ObfuscatedFileUtil* CreateForTesting(
+ quota::SpecialStoragePolicy* special_storage_policy,
+ const base::FilePath& file_system_directory,
+ base::SequencedTaskRunner* file_task_runner);
+
+ base::FilePath GetDirectoryForURL(
+ const FileSystemURL& url,
+ bool create,
+ base::PlatformFileError* error_code);
+
+ // This just calls get_type_string_for_url_ callback that is given in ctor.
+ std::string CallGetTypeStringForURL(const FileSystemURL& url);
+
base::PlatformFileError GetFileInfoInternal(
SandboxDirectoryDatabase* db,
FileSystemOperationContext* context,
- const GURL& origin,
- FileSystemType type,
+ const FileSystemURL& url,
FileId file_id,
FileInfo* local_info,
base::PlatformFileInfo* file_info,
@@ -220,8 +280,7 @@ class WEBKIT_STORAGE_BROWSER_EXPORT_PRIVATE ObfuscatedFileUtil
base::PlatformFileError CreateFile(
FileSystemOperationContext* context,
const base::FilePath& source_file_path,
- const GURL& dest_origin,
- FileSystemType dest_type,
+ const FileSystemURL& dest_url,
FileInfo* dest_file_info,
int file_flags,
base::PlatformFile* handle);
@@ -230,23 +289,23 @@ class WEBKIT_STORAGE_BROWSER_EXPORT_PRIVATE ObfuscatedFileUtil
// field] to an absolute platform path that can be given to the native
// filesystem.
base::FilePath DataPathToLocalPath(
- const GURL& origin,
- FileSystemType type,
+ const FileSystemURL& url,
const base::FilePath& data_file_path);
- std::string GetDirectoryDatabaseKey(const GURL& origin, FileSystemType type);
+ std::string GetDirectoryDatabaseKey(const GURL& origin,
+ const std::string& type_string);
// This returns NULL if |create| flag is false and a filesystem does not
- // exist for the given |origin_url| and |type|.
+ // exist for the given |url|.
// For read operations |create| should be false.
- SandboxDirectoryDatabase* GetDirectoryDatabase(
- const GURL& origin_url, FileSystemType type, bool create);
+ SandboxDirectoryDatabase* GetDirectoryDatabase(const FileSystemURL& url,
+ bool create);
// Gets the topmost directory specific to this origin. This will
// contain both the filesystem type subdirectories.
base::FilePath GetDirectoryForOrigin(const GURL& origin,
- bool create,
- base::PlatformFileError* error_code);
+ bool create,
+ base::PlatformFileError* error_code);
void InvalidateUsageCache(FileSystemOperationContext* context,
const GURL& origin,
@@ -254,13 +313,15 @@ class WEBKIT_STORAGE_BROWSER_EXPORT_PRIVATE ObfuscatedFileUtil
void MarkUsed();
void DropDatabases();
- bool InitOriginDatabase(bool create);
+
+ // Initializes the origin database. |origin_hint| may be used as a hint
+ // for initializing database if it's not empty.
+ bool InitOriginDatabase(const GURL& origin_hint, bool create);
base::PlatformFileError GenerateNewLocalPath(
SandboxDirectoryDatabase* db,
FileSystemOperationContext* context,
- const GURL& origin,
- FileSystemType type,
+ const FileSystemURL& url,
base::FilePath* local_path);
base::PlatformFileError CreateOrOpenInternal(
@@ -284,9 +345,11 @@ class WEBKIT_STORAGE_BROWSER_EXPORT_PRIVATE ObfuscatedFileUtil
scoped_refptr<base::SequencedTaskRunner> file_task_runner_;
scoped_ptr<TimedTaskHelper> timer_;
- // If this instance is initialized for an isolated partition, this should
- // only see a single origin.
- GURL isolated_origin_;
+ GetTypeStringForURLCallback get_type_string_for_url_;
+ std::set<std::string> known_type_strings_;
+
+ // Not owned.
+ SandboxFileSystemBackendDelegate* sandbox_delegate_;
DISALLOW_COPY_AND_ASSIGN(ObfuscatedFileUtil);
};
diff --git a/chromium/webkit/browser/fileapi/obfuscated_file_util_unittest.cc b/chromium/webkit/browser/fileapi/obfuscated_file_util_unittest.cc
deleted file mode 100644
index c37b17caa23..00000000000
--- a/chromium/webkit/browser/fileapi/obfuscated_file_util_unittest.cc
+++ /dev/null
@@ -1,2403 +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 <set>
-#include <string>
-#include <vector>
-
-#include "base/bind.h"
-#include "base/file_util.h"
-#include "base/files/file_path.h"
-#include "base/files/scoped_temp_dir.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/platform_file.h"
-#include "base/run_loop.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "webkit/browser/fileapi/async_file_test_helper.h"
-#include "webkit/browser/fileapi/external_mount_points.h"
-#include "webkit/browser/fileapi/file_system_backend.h"
-#include "webkit/browser/fileapi/file_system_context.h"
-#include "webkit/browser/fileapi/file_system_operation_context.h"
-#include "webkit/browser/fileapi/file_system_usage_cache.h"
-#include "webkit/browser/fileapi/mock_file_change_observer.h"
-#include "webkit/browser/fileapi/mock_file_system_context.h"
-#include "webkit/browser/fileapi/obfuscated_file_util.h"
-#include "webkit/browser/fileapi/sandbox_directory_database.h"
-#include "webkit/browser/fileapi/sandbox_file_system_test_helper.h"
-#include "webkit/browser/fileapi/sandbox_isolated_origin_database.h"
-#include "webkit/browser/fileapi/sandbox_origin_database.h"
-#include "webkit/browser/fileapi/test_file_set.h"
-#include "webkit/browser/quota/mock_special_storage_policy.h"
-#include "webkit/browser/quota/quota_manager.h"
-#include "webkit/common/database/database_identifier.h"
-#include "webkit/common/quota/quota_types.h"
-
-namespace fileapi {
-
-namespace {
-
-bool FileExists(const base::FilePath& path) {
- return base::PathExists(path) && !base::DirectoryExists(path);
-}
-
-int64 GetSize(const base::FilePath& path) {
- int64 size;
- EXPECT_TRUE(file_util::GetFileSize(path, &size));
- return size;
-}
-
-// After a move, the dest exists and the source doesn't.
-// After a copy, both source and dest exist.
-struct CopyMoveTestCaseRecord {
- bool is_copy_not_move;
- const char source_path[64];
- const char dest_path[64];
- bool cause_overwrite;
-};
-
-const CopyMoveTestCaseRecord kCopyMoveTestCases[] = {
- // This is the combinatoric set of:
- // rename vs. same-name
- // different directory vs. same directory
- // overwrite vs. no-overwrite
- // copy vs. move
- // We can never be called with source and destination paths identical, so
- // those cases are omitted.
- {true, "dir0/file0", "dir0/file1", false},
- {false, "dir0/file0", "dir0/file1", false},
- {true, "dir0/file0", "dir0/file1", true},
- {false, "dir0/file0", "dir0/file1", true},
-
- {true, "dir0/file0", "dir1/file0", false},
- {false, "dir0/file0", "dir1/file0", false},
- {true, "dir0/file0", "dir1/file0", true},
- {false, "dir0/file0", "dir1/file0", true},
- {true, "dir0/file0", "dir1/file1", false},
- {false, "dir0/file0", "dir1/file1", false},
- {true, "dir0/file0", "dir1/file1", true},
- {false, "dir0/file0", "dir1/file1", true},
-};
-
-struct OriginEnumerationTestRecord {
- std::string origin_url;
- bool has_temporary;
- bool has_persistent;
-};
-
-const OriginEnumerationTestRecord kOriginEnumerationTestRecords[] = {
- {"http://example.com", false, true},
- {"http://example1.com", true, false},
- {"https://example1.com", true, true},
- {"file://", false, true},
- {"http://example.com:8000", false, true},
-};
-
-FileSystemURL FileSystemURLAppend(
- const FileSystemURL& url, const base::FilePath::StringType& child) {
- return FileSystemURL::CreateForTest(
- url.origin(), url.mount_type(), url.virtual_path().Append(child));
-}
-
-FileSystemURL FileSystemURLAppendUTF8(
- const FileSystemURL& url, const std::string& child) {
- return FileSystemURL::CreateForTest(
- url.origin(),
- url.mount_type(),
- url.virtual_path().Append(base::FilePath::FromUTF8Unsafe(child)));
-}
-
-FileSystemURL FileSystemURLDirName(const FileSystemURL& url) {
- return FileSystemURL::CreateForTest(
- url.origin(), url.mount_type(), VirtualPath::DirName(url.virtual_path()));
-}
-
-} // namespace (anonymous)
-
-// TODO(ericu): The vast majority of this and the other FSFU subclass tests
-// could theoretically be shared. It would basically be a FSFU interface
-// compliance test, and only the subclass-specific bits that look into the
-// implementation would need to be written per-subclass.
-class ObfuscatedFileUtilTest : public testing::Test {
- public:
- ObfuscatedFileUtilTest()
- : origin_(GURL("http://www.example.com")),
- type_(kFileSystemTypeTemporary),
- weak_factory_(this),
- sandbox_file_system_(origin_, type_),
- quota_status_(quota::kQuotaStatusUnknown),
- usage_(-1) {
- }
-
- virtual void SetUp() {
- ASSERT_TRUE(data_dir_.CreateUniqueTempDir());
-
- storage_policy_ = new quota::MockSpecialStoragePolicy();
-
- quota_manager_ =
- new quota::QuotaManager(false /* is_incognito */,
- data_dir_.path(),
- base::MessageLoopProxy::current().get(),
- base::MessageLoopProxy::current().get(),
- storage_policy_.get());
-
- // Every time we create a new sandbox_file_system helper,
- // it creates another context, which creates another path manager,
- // another sandbox_backend, and another OFU.
- // We need to pass in the context to skip all that.
- file_system_context_ = CreateFileSystemContextForTesting(
- quota_manager_->proxy(),
- data_dir_.path());
-
- sandbox_file_system_.SetUp(file_system_context_.get());
-
- change_observers_ = MockFileChangeObserver::CreateList(&change_observer_);
- }
-
- virtual void TearDown() {
- quota_manager_ = NULL;
- sandbox_file_system_.TearDown();
- }
-
- scoped_ptr<FileSystemOperationContext> LimitedContext(
- int64 allowed_bytes_growth) {
- scoped_ptr<FileSystemOperationContext> context(
- sandbox_file_system_.NewOperationContext());
- context->set_allowed_bytes_growth(allowed_bytes_growth);
- return context.Pass();
- }
-
- scoped_ptr<FileSystemOperationContext> UnlimitedContext() {
- return LimitedContext(kint64max);
- }
-
- FileSystemOperationContext* NewContext(
- SandboxFileSystemTestHelper* file_system) {
- change_observer()->ResetCount();
- FileSystemOperationContext* context;
- if (file_system)
- context = file_system->NewOperationContext();
- else
- context = sandbox_file_system_.NewOperationContext();
- // Setting allowed_bytes_growth big enough for all tests.
- context->set_allowed_bytes_growth(1024 * 1024);
- context->set_change_observers(change_observers());
- return context;
- }
-
- const ChangeObserverList& change_observers() const {
- return change_observers_;
- }
-
- MockFileChangeObserver* change_observer() {
- return &change_observer_;
- }
-
- // This can only be used after SetUp has run and created file_system_context_
- // and obfuscated_file_util_.
- // Use this for tests which need to run in multiple origins; we need a test
- // helper per origin.
- SandboxFileSystemTestHelper* NewFileSystem(
- const GURL& origin, fileapi::FileSystemType type) {
- SandboxFileSystemTestHelper* file_system =
- new SandboxFileSystemTestHelper(origin, type);
-
- file_system->SetUp(file_system_context_.get());
- return file_system;
- }
-
- ObfuscatedFileUtil* ofu() {
- return static_cast<ObfuscatedFileUtil*>(sandbox_file_system_.file_util());
- }
-
- const base::FilePath& test_directory() const {
- return data_dir_.path();
- }
-
- const GURL& origin() const {
- return origin_;
- }
-
- fileapi::FileSystemType type() const {
- return type_;
- }
-
- int64 ComputeTotalFileSize() {
- return sandbox_file_system_.ComputeCurrentOriginUsage() -
- sandbox_file_system_.ComputeCurrentDirectoryDatabaseUsage();
- }
-
- void GetUsageFromQuotaManager() {
- int64 quota = -1;
- quota_status_ =
- AsyncFileTestHelper::GetUsageAndQuota(quota_manager_.get(),
- origin(),
- sandbox_file_system_.type(),
- &usage_,
- &quota);
- EXPECT_EQ(quota::kQuotaStatusOk, quota_status_);
- }
-
- void RevokeUsageCache() {
- quota_manager_->ResetUsageTracker(sandbox_file_system_.storage_type());
- usage_cache()->Delete(sandbox_file_system_.GetUsageCachePath());
- }
-
- int64 SizeByQuotaUtil() {
- return sandbox_file_system_.GetCachedOriginUsage();
- }
-
- int64 SizeInUsageFile() {
- base::RunLoop().RunUntilIdle();
- int64 usage = 0;
- return usage_cache()->GetUsage(
- sandbox_file_system_.GetUsageCachePath(), &usage) ? usage : -1;
- }
-
- bool PathExists(const FileSystemURL& url) {
- scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
- base::PlatformFileInfo file_info;
- base::FilePath platform_path;
- base::PlatformFileError error = ofu()->GetFileInfo(
- context.get(), url, &file_info, &platform_path);
- return error == base::PLATFORM_FILE_OK;
- }
-
- bool DirectoryExists(const FileSystemURL& url) {
- return AsyncFileTestHelper::DirectoryExists(file_system_context(), url);
- }
-
- int64 usage() const { return usage_; }
- FileSystemUsageCache* usage_cache() {
- return sandbox_file_system_.usage_cache();
- }
-
- FileSystemURL CreateURLFromUTF8(const std::string& path) {
- return sandbox_file_system_.CreateURLFromUTF8(path);
- }
-
- int64 PathCost(const FileSystemURL& url) {
- return ObfuscatedFileUtil::ComputeFilePathCost(url.path());
- }
-
- FileSystemURL CreateURL(const base::FilePath& path) {
- return sandbox_file_system_.CreateURL(path);
- }
-
- void CheckFileAndCloseHandle(
- const FileSystemURL& url, base::PlatformFile file_handle) {
- scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
- base::FilePath local_path;
- EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->GetLocalFilePath(
- context.get(), url, &local_path));
-
- base::PlatformFileInfo file_info0;
- base::FilePath data_path;
- EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->GetFileInfo(
- context.get(), url, &file_info0, &data_path));
- EXPECT_EQ(data_path, local_path);
- EXPECT_TRUE(FileExists(data_path));
- EXPECT_EQ(0, GetSize(data_path));
-
- const char data[] = "test data";
- const int length = arraysize(data) - 1;
-
- if (base::kInvalidPlatformFileValue == file_handle) {
- bool created = true;
- base::PlatformFileError error;
- file_handle = base::CreatePlatformFile(
- data_path,
- base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_WRITE,
- &created,
- &error);
- ASSERT_NE(base::kInvalidPlatformFileValue, file_handle);
- ASSERT_EQ(base::PLATFORM_FILE_OK, error);
- EXPECT_FALSE(created);
- }
- ASSERT_EQ(length, base::WritePlatformFile(file_handle, 0, data, length));
- EXPECT_TRUE(base::ClosePlatformFile(file_handle));
-
- base::PlatformFileInfo file_info1;
- EXPECT_EQ(length, GetSize(data_path));
- context.reset(NewContext(NULL));
- EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->GetFileInfo(
- context.get(), url, &file_info1, &data_path));
- EXPECT_EQ(data_path, local_path);
-
- EXPECT_FALSE(file_info0.is_directory);
- EXPECT_FALSE(file_info1.is_directory);
- EXPECT_FALSE(file_info0.is_symbolic_link);
- EXPECT_FALSE(file_info1.is_symbolic_link);
- EXPECT_EQ(0, file_info0.size);
- EXPECT_EQ(length, file_info1.size);
- EXPECT_LE(file_info0.last_modified, file_info1.last_modified);
-
- context.reset(NewContext(NULL));
- EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->Truncate(
- context.get(), url, length * 2));
- EXPECT_EQ(length * 2, GetSize(data_path));
-
- context.reset(NewContext(NULL));
- EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->Truncate(
- context.get(), url, 0));
- EXPECT_EQ(0, GetSize(data_path));
- }
-
- void ValidateTestDirectory(
- const FileSystemURL& root_url,
- const std::set<base::FilePath::StringType>& files,
- const std::set<base::FilePath::StringType>& directories) {
- scoped_ptr<FileSystemOperationContext> context;
- std::set<base::FilePath::StringType>::const_iterator iter;
- for (iter = files.begin(); iter != files.end(); ++iter) {
- bool created = true;
- context.reset(NewContext(NULL));
- ASSERT_EQ(base::PLATFORM_FILE_OK,
- ofu()->EnsureFileExists(
- context.get(), FileSystemURLAppend(root_url, *iter),
- &created));
- ASSERT_FALSE(created);
- }
- for (iter = directories.begin(); iter != directories.end(); ++iter) {
- context.reset(NewContext(NULL));
- EXPECT_TRUE(DirectoryExists(
- FileSystemURLAppend(root_url, *iter)));
- }
- }
-
- class UsageVerifyHelper {
- public:
- UsageVerifyHelper(scoped_ptr<FileSystemOperationContext> context,
- SandboxFileSystemTestHelper* file_system,
- int64 expected_usage)
- : context_(context.Pass()),
- sandbox_file_system_(file_system),
- expected_usage_(expected_usage) {}
-
- ~UsageVerifyHelper() {
- base::RunLoop().RunUntilIdle();
- Check();
- }
-
- FileSystemOperationContext* context() {
- return context_.get();
- }
-
- private:
- void Check() {
- ASSERT_EQ(expected_usage_,
- sandbox_file_system_->GetCachedOriginUsage());
- }
-
- scoped_ptr<FileSystemOperationContext> context_;
- SandboxFileSystemTestHelper* sandbox_file_system_;
- int64 expected_usage_;
- };
-
- scoped_ptr<UsageVerifyHelper> AllowUsageIncrease(int64 requested_growth) {
- int64 usage = sandbox_file_system_.GetCachedOriginUsage();
- return scoped_ptr<UsageVerifyHelper>(new UsageVerifyHelper(
- LimitedContext(requested_growth),
- &sandbox_file_system_, usage + requested_growth));
- }
-
- scoped_ptr<UsageVerifyHelper> DisallowUsageIncrease(int64 requested_growth) {
- int64 usage = sandbox_file_system_.GetCachedOriginUsage();
- return scoped_ptr<UsageVerifyHelper>(new UsageVerifyHelper(
- LimitedContext(requested_growth - 1), &sandbox_file_system_, usage));
- }
-
- void FillTestDirectory(
- const FileSystemURL& root_url,
- std::set<base::FilePath::StringType>* files,
- std::set<base::FilePath::StringType>* directories) {
- scoped_ptr<FileSystemOperationContext> context;
- std::vector<DirectoryEntry> entries;
- EXPECT_EQ(base::PLATFORM_FILE_OK,
- AsyncFileTestHelper::ReadDirectory(
- file_system_context(), root_url, &entries));
- EXPECT_EQ(0UL, entries.size());
-
- files->clear();
- files->insert(FILE_PATH_LITERAL("first"));
- files->insert(FILE_PATH_LITERAL("second"));
- files->insert(FILE_PATH_LITERAL("third"));
- directories->clear();
- directories->insert(FILE_PATH_LITERAL("fourth"));
- directories->insert(FILE_PATH_LITERAL("fifth"));
- directories->insert(FILE_PATH_LITERAL("sixth"));
- std::set<base::FilePath::StringType>::iterator iter;
- for (iter = files->begin(); iter != files->end(); ++iter) {
- bool created = false;
- context.reset(NewContext(NULL));
- ASSERT_EQ(base::PLATFORM_FILE_OK,
- ofu()->EnsureFileExists(
- context.get(),
- FileSystemURLAppend(root_url, *iter),
- &created));
- ASSERT_TRUE(created);
- }
- for (iter = directories->begin(); iter != directories->end(); ++iter) {
- bool exclusive = true;
- bool recursive = false;
- context.reset(NewContext(NULL));
- EXPECT_EQ(base::PLATFORM_FILE_OK,
- ofu()->CreateDirectory(
- context.get(),
- FileSystemURLAppend(root_url, *iter),
- exclusive, recursive));
- }
- ValidateTestDirectory(root_url, *files, *directories);
- }
-
- void TestReadDirectoryHelper(const FileSystemURL& root_url) {
- std::set<base::FilePath::StringType> files;
- std::set<base::FilePath::StringType> directories;
- FillTestDirectory(root_url, &files, &directories);
-
- scoped_ptr<FileSystemOperationContext> context;
- std::vector<DirectoryEntry> entries;
- context.reset(NewContext(NULL));
- EXPECT_EQ(base::PLATFORM_FILE_OK,
- AsyncFileTestHelper::ReadDirectory(
- file_system_context(), root_url, &entries));
- std::vector<DirectoryEntry>::iterator entry_iter;
- EXPECT_EQ(files.size() + directories.size(), entries.size());
- EXPECT_TRUE(change_observer()->HasNoChange());
- for (entry_iter = entries.begin(); entry_iter != entries.end();
- ++entry_iter) {
- const DirectoryEntry& entry = *entry_iter;
- std::set<base::FilePath::StringType>::iterator iter =
- files.find(entry.name);
- if (iter != files.end()) {
- EXPECT_FALSE(entry.is_directory);
- files.erase(iter);
- continue;
- }
- iter = directories.find(entry.name);
- EXPECT_FALSE(directories.end() == iter);
- EXPECT_TRUE(entry.is_directory);
- directories.erase(iter);
- }
- }
-
- void TestTouchHelper(const FileSystemURL& url, bool is_file) {
- base::Time last_access_time = base::Time::Now();
- base::Time last_modified_time = base::Time::Now();
-
- scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
- EXPECT_EQ(base::PLATFORM_FILE_OK,
- ofu()->Touch(
- context.get(), url, last_access_time, last_modified_time));
- // Currently we fire no change notifications for Touch.
- EXPECT_TRUE(change_observer()->HasNoChange());
- base::FilePath local_path;
- base::PlatformFileInfo file_info;
- context.reset(NewContext(NULL));
- EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->GetFileInfo(
- context.get(), url, &file_info, &local_path));
- // We compare as time_t here to lower our resolution, to avoid false
- // negatives caused by conversion to the local filesystem's native
- // representation and back.
- EXPECT_EQ(file_info.last_modified.ToTimeT(), last_modified_time.ToTimeT());
-
- context.reset(NewContext(NULL));
- last_modified_time += base::TimeDelta::FromHours(1);
- last_access_time += base::TimeDelta::FromHours(14);
- EXPECT_EQ(base::PLATFORM_FILE_OK,
- ofu()->Touch(
- context.get(), url, last_access_time, last_modified_time));
- EXPECT_TRUE(change_observer()->HasNoChange());
- context.reset(NewContext(NULL));
- EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->GetFileInfo(
- context.get(), url, &file_info, &local_path));
- EXPECT_EQ(file_info.last_modified.ToTimeT(), last_modified_time.ToTimeT());
- if (is_file) // Directories in OFU don't support atime.
- EXPECT_EQ(file_info.last_accessed.ToTimeT(), last_access_time.ToTimeT());
- }
-
- void TestCopyInForeignFileHelper(bool overwrite) {
- base::ScopedTempDir source_dir;
- ASSERT_TRUE(source_dir.CreateUniqueTempDir());
- base::FilePath root_file_path = source_dir.path();
- base::FilePath src_file_path = root_file_path.AppendASCII("file_name");
- FileSystemURL dest_url = CreateURLFromUTF8("new file");
- int64 src_file_length = 87;
-
- base::PlatformFileError error_code;
- bool created = false;
- int file_flags = base::PLATFORM_FILE_CREATE | base::PLATFORM_FILE_WRITE;
- base::PlatformFile file_handle =
- base::CreatePlatformFile(
- src_file_path, file_flags, &created, &error_code);
- EXPECT_TRUE(created);
- ASSERT_EQ(base::PLATFORM_FILE_OK, error_code);
- ASSERT_NE(base::kInvalidPlatformFileValue, file_handle);
- ASSERT_TRUE(base::TruncatePlatformFile(file_handle, src_file_length));
- EXPECT_TRUE(base::ClosePlatformFile(file_handle));
-
- scoped_ptr<FileSystemOperationContext> context;
-
- if (overwrite) {
- context.reset(NewContext(NULL));
- EXPECT_EQ(base::PLATFORM_FILE_OK,
- ofu()->EnsureFileExists(context.get(), dest_url, &created));
- EXPECT_TRUE(created);
-
- // We must have observed one (and only one) create_file_count.
- EXPECT_EQ(1, change_observer()->get_and_reset_create_file_count());
- EXPECT_TRUE(change_observer()->HasNoChange());
- }
-
- const int64 path_cost =
- ObfuscatedFileUtil::ComputeFilePathCost(dest_url.path());
- if (!overwrite) {
- // Verify that file creation requires sufficient quota for the path.
- 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_file_path, dest_url));
- }
-
- 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_file_path, dest_url));
-
- EXPECT_TRUE(PathExists(dest_url));
- EXPECT_FALSE(DirectoryExists(dest_url));
-
- context.reset(NewContext(NULL));
- base::PlatformFileInfo file_info;
- base::FilePath data_path;
- EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->GetFileInfo(
- context.get(), dest_url, &file_info, &data_path));
- EXPECT_NE(data_path, src_file_path);
- EXPECT_TRUE(FileExists(data_path));
- EXPECT_EQ(src_file_length, GetSize(data_path));
-
- EXPECT_EQ(base::PLATFORM_FILE_OK,
- ofu()->DeleteFile(context.get(), dest_url));
- }
-
- void ClearTimestamp(const FileSystemURL& url) {
- scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
- EXPECT_EQ(base::PLATFORM_FILE_OK,
- ofu()->Touch(context.get(), url, base::Time(), base::Time()));
- EXPECT_EQ(base::Time(), GetModifiedTime(url));
- }
-
- base::Time GetModifiedTime(const FileSystemURL& url) {
- scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
- base::FilePath data_path;
- base::PlatformFileInfo file_info;
- context.reset(NewContext(NULL));
- EXPECT_EQ(base::PLATFORM_FILE_OK,
- ofu()->GetFileInfo(context.get(), url, &file_info, &data_path));
- EXPECT_TRUE(change_observer()->HasNoChange());
- return file_info.last_modified;
- }
-
- void TestDirectoryTimestampHelper(const FileSystemURL& base_dir,
- bool copy,
- bool overwrite) {
- scoped_ptr<FileSystemOperationContext> context;
- const FileSystemURL src_dir_url(
- FileSystemURLAppendUTF8(base_dir, "foo_dir"));
- const FileSystemURL dest_dir_url(
- FileSystemURLAppendUTF8(base_dir, "bar_dir"));
-
- const FileSystemURL src_file_url(
- FileSystemURLAppendUTF8(src_dir_url, "hoge"));
- const FileSystemURL dest_file_url(
- FileSystemURLAppendUTF8(dest_dir_url, "fuga"));
-
- context.reset(NewContext(NULL));
- EXPECT_EQ(base::PLATFORM_FILE_OK,
- ofu()->CreateDirectory(context.get(), src_dir_url, true, true));
- context.reset(NewContext(NULL));
- EXPECT_EQ(base::PLATFORM_FILE_OK,
- ofu()->CreateDirectory(context.get(), dest_dir_url, true, true));
-
- bool created = false;
- context.reset(NewContext(NULL));
- EXPECT_EQ(base::PLATFORM_FILE_OK,
- ofu()->EnsureFileExists(context.get(), src_file_url, &created));
- if (overwrite) {
- context.reset(NewContext(NULL));
- EXPECT_EQ(base::PLATFORM_FILE_OK,
- ofu()->EnsureFileExists(context.get(),
- dest_file_url, &created));
- }
-
- ClearTimestamp(src_dir_url);
- ClearTimestamp(dest_dir_url);
- context.reset(NewContext(NULL));
- EXPECT_EQ(base::PLATFORM_FILE_OK,
- ofu()->CopyOrMoveFile(context.get(),
- src_file_url, dest_file_url,
- copy));
- if (copy)
- EXPECT_EQ(base::Time(), GetModifiedTime(src_dir_url));
- else
- EXPECT_NE(base::Time(), GetModifiedTime(src_dir_url));
- EXPECT_NE(base::Time(), GetModifiedTime(dest_dir_url));
- }
-
- int64 ComputeCurrentUsage() {
- return sandbox_file_system_.ComputeCurrentOriginUsage() -
- sandbox_file_system_.ComputeCurrentDirectoryDatabaseUsage();
- }
-
- FileSystemContext* file_system_context() {
- return sandbox_file_system_.file_system_context();
- }
-
- const base::FilePath& data_dir_path() const {
- return data_dir_.path();
- }
-
- protected:
- base::ScopedTempDir data_dir_;
- base::MessageLoop message_loop_;
- scoped_refptr<quota::MockSpecialStoragePolicy> storage_policy_;
- scoped_refptr<quota::QuotaManager> quota_manager_;
- scoped_refptr<FileSystemContext> file_system_context_;
- GURL origin_;
- fileapi::FileSystemType type_;
- base::WeakPtrFactory<ObfuscatedFileUtilTest> weak_factory_;
- SandboxFileSystemTestHelper sandbox_file_system_;
- quota::QuotaStatusCode quota_status_;
- int64 usage_;
- MockFileChangeObserver change_observer_;
- ChangeObserverList change_observers_;
-
- DISALLOW_COPY_AND_ASSIGN(ObfuscatedFileUtilTest);
-};
-
-TEST_F(ObfuscatedFileUtilTest, TestCreateAndDeleteFile) {
- base::PlatformFile file_handle = base::kInvalidPlatformFileValue;
- bool created;
- FileSystemURL url = CreateURLFromUTF8("fake/file");
- scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
- int file_flags = base::PLATFORM_FILE_CREATE | base::PLATFORM_FILE_WRITE;
-
- EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND,
- ofu()->CreateOrOpen(
- context.get(), url, file_flags, &file_handle,
- &created));
-
- context.reset(NewContext(NULL));
- EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND,
- ofu()->DeleteFile(context.get(), url));
-
- url = CreateURLFromUTF8("test file");
-
- EXPECT_TRUE(change_observer()->HasNoChange());
-
- // Verify that file creation requires sufficient quota for the path.
- context.reset(NewContext(NULL));
- context->set_allowed_bytes_growth(
- ObfuscatedFileUtil::ComputeFilePathCost(url.path()) - 1);
- ASSERT_EQ(base::PLATFORM_FILE_ERROR_NO_SPACE,
- ofu()->CreateOrOpen(
- context.get(), url, file_flags, &file_handle, &created));
-
- context.reset(NewContext(NULL));
- context->set_allowed_bytes_growth(
- ObfuscatedFileUtil::ComputeFilePathCost(url.path()));
- ASSERT_EQ(base::PLATFORM_FILE_OK,
- ofu()->CreateOrOpen(
- context.get(), url, file_flags, &file_handle, &created));
- ASSERT_TRUE(created);
- EXPECT_EQ(1, change_observer()->get_and_reset_create_file_count());
- EXPECT_NE(base::kInvalidPlatformFileValue, file_handle);
-
- CheckFileAndCloseHandle(url, file_handle);
-
- context.reset(NewContext(NULL));
- base::FilePath local_path;
- EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->GetLocalFilePath(
- context.get(), url, &local_path));
- EXPECT_TRUE(base::PathExists(local_path));
-
- // Verify that deleting a file isn't stopped by zero quota, and that it frees
- // up quote from its path.
- context.reset(NewContext(NULL));
- context->set_allowed_bytes_growth(0);
- EXPECT_EQ(base::PLATFORM_FILE_OK,
- ofu()->DeleteFile(context.get(), url));
- EXPECT_EQ(1, change_observer()->get_and_reset_remove_file_count());
- EXPECT_FALSE(base::PathExists(local_path));
- EXPECT_EQ(ObfuscatedFileUtil::ComputeFilePathCost(url.path()),
- context->allowed_bytes_growth());
-
- context.reset(NewContext(NULL));
- bool exclusive = true;
- bool recursive = true;
- FileSystemURL directory_url = CreateURLFromUTF8(
- "series/of/directories");
- url = FileSystemURLAppendUTF8(directory_url, "file name");
- EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->CreateDirectory(
- context.get(), directory_url, exclusive, recursive));
- // The oepration created 3 directories recursively.
- EXPECT_EQ(3, change_observer()->get_and_reset_create_directory_count());
-
- context.reset(NewContext(NULL));
- file_handle = base::kInvalidPlatformFileValue;
- ASSERT_EQ(base::PLATFORM_FILE_OK,
- ofu()->CreateOrOpen(
- context.get(), url, file_flags, &file_handle, &created));
- ASSERT_TRUE(created);
- EXPECT_EQ(1, change_observer()->get_and_reset_create_file_count());
- EXPECT_NE(base::kInvalidPlatformFileValue, file_handle);
-
- CheckFileAndCloseHandle(url, file_handle);
-
- context.reset(NewContext(NULL));
- EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->GetLocalFilePath(
- context.get(), url, &local_path));
- EXPECT_TRUE(base::PathExists(local_path));
-
- context.reset(NewContext(NULL));
- EXPECT_EQ(base::PLATFORM_FILE_OK,
- ofu()->DeleteFile(context.get(), url));
- EXPECT_EQ(1, change_observer()->get_and_reset_remove_file_count());
- EXPECT_FALSE(base::PathExists(local_path));
-
- // Make sure we have no unexpected changes.
- EXPECT_TRUE(change_observer()->HasNoChange());
-}
-
-TEST_F(ObfuscatedFileUtilTest, TestTruncate) {
- bool created = false;
- FileSystemURL url = CreateURLFromUTF8("file");
- scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
-
- EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND,
- ofu()->Truncate(context.get(), url, 4));
-
- context.reset(NewContext(NULL));
- ASSERT_EQ(base::PLATFORM_FILE_OK,
- ofu()->EnsureFileExists(context.get(), url, &created));
- ASSERT_TRUE(created);
- EXPECT_EQ(1, change_observer()->get_and_reset_create_file_count());
-
- context.reset(NewContext(NULL));
- base::FilePath local_path;
- EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->GetLocalFilePath(
- context.get(), url, &local_path));
- EXPECT_EQ(0, GetSize(local_path));
-
- context.reset(NewContext(NULL));
- EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->Truncate(
- context.get(), url, 10));
- EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count());
- EXPECT_EQ(10, GetSize(local_path));
-
- context.reset(NewContext(NULL));
- EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->Truncate(
- context.get(), url, 1));
- EXPECT_EQ(1, GetSize(local_path));
- EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count());
-
- EXPECT_FALSE(DirectoryExists(url));
- EXPECT_TRUE(PathExists(url));
-
- // Make sure we have no unexpected changes.
- EXPECT_TRUE(change_observer()->HasNoChange());
-}
-
-TEST_F(ObfuscatedFileUtilTest, TestQuotaOnTruncation) {
- bool created = false;
- FileSystemURL url = CreateURLFromUTF8("file");
-
- ASSERT_EQ(base::PLATFORM_FILE_OK,
- ofu()->EnsureFileExists(
- AllowUsageIncrease(PathCost(url))->context(),
- url, &created));
- ASSERT_TRUE(created);
- ASSERT_EQ(0, ComputeTotalFileSize());
-
- ASSERT_EQ(base::PLATFORM_FILE_OK,
- ofu()->Truncate(
- AllowUsageIncrease(1020)->context(),
- url, 1020));
- ASSERT_EQ(1020, ComputeTotalFileSize());
-
- ASSERT_EQ(base::PLATFORM_FILE_OK,
- ofu()->Truncate(
- AllowUsageIncrease(-1020)->context(),
- url, 0));
- ASSERT_EQ(0, ComputeTotalFileSize());
-
- EXPECT_EQ(base::PLATFORM_FILE_ERROR_NO_SPACE,
- ofu()->Truncate(
- DisallowUsageIncrease(1021)->context(),
- url, 1021));
- ASSERT_EQ(0, ComputeTotalFileSize());
-
- EXPECT_EQ(base::PLATFORM_FILE_OK,
- ofu()->Truncate(
- AllowUsageIncrease(1020)->context(),
- url, 1020));
- ASSERT_EQ(1020, ComputeTotalFileSize());
-
- EXPECT_EQ(base::PLATFORM_FILE_OK,
- ofu()->Truncate(
- AllowUsageIncrease(0)->context(),
- url, 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(), url, 1019));
- ASSERT_EQ(1019, ComputeTotalFileSize());
- }
-
- // Delete backing file to make following truncation fail.
- base::FilePath local_path;
- ASSERT_EQ(base::PLATFORM_FILE_OK,
- ofu()->GetLocalFilePath(
- UnlimitedContext().get(),
- url, &local_path));
- ASSERT_FALSE(local_path.empty());
- ASSERT_TRUE(base::DeleteFile(local_path, false));
-
- EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND,
- ofu()->Truncate(
- LimitedContext(1234).get(),
- url, 1234));
- ASSERT_EQ(0, ComputeTotalFileSize());
-}
-
-TEST_F(ObfuscatedFileUtilTest, TestEnsureFileExists) {
- FileSystemURL url = CreateURLFromUTF8("fake/file");
- bool created = false;
- scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
- EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND,
- ofu()->EnsureFileExists(
- context.get(), url, &created));
- EXPECT_TRUE(change_observer()->HasNoChange());
-
- // Verify that file creation requires sufficient quota for the path.
- context.reset(NewContext(NULL));
- url = CreateURLFromUTF8("test file");
- created = false;
- context->set_allowed_bytes_growth(
- ObfuscatedFileUtil::ComputeFilePathCost(url.path()) - 1);
- ASSERT_EQ(base::PLATFORM_FILE_ERROR_NO_SPACE,
- ofu()->EnsureFileExists(context.get(), url, &created));
- ASSERT_FALSE(created);
- EXPECT_TRUE(change_observer()->HasNoChange());
-
- context.reset(NewContext(NULL));
- context->set_allowed_bytes_growth(
- ObfuscatedFileUtil::ComputeFilePathCost(url.path()));
- ASSERT_EQ(base::PLATFORM_FILE_OK,
- ofu()->EnsureFileExists(context.get(), url, &created));
- ASSERT_TRUE(created);
- EXPECT_EQ(1, change_observer()->get_and_reset_create_file_count());
-
- CheckFileAndCloseHandle(url, base::kInvalidPlatformFileValue);
-
- context.reset(NewContext(NULL));
- ASSERT_EQ(base::PLATFORM_FILE_OK,
- ofu()->EnsureFileExists(context.get(), url, &created));
- ASSERT_FALSE(created);
- EXPECT_TRUE(change_observer()->HasNoChange());
-
- // Also test in a subdirectory.
- url = CreateURLFromUTF8("path/to/file.txt");
- context.reset(NewContext(NULL));
- bool exclusive = true;
- bool recursive = true;
- EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->CreateDirectory(
- context.get(),
- FileSystemURLDirName(url),
- exclusive, recursive));
- // 2 directories: path/ and path/to.
- EXPECT_EQ(2, change_observer()->get_and_reset_create_directory_count());
-
- context.reset(NewContext(NULL));
- ASSERT_EQ(base::PLATFORM_FILE_OK,
- ofu()->EnsureFileExists(context.get(), url, &created));
- ASSERT_TRUE(created);
- EXPECT_FALSE(DirectoryExists(url));
- EXPECT_TRUE(PathExists(url));
- EXPECT_TRUE(change_observer()->HasNoChange());
-}
-
-TEST_F(ObfuscatedFileUtilTest, TestDirectoryOps) {
- scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
-
- bool exclusive = false;
- bool recursive = false;
- FileSystemURL url = CreateURLFromUTF8("foo/bar");
- EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, ofu()->CreateDirectory(
- context.get(), url, exclusive, recursive));
-
- context.reset(NewContext(NULL));
- EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND,
- ofu()->DeleteDirectory(context.get(), url));
-
- FileSystemURL root = CreateURLFromUTF8(std::string());
- EXPECT_FALSE(DirectoryExists(url));
- EXPECT_FALSE(PathExists(url));
- context.reset(NewContext(NULL));
- EXPECT_TRUE(ofu()->IsDirectoryEmpty(context.get(), root));
-
- context.reset(NewContext(NULL));
- exclusive = false;
- recursive = true;
- EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->CreateDirectory(
- context.get(), url, exclusive, recursive));
- EXPECT_EQ(2, change_observer()->get_and_reset_create_directory_count());
-
- EXPECT_TRUE(DirectoryExists(url));
- EXPECT_TRUE(PathExists(url));
-
- context.reset(NewContext(NULL));
- EXPECT_FALSE(ofu()->IsDirectoryEmpty(context.get(), root));
- EXPECT_TRUE(DirectoryExists(FileSystemURLDirName(url)));
-
- context.reset(NewContext(NULL));
- EXPECT_FALSE(ofu()->IsDirectoryEmpty(context.get(),
- FileSystemURLDirName(url)));
-
- // Can't remove a non-empty directory.
- context.reset(NewContext(NULL));
- EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_EMPTY,
- ofu()->DeleteDirectory(context.get(),
- FileSystemURLDirName(url)));
- EXPECT_TRUE(change_observer()->HasNoChange());
-
- base::PlatformFileInfo file_info;
- base::FilePath local_path;
- EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->GetFileInfo(
- context.get(), url, &file_info, &local_path));
- EXPECT_TRUE(local_path.empty());
- EXPECT_TRUE(file_info.is_directory);
- EXPECT_FALSE(file_info.is_symbolic_link);
-
- // Same create again should succeed, since exclusive is false.
- context.reset(NewContext(NULL));
- EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->CreateDirectory(
- context.get(), url, exclusive, recursive));
- EXPECT_TRUE(change_observer()->HasNoChange());
-
- exclusive = true;
- recursive = true;
- context.reset(NewContext(NULL));
- EXPECT_EQ(base::PLATFORM_FILE_ERROR_EXISTS, ofu()->CreateDirectory(
- context.get(), url, exclusive, recursive));
- EXPECT_TRUE(change_observer()->HasNoChange());
-
- // Verify that deleting a directory isn't stopped by zero quota, and that it
- // frees up quota from its path.
- context.reset(NewContext(NULL));
- context->set_allowed_bytes_growth(0);
- EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->DeleteDirectory(context.get(), url));
- EXPECT_EQ(1, change_observer()->get_and_reset_remove_directory_count());
- EXPECT_EQ(ObfuscatedFileUtil::ComputeFilePathCost(url.path()),
- context->allowed_bytes_growth());
-
- url = CreateURLFromUTF8("foo/bop");
-
- EXPECT_FALSE(DirectoryExists(url));
- EXPECT_FALSE(PathExists(url));
-
- context.reset(NewContext(NULL));
- EXPECT_TRUE(ofu()->IsDirectoryEmpty(context.get(), url));
- EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, ofu()->GetFileInfo(
- context.get(), url, &file_info, &local_path));
-
- // Verify that file creation requires sufficient quota for the path.
- exclusive = true;
- recursive = false;
- context.reset(NewContext(NULL));
- context->set_allowed_bytes_growth(
- ObfuscatedFileUtil::ComputeFilePathCost(url.path()) - 1);
- EXPECT_EQ(base::PLATFORM_FILE_ERROR_NO_SPACE, ofu()->CreateDirectory(
- context.get(), url, exclusive, recursive));
- EXPECT_TRUE(change_observer()->HasNoChange());
-
- context.reset(NewContext(NULL));
- context->set_allowed_bytes_growth(
- ObfuscatedFileUtil::ComputeFilePathCost(url.path()));
- EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->CreateDirectory(
- context.get(), url, exclusive, recursive));
- EXPECT_EQ(1, change_observer()->get_and_reset_create_directory_count());
-
- EXPECT_TRUE(DirectoryExists(url));
- EXPECT_TRUE(PathExists(url));
-
- exclusive = true;
- recursive = false;
- context.reset(NewContext(NULL));
- EXPECT_EQ(base::PLATFORM_FILE_ERROR_EXISTS, ofu()->CreateDirectory(
- context.get(), url, exclusive, recursive));
- EXPECT_TRUE(change_observer()->HasNoChange());
-
- exclusive = true;
- recursive = false;
- url = CreateURLFromUTF8("foo");
- context.reset(NewContext(NULL));
- EXPECT_EQ(base::PLATFORM_FILE_ERROR_EXISTS, ofu()->CreateDirectory(
- context.get(), url, exclusive, recursive));
- EXPECT_TRUE(change_observer()->HasNoChange());
-
- url = CreateURLFromUTF8("blah");
-
- EXPECT_FALSE(DirectoryExists(url));
- EXPECT_FALSE(PathExists(url));
-
- exclusive = true;
- recursive = false;
- context.reset(NewContext(NULL));
- EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->CreateDirectory(
- context.get(), url, exclusive, recursive));
- EXPECT_EQ(1, change_observer()->get_and_reset_create_directory_count());
-
- EXPECT_TRUE(DirectoryExists(url));
- EXPECT_TRUE(PathExists(url));
-
- exclusive = true;
- recursive = false;
- context.reset(NewContext(NULL));
- EXPECT_EQ(base::PLATFORM_FILE_ERROR_EXISTS, ofu()->CreateDirectory(
- context.get(), url, exclusive, recursive));
- EXPECT_TRUE(change_observer()->HasNoChange());
-}
-
-TEST_F(ObfuscatedFileUtilTest, TestReadDirectory) {
- scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
- bool exclusive = true;
- bool recursive = true;
- FileSystemURL url = CreateURLFromUTF8("directory/to/use");
- EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->CreateDirectory(
- context.get(), url, exclusive, recursive));
- TestReadDirectoryHelper(url);
-}
-
-TEST_F(ObfuscatedFileUtilTest, TestReadRootWithSlash) {
- TestReadDirectoryHelper(CreateURLFromUTF8(std::string()));
-}
-
-TEST_F(ObfuscatedFileUtilTest, TestReadRootWithEmptyString) {
- TestReadDirectoryHelper(CreateURLFromUTF8("/"));
-}
-
-TEST_F(ObfuscatedFileUtilTest, TestReadDirectoryOnFile) {
- FileSystemURL url = CreateURLFromUTF8("file");
- scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
-
- bool created = false;
- ASSERT_EQ(base::PLATFORM_FILE_OK,
- ofu()->EnsureFileExists(context.get(), url, &created));
- ASSERT_TRUE(created);
-
- std::vector<DirectoryEntry> entries;
- EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY,
- AsyncFileTestHelper::ReadDirectory(
- file_system_context(), url, &entries));
-
- EXPECT_TRUE(ofu()->IsDirectoryEmpty(context.get(), url));
-}
-
-TEST_F(ObfuscatedFileUtilTest, TestTouch) {
- FileSystemURL url = CreateURLFromUTF8("file");
- scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
-
- base::Time last_access_time = base::Time::Now();
- base::Time last_modified_time = base::Time::Now();
-
- // It's not there yet.
- EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND,
- ofu()->Touch(
- context.get(), url, last_access_time, last_modified_time));
-
- // OK, now create it.
- context.reset(NewContext(NULL));
- bool created = false;
- ASSERT_EQ(base::PLATFORM_FILE_OK,
- ofu()->EnsureFileExists(context.get(), url, &created));
- ASSERT_TRUE(created);
- TestTouchHelper(url, true);
-
- // Now test a directory:
- context.reset(NewContext(NULL));
- bool exclusive = true;
- bool recursive = false;
- url = CreateURLFromUTF8("dir");
- ASSERT_EQ(base::PLATFORM_FILE_OK, ofu()->CreateDirectory(context.get(),
- url, exclusive, recursive));
- TestTouchHelper(url, false);
-}
-
-TEST_F(ObfuscatedFileUtilTest, TestPathQuotas) {
- FileSystemURL url = CreateURLFromUTF8("fake/file");
- scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
-
- url = CreateURLFromUTF8("file name");
- context->set_allowed_bytes_growth(5);
- bool created = false;
- EXPECT_EQ(base::PLATFORM_FILE_ERROR_NO_SPACE,
- ofu()->EnsureFileExists(context.get(), url, &created));
- EXPECT_FALSE(created);
- context->set_allowed_bytes_growth(1024);
- EXPECT_EQ(base::PLATFORM_FILE_OK,
- ofu()->EnsureFileExists(context.get(), url, &created));
- EXPECT_TRUE(created);
- int64 path_cost = ObfuscatedFileUtil::ComputeFilePathCost(url.path());
- EXPECT_EQ(1024 - path_cost, context->allowed_bytes_growth());
-
- context->set_allowed_bytes_growth(1024);
- bool exclusive = true;
- bool recursive = true;
- url = CreateURLFromUTF8("directory/to/use");
- std::vector<base::FilePath::StringType> components;
- url.path().GetComponents(&components);
- path_cost = 0;
- typedef std::vector<base::FilePath::StringType>::iterator iterator;
- for (iterator iter = components.begin();
- iter != components.end(); ++iter) {
- path_cost += ObfuscatedFileUtil::ComputeFilePathCost(
- base::FilePath(*iter));
- }
- context.reset(NewContext(NULL));
- context->set_allowed_bytes_growth(1024);
- EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->CreateDirectory(
- context.get(), url, exclusive, recursive));
- EXPECT_EQ(1024 - path_cost, context->allowed_bytes_growth());
-}
-
-TEST_F(ObfuscatedFileUtilTest, TestCopyOrMoveFileNotFound) {
- FileSystemURL source_url = CreateURLFromUTF8("path0.txt");
- FileSystemURL dest_url = CreateURLFromUTF8("path1.txt");
- scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
-
- bool is_copy_not_move = false;
- EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND,
- ofu()->CopyOrMoveFile(context.get(), source_url, dest_url,
- is_copy_not_move));
- EXPECT_TRUE(change_observer()->HasNoChange());
- context.reset(NewContext(NULL));
- is_copy_not_move = true;
- EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND,
- ofu()->CopyOrMoveFile(context.get(), source_url, dest_url,
- is_copy_not_move));
- EXPECT_TRUE(change_observer()->HasNoChange());
- source_url = CreateURLFromUTF8("dir/dir/file");
- bool exclusive = true;
- bool recursive = true;
- context.reset(NewContext(NULL));
- ASSERT_EQ(base::PLATFORM_FILE_OK, ofu()->CreateDirectory(
- context.get(),
- FileSystemURLDirName(source_url),
- exclusive, recursive));
- EXPECT_EQ(2, change_observer()->get_and_reset_create_directory_count());
- is_copy_not_move = false;
- EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND,
- ofu()->CopyOrMoveFile(context.get(), source_url, dest_url,
- is_copy_not_move));
- EXPECT_TRUE(change_observer()->HasNoChange());
- context.reset(NewContext(NULL));
- is_copy_not_move = true;
- EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND,
- ofu()->CopyOrMoveFile(context.get(), source_url, dest_url,
- is_copy_not_move));
- EXPECT_TRUE(change_observer()->HasNoChange());
-}
-
-TEST_F(ObfuscatedFileUtilTest, TestCopyOrMoveFileSuccess) {
- const int64 kSourceLength = 5;
- const int64 kDestLength = 50;
-
- for (size_t i = 0; i < arraysize(kCopyMoveTestCases); ++i) {
- SCOPED_TRACE(testing::Message() << "kCopyMoveTestCase " << i);
- const CopyMoveTestCaseRecord& test_case = kCopyMoveTestCases[i];
- SCOPED_TRACE(testing::Message() << "\t is_copy_not_move " <<
- test_case.is_copy_not_move);
- SCOPED_TRACE(testing::Message() << "\t source_path " <<
- test_case.source_path);
- SCOPED_TRACE(testing::Message() << "\t dest_path " <<
- test_case.dest_path);
- SCOPED_TRACE(testing::Message() << "\t cause_overwrite " <<
- test_case.cause_overwrite);
- scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
-
- bool exclusive = false;
- bool recursive = true;
- FileSystemURL source_url = CreateURLFromUTF8(test_case.source_path);
- FileSystemURL dest_url = CreateURLFromUTF8(test_case.dest_path);
-
- context.reset(NewContext(NULL));
- ASSERT_EQ(base::PLATFORM_FILE_OK, ofu()->CreateDirectory(
- context.get(),
- FileSystemURLDirName(source_url),
- exclusive, recursive));
- context.reset(NewContext(NULL));
- ASSERT_EQ(base::PLATFORM_FILE_OK, ofu()->CreateDirectory(
- context.get(),
- FileSystemURLDirName(dest_url),
- exclusive, recursive));
-
- bool created = false;
- context.reset(NewContext(NULL));
- ASSERT_EQ(base::PLATFORM_FILE_OK,
- ofu()->EnsureFileExists(context.get(), source_url, &created));
- ASSERT_TRUE(created);
- context.reset(NewContext(NULL));
- ASSERT_EQ(base::PLATFORM_FILE_OK,
- ofu()->Truncate(context.get(), source_url, kSourceLength));
-
- if (test_case.cause_overwrite) {
- context.reset(NewContext(NULL));
- created = false;
- ASSERT_EQ(base::PLATFORM_FILE_OK,
- ofu()->EnsureFileExists(context.get(), dest_url, &created));
- ASSERT_TRUE(created);
- context.reset(NewContext(NULL));
- ASSERT_EQ(base::PLATFORM_FILE_OK,
- ofu()->Truncate(context.get(), dest_url, kDestLength));
- }
-
- context.reset(NewContext(NULL));
- EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->CopyOrMoveFile(context.get(),
- source_url, dest_url, test_case.is_copy_not_move));
-
- if (test_case.is_copy_not_move) {
- base::PlatformFileInfo file_info;
- base::FilePath local_path;
- context.reset(NewContext(NULL));
- EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->GetFileInfo(
- context.get(), source_url, &file_info, &local_path));
- EXPECT_EQ(kSourceLength, file_info.size);
- EXPECT_EQ(base::PLATFORM_FILE_OK,
- ofu()->DeleteFile(context.get(), source_url));
- } else {
- base::PlatformFileInfo file_info;
- base::FilePath local_path;
- context.reset(NewContext(NULL));
- EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, ofu()->GetFileInfo(
- context.get(), source_url, &file_info, &local_path));
- }
- base::PlatformFileInfo file_info;
- base::FilePath local_path;
- EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->GetFileInfo(
- context.get(), dest_url, &file_info, &local_path));
- EXPECT_EQ(kSourceLength, file_info.size);
-
- EXPECT_EQ(base::PLATFORM_FILE_OK,
- ofu()->DeleteFile(context.get(), dest_url));
- }
-}
-
-TEST_F(ObfuscatedFileUtilTest, TestCopyPathQuotas) {
- FileSystemURL src_url = CreateURLFromUTF8("src path");
- FileSystemURL dest_url = CreateURLFromUTF8("destination path");
- scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
- bool created = false;
- ASSERT_EQ(base::PLATFORM_FILE_OK, ofu()->EnsureFileExists(
- context.get(), src_url, &created));
-
- bool is_copy = true;
- // Copy, no overwrite.
- context->set_allowed_bytes_growth(
- ObfuscatedFileUtil::ComputeFilePathCost(dest_url.path()) - 1);
- EXPECT_EQ(base::PLATFORM_FILE_ERROR_NO_SPACE,
- ofu()->CopyOrMoveFile(context.get(), src_url, dest_url, is_copy));
- context.reset(NewContext(NULL));
- context->set_allowed_bytes_growth(
- ObfuscatedFileUtil::ComputeFilePathCost(dest_url.path()));
- EXPECT_EQ(base::PLATFORM_FILE_OK,
- ofu()->CopyOrMoveFile(context.get(), src_url, dest_url, is_copy));
-
- // Copy, with overwrite.
- context.reset(NewContext(NULL));
- context->set_allowed_bytes_growth(0);
- EXPECT_EQ(base::PLATFORM_FILE_OK,
- ofu()->CopyOrMoveFile(context.get(), src_url, dest_url, is_copy));
-}
-
-TEST_F(ObfuscatedFileUtilTest, TestMovePathQuotasWithRename) {
- FileSystemURL src_url = CreateURLFromUTF8("src path");
- FileSystemURL dest_url = CreateURLFromUTF8("destination path");
- scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
- bool created = false;
- ASSERT_EQ(base::PLATFORM_FILE_OK, ofu()->EnsureFileExists(
- context.get(), src_url, &created));
-
- bool is_copy = false;
- // Move, rename, no overwrite.
- context.reset(NewContext(NULL));
- context->set_allowed_bytes_growth(
- ObfuscatedFileUtil::ComputeFilePathCost(dest_url.path()) -
- ObfuscatedFileUtil::ComputeFilePathCost(src_url.path()) - 1);
- EXPECT_EQ(base::PLATFORM_FILE_ERROR_NO_SPACE,
- ofu()->CopyOrMoveFile(context.get(), src_url, dest_url, is_copy));
- context.reset(NewContext(NULL));
- context->set_allowed_bytes_growth(
- ObfuscatedFileUtil::ComputeFilePathCost(dest_url.path()) -
- ObfuscatedFileUtil::ComputeFilePathCost(src_url.path()));
- EXPECT_EQ(base::PLATFORM_FILE_OK,
- ofu()->CopyOrMoveFile(context.get(), src_url, dest_url, is_copy));
-
- context.reset(NewContext(NULL));
- ASSERT_EQ(base::PLATFORM_FILE_OK, ofu()->EnsureFileExists(
- context.get(), src_url, &created));
-
- // Move, rename, with overwrite.
- context.reset(NewContext(NULL));
- context->set_allowed_bytes_growth(0);
- EXPECT_EQ(base::PLATFORM_FILE_OK,
- ofu()->CopyOrMoveFile(context.get(), src_url, dest_url, is_copy));
-}
-
-TEST_F(ObfuscatedFileUtilTest, TestMovePathQuotasWithoutRename) {
- FileSystemURL src_url = CreateURLFromUTF8("src path");
- scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
- bool created = false;
- ASSERT_EQ(base::PLATFORM_FILE_OK, ofu()->EnsureFileExists(
- context.get(), src_url, &created));
-
- bool exclusive = true;
- bool recursive = false;
- FileSystemURL dir_url = CreateURLFromUTF8("directory path");
- context.reset(NewContext(NULL));
- ASSERT_EQ(base::PLATFORM_FILE_OK, ofu()->CreateDirectory(
- context.get(), dir_url, exclusive, recursive));
-
- FileSystemURL dest_url = FileSystemURLAppend(
- dir_url, src_url.path().value());
-
- bool is_copy = false;
- int64 allowed_bytes_growth = -1000; // Over quota, this should still work.
- // Move, no rename, no overwrite.
- context.reset(NewContext(NULL));
- context->set_allowed_bytes_growth(allowed_bytes_growth);
- EXPECT_EQ(base::PLATFORM_FILE_OK,
- ofu()->CopyOrMoveFile(context.get(), src_url, dest_url, is_copy));
- EXPECT_EQ(allowed_bytes_growth, context->allowed_bytes_growth());
-
- // Move, no rename, with overwrite.
- context.reset(NewContext(NULL));
- ASSERT_EQ(base::PLATFORM_FILE_OK, ofu()->EnsureFileExists(
- context.get(), src_url, &created));
- context.reset(NewContext(NULL));
- context->set_allowed_bytes_growth(allowed_bytes_growth);
- EXPECT_EQ(base::PLATFORM_FILE_OK,
- ofu()->CopyOrMoveFile(context.get(), src_url, dest_url, is_copy));
- EXPECT_EQ(
- allowed_bytes_growth +
- ObfuscatedFileUtil::ComputeFilePathCost(src_url.path()),
- context->allowed_bytes_growth());
-}
-
-TEST_F(ObfuscatedFileUtilTest, TestCopyInForeignFile) {
- TestCopyInForeignFileHelper(false /* overwrite */);
- TestCopyInForeignFileHelper(true /* overwrite */);
-}
-
-TEST_F(ObfuscatedFileUtilTest, TestEnumerator) {
- scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
- FileSystemURL src_url = CreateURLFromUTF8("source dir");
- bool exclusive = true;
- bool recursive = false;
- ASSERT_EQ(base::PLATFORM_FILE_OK, ofu()->CreateDirectory(
- context.get(), src_url, exclusive, recursive));
-
- std::set<base::FilePath::StringType> files;
- std::set<base::FilePath::StringType> directories;
- FillTestDirectory(src_url, &files, &directories);
-
- FileSystemURL dest_url = CreateURLFromUTF8("destination dir");
-
- EXPECT_FALSE(DirectoryExists(dest_url));
- ASSERT_EQ(base::PLATFORM_FILE_OK,
- AsyncFileTestHelper::Copy(
- file_system_context(), src_url, dest_url));
-
- ValidateTestDirectory(dest_url, files, directories);
- EXPECT_TRUE(DirectoryExists(src_url));
- EXPECT_TRUE(DirectoryExists(dest_url));
- recursive = true;
- ASSERT_EQ(base::PLATFORM_FILE_OK,
- AsyncFileTestHelper::Remove(
- file_system_context(), dest_url, recursive));
- EXPECT_FALSE(DirectoryExists(dest_url));
-}
-
-TEST_F(ObfuscatedFileUtilTest, TestOriginEnumerator) {
- scoped_ptr<ObfuscatedFileUtil::AbstractOriginEnumerator>
- enumerator(ofu()->CreateOriginEnumerator());
- // The test helper starts out with a single filesystem.
- EXPECT_TRUE(enumerator.get());
- EXPECT_EQ(origin(), enumerator->Next());
- ASSERT_TRUE(type() == kFileSystemTypeTemporary);
- EXPECT_TRUE(enumerator->HasFileSystemType(kFileSystemTypeTemporary));
- EXPECT_FALSE(enumerator->HasFileSystemType(kFileSystemTypePersistent));
- EXPECT_EQ(GURL(), enumerator->Next());
- EXPECT_FALSE(enumerator->HasFileSystemType(kFileSystemTypeTemporary));
- EXPECT_FALSE(enumerator->HasFileSystemType(kFileSystemTypePersistent));
-
- std::set<GURL> origins_expected;
- origins_expected.insert(origin());
-
- for (size_t i = 0; i < arraysize(kOriginEnumerationTestRecords); ++i) {
- SCOPED_TRACE(testing::Message() <<
- "Validating kOriginEnumerationTestRecords " << i);
- const OriginEnumerationTestRecord& record =
- kOriginEnumerationTestRecords[i];
- GURL origin_url(record.origin_url);
- origins_expected.insert(origin_url);
- if (record.has_temporary) {
- scoped_ptr<SandboxFileSystemTestHelper> file_system(
- NewFileSystem(origin_url, kFileSystemTypeTemporary));
- scoped_ptr<FileSystemOperationContext> context(
- NewContext(file_system.get()));
- bool created = false;
- ASSERT_EQ(base::PLATFORM_FILE_OK,
- ofu()->EnsureFileExists(
- context.get(),
- file_system->CreateURLFromUTF8("file"),
- &created));
- EXPECT_TRUE(created);
- }
- if (record.has_persistent) {
- scoped_ptr<SandboxFileSystemTestHelper> file_system(
- NewFileSystem(origin_url, kFileSystemTypePersistent));
- scoped_ptr<FileSystemOperationContext> context(
- NewContext(file_system.get()));
- bool created = false;
- ASSERT_EQ(base::PLATFORM_FILE_OK,
- ofu()->EnsureFileExists(
- context.get(),
- file_system->CreateURLFromUTF8("file"),
- &created));
- EXPECT_TRUE(created);
- }
- }
- enumerator.reset(ofu()->CreateOriginEnumerator());
- EXPECT_TRUE(enumerator.get());
- std::set<GURL> origins_found;
- GURL origin_url;
- while (!(origin_url = enumerator->Next()).is_empty()) {
- origins_found.insert(origin_url);
- SCOPED_TRACE(testing::Message() << "Handling " << origin_url.spec());
- bool found = false;
- for (size_t i = 0; !found && i < arraysize(kOriginEnumerationTestRecords);
- ++i) {
- const OriginEnumerationTestRecord& record =
- kOriginEnumerationTestRecords[i];
- if (GURL(record.origin_url) != origin_url)
- continue;
- found = true;
- EXPECT_EQ(record.has_temporary,
- enumerator->HasFileSystemType(kFileSystemTypeTemporary));
- EXPECT_EQ(record.has_persistent,
- enumerator->HasFileSystemType(kFileSystemTypePersistent));
- }
- // Deal with the default filesystem created by the test helper.
- if (!found && origin_url == origin()) {
- ASSERT_TRUE(type() == kFileSystemTypeTemporary);
- EXPECT_EQ(true,
- enumerator->HasFileSystemType(kFileSystemTypeTemporary));
- EXPECT_FALSE(enumerator->HasFileSystemType(kFileSystemTypePersistent));
- found = true;
- }
- EXPECT_TRUE(found);
- }
-
- std::set<GURL> diff;
- std::set_symmetric_difference(origins_expected.begin(),
- origins_expected.end(), origins_found.begin(), origins_found.end(),
- inserter(diff, diff.begin()));
- EXPECT_TRUE(diff.empty());
-}
-
-TEST_F(ObfuscatedFileUtilTest, TestRevokeUsageCache) {
- scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
-
- int64 expected_quota = 0;
-
- for (size_t i = 0; i < test::kRegularTestCaseSize; ++i) {
- SCOPED_TRACE(testing::Message() << "Creating kRegularTestCase " << i);
- const test::TestCaseRecord& test_case = test::kRegularTestCases[i];
- base::FilePath file_path(test_case.path);
- expected_quota += ObfuscatedFileUtil::ComputeFilePathCost(file_path);
- if (test_case.is_directory) {
- bool exclusive = true;
- bool recursive = false;
- ASSERT_EQ(base::PLATFORM_FILE_OK,
- ofu()->CreateDirectory(context.get(), CreateURL(file_path),
- exclusive, recursive));
- } else {
- bool created = false;
- ASSERT_EQ(base::PLATFORM_FILE_OK,
- ofu()->EnsureFileExists(context.get(), CreateURL(file_path),
- &created));
- ASSERT_TRUE(created);
- ASSERT_EQ(base::PLATFORM_FILE_OK,
- ofu()->Truncate(context.get(),
- CreateURL(file_path),
- test_case.data_file_size));
- expected_quota += test_case.data_file_size;
- }
- }
-
- // Usually raw size in usage cache and the usage returned by QuotaUtil
- // should be same.
- EXPECT_EQ(expected_quota, SizeInUsageFile());
- EXPECT_EQ(expected_quota, SizeByQuotaUtil());
-
- RevokeUsageCache();
- EXPECT_EQ(-1, SizeInUsageFile());
- EXPECT_EQ(expected_quota, SizeByQuotaUtil());
-
- // This should reconstruct the cache.
- GetUsageFromQuotaManager();
- EXPECT_EQ(expected_quota, SizeInUsageFile());
- EXPECT_EQ(expected_quota, SizeByQuotaUtil());
- EXPECT_EQ(expected_quota, usage());
-}
-
-TEST_F(ObfuscatedFileUtilTest, TestInconsistency) {
- const FileSystemURL kPath1 = CreateURLFromUTF8("hoge");
- const FileSystemURL kPath2 = CreateURLFromUTF8("fuga");
-
- scoped_ptr<FileSystemOperationContext> context;
- base::PlatformFile file;
- base::PlatformFileInfo file_info;
- base::FilePath data_path;
- bool created = false;
-
- // Create a non-empty file.
- context.reset(NewContext(NULL));
- EXPECT_EQ(base::PLATFORM_FILE_OK,
- ofu()->EnsureFileExists(context.get(), kPath1, &created));
- EXPECT_TRUE(created);
- context.reset(NewContext(NULL));
- EXPECT_EQ(base::PLATFORM_FILE_OK,
- ofu()->Truncate(context.get(), kPath1, 10));
- context.reset(NewContext(NULL));
- EXPECT_EQ(base::PLATFORM_FILE_OK,
- ofu()->GetFileInfo(
- context.get(), kPath1, &file_info, &data_path));
- EXPECT_EQ(10, file_info.size);
-
- // Destroy database to make inconsistency between database and filesystem.
- ofu()->DestroyDirectoryDatabase(origin(), type());
-
- // Try to get file info of broken file.
- EXPECT_FALSE(PathExists(kPath1));
- context.reset(NewContext(NULL));
- EXPECT_EQ(base::PLATFORM_FILE_OK,
- ofu()->EnsureFileExists(context.get(), kPath1, &created));
- EXPECT_TRUE(created);
- context.reset(NewContext(NULL));
- EXPECT_EQ(base::PLATFORM_FILE_OK,
- ofu()->GetFileInfo(
- context.get(), kPath1, &file_info, &data_path));
- EXPECT_EQ(0, file_info.size);
-
- // Make another broken file to |kPath2|.
- context.reset(NewContext(NULL));
- EXPECT_EQ(base::PLATFORM_FILE_OK,
- ofu()->EnsureFileExists(context.get(), kPath2, &created));
- EXPECT_TRUE(created);
-
- // Destroy again.
- ofu()->DestroyDirectoryDatabase(origin(), type());
-
- // Repair broken |kPath1|.
- context.reset(NewContext(NULL));
- EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND,
- ofu()->Touch(context.get(), kPath1, base::Time::Now(),
- base::Time::Now()));
- EXPECT_EQ(base::PLATFORM_FILE_OK,
- ofu()->EnsureFileExists(context.get(), kPath1, &created));
- EXPECT_TRUE(created);
-
- // Copy from sound |kPath1| to broken |kPath2|.
- context.reset(NewContext(NULL));
- EXPECT_EQ(base::PLATFORM_FILE_OK,
- ofu()->CopyOrMoveFile(context.get(), kPath1, kPath2,
- true /* copy */));
-
- ofu()->DestroyDirectoryDatabase(origin(), type());
- context.reset(NewContext(NULL));
- EXPECT_EQ(base::PLATFORM_FILE_OK,
- ofu()->CreateOrOpen(
- context.get(), kPath1,
- base::PLATFORM_FILE_READ | base::PLATFORM_FILE_CREATE,
- &file, &created));
- EXPECT_TRUE(created);
- EXPECT_TRUE(base::GetPlatformFileInfo(file, &file_info));
- EXPECT_EQ(0, file_info.size);
- EXPECT_TRUE(base::ClosePlatformFile(file));
-}
-
-TEST_F(ObfuscatedFileUtilTest, TestIncompleteDirectoryReading) {
- const FileSystemURL kPath[] = {
- CreateURLFromUTF8("foo"),
- CreateURLFromUTF8("bar"),
- CreateURLFromUTF8("baz")
- };
- const FileSystemURL empty_path = CreateURL(base::FilePath());
- scoped_ptr<FileSystemOperationContext> context;
-
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kPath); ++i) {
- bool created = false;
- context.reset(NewContext(NULL));
- EXPECT_EQ(base::PLATFORM_FILE_OK,
- ofu()->EnsureFileExists(context.get(), kPath[i], &created));
- EXPECT_TRUE(created);
- }
-
- std::vector<DirectoryEntry> entries;
- EXPECT_EQ(base::PLATFORM_FILE_OK,
- AsyncFileTestHelper::ReadDirectory(
- file_system_context(), empty_path, &entries));
- EXPECT_EQ(3u, entries.size());
-
- base::FilePath local_path;
- EXPECT_EQ(base::PLATFORM_FILE_OK,
- ofu()->GetLocalFilePath(context.get(), kPath[0], &local_path));
- EXPECT_TRUE(base::DeleteFile(local_path, false));
-
- entries.clear();
- EXPECT_EQ(base::PLATFORM_FILE_OK,
- AsyncFileTestHelper::ReadDirectory(
- file_system_context(), empty_path, &entries));
- EXPECT_EQ(ARRAYSIZE_UNSAFE(kPath) - 1, entries.size());
-}
-
-TEST_F(ObfuscatedFileUtilTest, TestDirectoryTimestampForCreation) {
- scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
- const FileSystemURL dir_url = CreateURLFromUTF8("foo_dir");
-
- // Create working directory.
- EXPECT_EQ(base::PLATFORM_FILE_OK,
- ofu()->CreateDirectory(context.get(), dir_url, false, false));
-
- // EnsureFileExists, create case.
- FileSystemURL url(FileSystemURLAppendUTF8(
- dir_url, "EnsureFileExists_file"));
- bool created = false;
- ClearTimestamp(dir_url);
- context.reset(NewContext(NULL));
- EXPECT_EQ(base::PLATFORM_FILE_OK,
- ofu()->EnsureFileExists(context.get(), url, &created));
- EXPECT_TRUE(created);
- EXPECT_NE(base::Time(), GetModifiedTime(dir_url));
-
- // non create case.
- created = true;
- ClearTimestamp(dir_url);
- context.reset(NewContext(NULL));
- EXPECT_EQ(base::PLATFORM_FILE_OK,
- ofu()->EnsureFileExists(context.get(), url, &created));
- EXPECT_FALSE(created);
- EXPECT_EQ(base::Time(), GetModifiedTime(dir_url));
-
- // fail case.
- url = FileSystemURLAppendUTF8(dir_url, "EnsureFileExists_dir");
- context.reset(NewContext(NULL));
- EXPECT_EQ(base::PLATFORM_FILE_OK,
- ofu()->CreateDirectory(context.get(), url, false, false));
-
- ClearTimestamp(dir_url);
- context.reset(NewContext(NULL));
- EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_A_FILE,
- ofu()->EnsureFileExists(context.get(), url, &created));
- EXPECT_EQ(base::Time(), GetModifiedTime(dir_url));
-
- // CreateOrOpen, create case.
- url = FileSystemURLAppendUTF8(dir_url, "CreateOrOpen_file");
- base::PlatformFile file_handle = base::kInvalidPlatformFileValue;
- created = false;
- ClearTimestamp(dir_url);
- context.reset(NewContext(NULL));
- EXPECT_EQ(base::PLATFORM_FILE_OK,
- ofu()->CreateOrOpen(
- context.get(), url,
- base::PLATFORM_FILE_CREATE | base::PLATFORM_FILE_WRITE,
- &file_handle, &created));
- EXPECT_NE(base::kInvalidPlatformFileValue, file_handle);
- EXPECT_TRUE(created);
- EXPECT_TRUE(base::ClosePlatformFile(file_handle));
- EXPECT_NE(base::Time(), GetModifiedTime(dir_url));
-
- // open case.
- file_handle = base::kInvalidPlatformFileValue;
- created = true;
- ClearTimestamp(dir_url);
- context.reset(NewContext(NULL));
- EXPECT_EQ(base::PLATFORM_FILE_OK,
- ofu()->CreateOrOpen(
- context.get(), url,
- base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_WRITE,
- &file_handle, &created));
- EXPECT_NE(base::kInvalidPlatformFileValue, file_handle);
- EXPECT_FALSE(created);
- EXPECT_TRUE(base::ClosePlatformFile(file_handle));
- EXPECT_EQ(base::Time(), GetModifiedTime(dir_url));
-
- // fail case
- file_handle = base::kInvalidPlatformFileValue;
- ClearTimestamp(dir_url);
- context.reset(NewContext(NULL));
- EXPECT_EQ(base::PLATFORM_FILE_ERROR_EXISTS,
- ofu()->CreateOrOpen(
- context.get(), url,
- base::PLATFORM_FILE_CREATE | base::PLATFORM_FILE_WRITE,
- &file_handle, &created));
- EXPECT_EQ(base::kInvalidPlatformFileValue, file_handle);
- EXPECT_EQ(base::Time(), GetModifiedTime(dir_url));
-
- // CreateDirectory, create case.
- // Creating CreateDirectory_dir and CreateDirectory_dir/subdir.
- url = FileSystemURLAppendUTF8(dir_url, "CreateDirectory_dir");
- FileSystemURL subdir_url(FileSystemURLAppendUTF8(url, "subdir"));
- ClearTimestamp(dir_url);
- context.reset(NewContext(NULL));
- EXPECT_EQ(base::PLATFORM_FILE_OK,
- ofu()->CreateDirectory(context.get(), subdir_url,
- true /* exclusive */, true /* recursive */));
- EXPECT_NE(base::Time(), GetModifiedTime(dir_url));
-
- // create subdir case.
- // Creating CreateDirectory_dir/subdir2.
- subdir_url = FileSystemURLAppendUTF8(url, "subdir2");
- ClearTimestamp(dir_url);
- ClearTimestamp(url);
- context.reset(NewContext(NULL));
- EXPECT_EQ(base::PLATFORM_FILE_OK,
- ofu()->CreateDirectory(context.get(), subdir_url,
- true /* exclusive */, true /* recursive */));
- EXPECT_EQ(base::Time(), GetModifiedTime(dir_url));
- EXPECT_NE(base::Time(), GetModifiedTime(url));
-
- // fail case.
- url = FileSystemURLAppendUTF8(dir_url, "CreateDirectory_dir");
- ClearTimestamp(dir_url);
- context.reset(NewContext(NULL));
- EXPECT_EQ(base::PLATFORM_FILE_ERROR_EXISTS,
- ofu()->CreateDirectory(context.get(), url,
- true /* exclusive */, true /* recursive */));
- EXPECT_EQ(base::Time(), GetModifiedTime(dir_url));
-
- // CopyInForeignFile, create case.
- url = FileSystemURLAppendUTF8(dir_url, "CopyInForeignFile_file");
- FileSystemURL src_path = FileSystemURLAppendUTF8(
- dir_url, "CopyInForeignFile_src_file");
- context.reset(NewContext(NULL));
- EXPECT_EQ(base::PLATFORM_FILE_OK,
- ofu()->EnsureFileExists(context.get(), src_path, &created));
- EXPECT_TRUE(created);
- base::FilePath src_local_path;
- context.reset(NewContext(NULL));
- EXPECT_EQ(base::PLATFORM_FILE_OK,
- ofu()->GetLocalFilePath(context.get(), src_path, &src_local_path));
-
- ClearTimestamp(dir_url);
- context.reset(NewContext(NULL));
- EXPECT_EQ(base::PLATFORM_FILE_OK,
- ofu()->CopyInForeignFile(context.get(),
- src_local_path,
- url));
- EXPECT_NE(base::Time(), GetModifiedTime(dir_url));
-}
-
-TEST_F(ObfuscatedFileUtilTest, TestDirectoryTimestampForDeletion) {
- scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
- const FileSystemURL dir_url = CreateURLFromUTF8("foo_dir");
-
- // Create working directory.
- EXPECT_EQ(base::PLATFORM_FILE_OK,
- ofu()->CreateDirectory(context.get(), dir_url, false, false));
-
- // DeleteFile, delete case.
- FileSystemURL url = FileSystemURLAppendUTF8(
- dir_url, "DeleteFile_file");
- bool created = false;
- context.reset(NewContext(NULL));
- EXPECT_EQ(base::PLATFORM_FILE_OK,
- ofu()->EnsureFileExists(context.get(), url, &created));
- EXPECT_TRUE(created);
-
- ClearTimestamp(dir_url);
- context.reset(NewContext(NULL));
- EXPECT_EQ(base::PLATFORM_FILE_OK,
- ofu()->DeleteFile(context.get(), url));
- EXPECT_NE(base::Time(), GetModifiedTime(dir_url));
-
- // fail case.
- ClearTimestamp(dir_url);
- context.reset(NewContext(NULL));
- EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND,
- ofu()->DeleteFile(context.get(), url));
- EXPECT_EQ(base::Time(), GetModifiedTime(dir_url));
-
- // DeleteDirectory, fail case.
- url = FileSystemURLAppendUTF8(dir_url, "DeleteDirectory_dir");
- FileSystemURL file_path(FileSystemURLAppendUTF8(url, "pakeratta"));
- context.reset(NewContext(NULL));
- EXPECT_EQ(base::PLATFORM_FILE_OK,
- ofu()->CreateDirectory(context.get(), url, true, true));
- created = false;
- context.reset(NewContext(NULL));
- EXPECT_EQ(base::PLATFORM_FILE_OK,
- ofu()->EnsureFileExists(context.get(), file_path, &created));
- EXPECT_TRUE(created);
-
- ClearTimestamp(dir_url);
- context.reset(NewContext(NULL));
- EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_EMPTY,
- ofu()->DeleteDirectory(context.get(), url));
- EXPECT_EQ(base::Time(), GetModifiedTime(dir_url));
-
- // delete case.
- context.reset(NewContext(NULL));
- EXPECT_EQ(base::PLATFORM_FILE_OK,
- ofu()->DeleteFile(context.get(), file_path));
-
- ClearTimestamp(dir_url);
- context.reset(NewContext(NULL));
- EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->DeleteDirectory(context.get(), url));
- EXPECT_NE(base::Time(), GetModifiedTime(dir_url));
-}
-
-TEST_F(ObfuscatedFileUtilTest, TestDirectoryTimestampForCopyAndMove) {
- TestDirectoryTimestampHelper(
- CreateURLFromUTF8("copy overwrite"), true, true);
- TestDirectoryTimestampHelper(
- CreateURLFromUTF8("copy non-overwrite"), true, false);
- TestDirectoryTimestampHelper(
- CreateURLFromUTF8("move overwrite"), false, true);
- TestDirectoryTimestampHelper(
- CreateURLFromUTF8("move non-overwrite"), false, false);
-}
-
-TEST_F(ObfuscatedFileUtilTest, TestFileEnumeratorTimestamp) {
- FileSystemURL dir = CreateURLFromUTF8("foo");
- FileSystemURL url1 = FileSystemURLAppendUTF8(dir, "bar");
- FileSystemURL url2 = FileSystemURLAppendUTF8(dir, "baz");
-
- scoped_ptr<FileSystemOperationContext> context(NewContext(NULL));
- EXPECT_EQ(base::PLATFORM_FILE_OK,
- ofu()->CreateDirectory(context.get(), dir, false, false));
-
- bool created = false;
- context.reset(NewContext(NULL));
- EXPECT_EQ(base::PLATFORM_FILE_OK,
- ofu()->EnsureFileExists(context.get(), url1, &created));
- EXPECT_TRUE(created);
-
- context.reset(NewContext(NULL));
- EXPECT_EQ(base::PLATFORM_FILE_OK,
- ofu()->CreateDirectory(context.get(), url2, false, false));
-
- base::FilePath file_path;
- context.reset(NewContext(NULL));
- EXPECT_EQ(base::PLATFORM_FILE_OK,
- ofu()->GetLocalFilePath(context.get(), url1, &file_path));
- EXPECT_FALSE(file_path.empty());
-
- context.reset(NewContext(NULL));
- EXPECT_EQ(base::PLATFORM_FILE_OK,
- ofu()->Touch(context.get(), url1,
- base::Time::Now() + base::TimeDelta::FromHours(1),
- base::Time()));
-
- context.reset(NewContext(NULL));
- scoped_ptr<FileSystemFileUtil::AbstractFileEnumerator> file_enum(
- ofu()->CreateFileEnumerator(context.get(), dir, false));
-
- int count = 0;
- base::FilePath file_path_each;
- while (!(file_path_each = file_enum->Next()).empty()) {
- context.reset(NewContext(NULL));
- base::PlatformFileInfo file_info;
- base::FilePath file_path;
- EXPECT_EQ(base::PLATFORM_FILE_OK,
- ofu()->GetFileInfo(context.get(),
- FileSystemURL::CreateForTest(
- dir.origin(),
- dir.mount_type(),
- file_path_each),
- &file_info, &file_path));
- EXPECT_EQ(file_info.is_directory, file_enum->IsDirectory());
- EXPECT_EQ(file_info.last_modified, file_enum->LastModifiedTime());
- EXPECT_EQ(file_info.size, file_enum->Size());
- ++count;
- }
- EXPECT_EQ(2, count);
-}
-
-// crbug.com/176470
-#if defined(OS_WIN) || defined(OS_ANDROID)
-#define MAYBE_TestQuotaOnCopyFile DISABLED_TestQuotaOnCopyFile
-#else
-#define MAYBE_TestQuotaOnCopyFile TestQuotaOnCopyFile
-#endif
-TEST_F(ObfuscatedFileUtilTest, MAYBE_TestQuotaOnCopyFile) {
- FileSystemURL from_file(CreateURLFromUTF8("fromfile"));
- FileSystemURL obstacle_file(CreateURLFromUTF8("obstaclefile"));
- FileSystemURL to_file1(CreateURLFromUTF8("tofile1"));
- FileSystemURL to_file2(CreateURLFromUTF8("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) {
- FileSystemURL from_file(CreateURLFromUTF8("fromfile"));
- FileSystemURL obstacle_file(CreateURLFromUTF8("obstaclefile"));
- FileSystemURL to_file(CreateURLFromUTF8("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) {
- FileSystemURL dir(CreateURLFromUTF8("dir"));
- FileSystemURL file(CreateURLFromUTF8("file"));
- FileSystemURL dfile1(CreateURLFromUTF8("dir/dfile1"));
- FileSystemURL dfile2(CreateURLFromUTF8("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,
- AsyncFileTestHelper::Remove(
- file_system_context(), dir, true /* recursive */));
- ASSERT_EQ(0, ComputeTotalFileSize());
-}
-
-TEST_F(ObfuscatedFileUtilTest, TestQuotaOnOpen) {
- FileSystemURL file(CreateURLFromUTF8("file"));
- base::PlatformFile file_handle;
- bool created;
-
- // Creating a file.
- ASSERT_EQ(base::PLATFORM_FILE_OK,
- ofu()->EnsureFileExists(
- AllowUsageIncrease(PathCost(file))->context(),
- file, &created));
- ASSERT_TRUE(created);
- ASSERT_EQ(0, ComputeTotalFileSize());
-
- // Opening it, which shouldn't change the usage.
- ASSERT_EQ(base::PLATFORM_FILE_OK,
- ofu()->CreateOrOpen(
- AllowUsageIncrease(0)->context(), file,
- base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_WRITE,
- &file_handle, &created));
- ASSERT_EQ(0, ComputeTotalFileSize());
- EXPECT_TRUE(base::ClosePlatformFile(file_handle));
-
- const int length = 33;
- ASSERT_EQ(base::PLATFORM_FILE_OK,
- ofu()->Truncate(
- AllowUsageIncrease(length)->context(), file, length));
- ASSERT_EQ(length, ComputeTotalFileSize());
-
- // Opening it with CREATE_ALWAYS flag, which should truncate the file size.
- ASSERT_EQ(base::PLATFORM_FILE_OK,
- ofu()->CreateOrOpen(
- AllowUsageIncrease(-length)->context(), file,
- base::PLATFORM_FILE_CREATE_ALWAYS | base::PLATFORM_FILE_WRITE,
- &file_handle, &created));
- ASSERT_EQ(0, ComputeTotalFileSize());
- EXPECT_TRUE(base::ClosePlatformFile(file_handle));
-
- // Extending the file again.
- ASSERT_EQ(base::PLATFORM_FILE_OK,
- ofu()->Truncate(
- AllowUsageIncrease(length)->context(), file, length));
- ASSERT_EQ(length, ComputeTotalFileSize());
-
- // Opening it with TRUNCATED flag, which should truncate the file size.
- ASSERT_EQ(base::PLATFORM_FILE_OK,
- ofu()->CreateOrOpen(
- AllowUsageIncrease(-length)->context(), file,
- base::PLATFORM_FILE_OPEN_TRUNCATED | base::PLATFORM_FILE_WRITE,
- &file_handle, &created));
- ASSERT_EQ(0, ComputeTotalFileSize());
- EXPECT_TRUE(base::ClosePlatformFile(file_handle));
-}
-
-TEST_F(ObfuscatedFileUtilTest, MaybeDropDatabasesAliveCase) {
- ObfuscatedFileUtil file_util(NULL,
- data_dir_path(),
- base::MessageLoopProxy::current().get());
- file_util.InitOriginDatabase(true /*create*/);
- ASSERT_TRUE(file_util.origin_database_ != NULL);
-
- // Callback to Drop DB is called while ObfuscatedFileUtilTest is still alive.
- file_util.db_flush_delay_seconds_ = 0;
- file_util.MarkUsed();
- base::RunLoop().RunUntilIdle();
-
- ASSERT_TRUE(file_util.origin_database_ == NULL);
-}
-
-TEST_F(ObfuscatedFileUtilTest, MaybeDropDatabasesAlreadyDeletedCase) {
- // Run message loop after OFU is already deleted to make sure callback doesn't
- // cause a crash for use after free.
- {
- ObfuscatedFileUtil file_util(NULL,
- data_dir_path(),
- base::MessageLoopProxy::current().get());
- file_util.InitOriginDatabase(true /*create*/);
- file_util.db_flush_delay_seconds_ = 0;
- file_util.MarkUsed();
- }
-
- // At this point the callback is still in the message queue but OFU is gone.
- base::RunLoop().RunUntilIdle();
-}
-
-TEST_F(ObfuscatedFileUtilTest, DestroyDirectoryDatabase_Isolated) {
- storage_policy_->AddIsolated(origin_);
- ObfuscatedFileUtil file_util(
- storage_policy_.get(), data_dir_path(),
- base::MessageLoopProxy::current().get());
-
- // Create DirectoryDatabase for isolated origin.
- SandboxDirectoryDatabase* db = file_util.GetDirectoryDatabase(
- origin_, kFileSystemTypePersistent, true /* create */);
- ASSERT_TRUE(db != NULL);
-
- // Destory it.
- ASSERT_TRUE(
- file_util.DestroyDirectoryDatabase(origin_, kFileSystemTypePersistent));
- ASSERT_TRUE(file_util.directories_.empty());
-}
-
-TEST_F(ObfuscatedFileUtilTest, GetDirectoryDatabase_Isolated) {
- storage_policy_->AddIsolated(origin_);
- ObfuscatedFileUtil file_util(
- storage_policy_.get(), data_dir_path(),
- base::MessageLoopProxy::current().get());
-
- // Create DirectoryDatabase for isolated origin.
- SandboxDirectoryDatabase* db = file_util.GetDirectoryDatabase(
- origin_, kFileSystemTypePersistent, true /* create */);
- ASSERT_TRUE(db != NULL);
- ASSERT_EQ(1U, file_util.directories_.size());
-
- // Remove isolated.
- storage_policy_->RemoveIsolated(origin_);
-
- // This should still get the same database.
- SandboxDirectoryDatabase* db2 = file_util.GetDirectoryDatabase(
- origin_, kFileSystemTypePersistent, false /* create */);
- ASSERT_EQ(db, db2);
-}
-
-TEST_F(ObfuscatedFileUtilTest, MigrationBackFromIsolated) {
- std::string kFakeDirectoryData("0123456789");
- base::FilePath old_directory_db_path;
-
- // Initialize the directory with one origin using
- // SandboxIsolatedOriginDatabase.
- {
- std::string origin_string =
- webkit_database::GetIdentifierFromOrigin(origin_);
- SandboxIsolatedOriginDatabase database_old(origin_string, data_dir_path());
- base::FilePath path;
- EXPECT_TRUE(database_old.GetPathForOrigin(origin_string, &path));
- EXPECT_FALSE(path.empty());
-
- // Populate the origin directory with some fake data.
- old_directory_db_path = data_dir_path().Append(path);
- ASSERT_TRUE(file_util::CreateDirectory(old_directory_db_path));
- EXPECT_EQ(static_cast<int>(kFakeDirectoryData.size()),
- file_util::WriteFile(old_directory_db_path.AppendASCII("dummy"),
- kFakeDirectoryData.data(),
- kFakeDirectoryData.size()));
- }
-
- storage_policy_->AddIsolated(origin_);
- ObfuscatedFileUtil file_util(
- storage_policy_.get(), data_dir_path(),
- base::MessageLoopProxy::current().get());
- base::PlatformFileError error = base::PLATFORM_FILE_ERROR_FAILED;
- base::FilePath origin_directory = file_util.GetDirectoryForOrigin(
- origin_, true /* create */, &error);
- EXPECT_EQ(base::PLATFORM_FILE_OK, error);
-
- // The database is migrated from the old one.
- EXPECT_TRUE(base::DirectoryExists(origin_directory));
- EXPECT_FALSE(base::DirectoryExists(old_directory_db_path));
-
- // Check we see the same contents in the new origin directory.
- std::string origin_db_data;
- EXPECT_TRUE(base::PathExists(origin_directory.AppendASCII("dummy")));
- EXPECT_TRUE(base::ReadFileToString(
- origin_directory.AppendASCII("dummy"), &origin_db_data));
- EXPECT_EQ(kFakeDirectoryData, origin_db_data);
-}
-
-TEST_F(ObfuscatedFileUtilTest, OpenPathInNonDirectory) {
- FileSystemURL file(CreateURLFromUTF8("file"));
- FileSystemURL path_in_file(CreateURLFromUTF8("file/file"));
- bool created;
-
- ASSERT_EQ(base::PLATFORM_FILE_OK,
- ofu()->EnsureFileExists(UnlimitedContext().get(), file, &created));
- ASSERT_TRUE(created);
-
- created = false;
- base::PlatformFile file_handle = base::kInvalidPlatformFileValue;
- int file_flags = base::PLATFORM_FILE_CREATE | base::PLATFORM_FILE_WRITE;
- ASSERT_EQ(base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY,
- ofu()->CreateOrOpen(UnlimitedContext().get(),
- path_in_file,
- file_flags,
- &file_handle,
- &created));
- ASSERT_FALSE(created);
- ASSERT_EQ(base::kInvalidPlatformFileValue, file_handle);
-
- ASSERT_EQ(base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY,
- ofu()->CreateDirectory(UnlimitedContext().get(),
- path_in_file,
- false /* exclusive */,
- false /* recursive */));
-}
-
-} // namespace fileapi
diff --git a/chromium/webkit/browser/fileapi/plugin_private_file_system_backend.cc b/chromium/webkit/browser/fileapi/plugin_private_file_system_backend.cc
new file mode 100644
index 00000000000..0426bd24911
--- /dev/null
+++ b/chromium/webkit/browser/fileapi/plugin_private_file_system_backend.cc
@@ -0,0 +1,297 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "webkit/browser/fileapi/plugin_private_file_system_backend.h"
+
+#include <map>
+
+#include "base/stl_util.h"
+#include "base/synchronization/lock.h"
+#include "base/task_runner_util.h"
+#include "net/base/net_util.h"
+#include "webkit/browser/blob/file_stream_reader.h"
+#include "webkit/browser/fileapi/async_file_util_adapter.h"
+#include "webkit/browser/fileapi/file_stream_writer.h"
+#include "webkit/browser/fileapi/file_system_context.h"
+#include "webkit/browser/fileapi/file_system_operation.h"
+#include "webkit/browser/fileapi/file_system_operation_context.h"
+#include "webkit/browser/fileapi/file_system_options.h"
+#include "webkit/browser/fileapi/isolated_context.h"
+#include "webkit/browser/fileapi/obfuscated_file_util.h"
+#include "webkit/browser/fileapi/quota/quota_reservation.h"
+#include "webkit/common/fileapi/file_system_util.h"
+
+namespace fileapi {
+
+class PluginPrivateFileSystemBackend::FileSystemIDToPluginMap {
+ public:
+ explicit FileSystemIDToPluginMap(base::SequencedTaskRunner* task_runner)
+ : task_runner_(task_runner) {}
+ ~FileSystemIDToPluginMap() {}
+
+ std::string GetPluginIDForURL(const FileSystemURL& url) {
+ DCHECK(task_runner_->RunsTasksOnCurrentThread());
+ Map::iterator found = map_.find(url.filesystem_id());
+ if (url.type() != kFileSystemTypePluginPrivate || found == map_.end()) {
+ NOTREACHED() << "Unsupported url is given: " << url.DebugString();
+ return std::string();
+ }
+ return found->second;
+ }
+
+ void RegisterFileSystem(const std::string& filesystem_id,
+ const std::string& plugin_id) {
+ DCHECK(task_runner_->RunsTasksOnCurrentThread());
+ DCHECK(!filesystem_id.empty());
+ DCHECK(!ContainsKey(map_, filesystem_id)) << filesystem_id;
+ map_[filesystem_id] = plugin_id;
+ }
+
+ void RemoveFileSystem(const std::string& filesystem_id) {
+ DCHECK(task_runner_->RunsTasksOnCurrentThread());
+ map_.erase(filesystem_id);
+ }
+
+ private:
+ typedef std::map<std::string, std::string> Map;
+ scoped_refptr<base::SequencedTaskRunner> task_runner_;
+ Map map_;
+};
+
+namespace {
+
+const base::FilePath::CharType* kFileSystemDirectory =
+ SandboxFileSystemBackendDelegate::kFileSystemDirectory;
+const base::FilePath::CharType* kPluginPrivateDirectory =
+ FILE_PATH_LITERAL("Plugins");
+
+base::PlatformFileError OpenFileSystemOnFileThread(
+ ObfuscatedFileUtil* file_util,
+ PluginPrivateFileSystemBackend::FileSystemIDToPluginMap* plugin_map,
+ const GURL& origin_url,
+ const std::string& filesystem_id,
+ const std::string& plugin_id,
+ OpenFileSystemMode mode) {
+ base::PlatformFileError error = base::PLATFORM_FILE_ERROR_FAILED;
+ const bool create = (mode == OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT);
+ file_util->GetDirectoryForOriginAndType(
+ origin_url, plugin_id, create, &error);
+ if (error == base::PLATFORM_FILE_OK)
+ plugin_map->RegisterFileSystem(filesystem_id, plugin_id);
+ return error;
+}
+
+} // namespace
+
+PluginPrivateFileSystemBackend::PluginPrivateFileSystemBackend(
+ base::SequencedTaskRunner* file_task_runner,
+ const base::FilePath& profile_path,
+ quota::SpecialStoragePolicy* special_storage_policy,
+ const FileSystemOptions& file_system_options)
+ : file_task_runner_(file_task_runner),
+ file_system_options_(file_system_options),
+ base_path_(profile_path.Append(
+ kFileSystemDirectory).Append(kPluginPrivateDirectory)),
+ plugin_map_(new FileSystemIDToPluginMap(file_task_runner)),
+ weak_factory_(this) {
+ file_util_.reset(
+ new AsyncFileUtilAdapter(new ObfuscatedFileUtil(
+ special_storage_policy,
+ base_path_,
+ file_task_runner,
+ base::Bind(&FileSystemIDToPluginMap::GetPluginIDForURL,
+ base::Owned(plugin_map_)),
+ std::set<std::string>(),
+ NULL)));
+}
+
+PluginPrivateFileSystemBackend::~PluginPrivateFileSystemBackend() {
+ if (!file_task_runner_->RunsTasksOnCurrentThread()) {
+ AsyncFileUtil* file_util = file_util_.release();
+ if (!file_task_runner_->DeleteSoon(FROM_HERE, file_util))
+ delete file_util;
+ }
+}
+
+void PluginPrivateFileSystemBackend::OpenPrivateFileSystem(
+ const GURL& origin_url,
+ FileSystemType type,
+ const std::string& filesystem_id,
+ const std::string& plugin_id,
+ OpenFileSystemMode mode,
+ const StatusCallback& callback) {
+ if (!CanHandleType(type) || file_system_options_.is_incognito()) {
+ base::MessageLoopProxy::current()->PostTask(
+ FROM_HERE, base::Bind(callback, base::PLATFORM_FILE_ERROR_SECURITY));
+ return;
+ }
+
+ PostTaskAndReplyWithResult(
+ file_task_runner_.get(),
+ FROM_HERE,
+ base::Bind(&OpenFileSystemOnFileThread,
+ obfuscated_file_util(), plugin_map_,
+ origin_url, filesystem_id, plugin_id, mode),
+ callback);
+}
+
+bool PluginPrivateFileSystemBackend::CanHandleType(FileSystemType type) const {
+ return type == kFileSystemTypePluginPrivate;
+}
+
+void PluginPrivateFileSystemBackend::Initialize(FileSystemContext* context) {
+}
+
+void PluginPrivateFileSystemBackend::OpenFileSystem(
+ const GURL& origin_url,
+ FileSystemType type,
+ OpenFileSystemMode mode,
+ const OpenFileSystemCallback& callback) {
+ // We never allow opening a new plugin-private filesystem via usual
+ // OpenFileSystem.
+ base::MessageLoopProxy::current()->PostTask(
+ FROM_HERE,
+ base::Bind(callback, GURL(), std::string(),
+ base::PLATFORM_FILE_ERROR_SECURITY));
+}
+
+AsyncFileUtil*
+PluginPrivateFileSystemBackend::GetAsyncFileUtil(FileSystemType type) {
+ return file_util_.get();
+}
+
+CopyOrMoveFileValidatorFactory*
+PluginPrivateFileSystemBackend::GetCopyOrMoveFileValidatorFactory(
+ FileSystemType type,
+ base::PlatformFileError* error_code) {
+ DCHECK(error_code);
+ *error_code = base::PLATFORM_FILE_OK;
+ return NULL;
+}
+
+FileSystemOperation* PluginPrivateFileSystemBackend::CreateFileSystemOperation(
+ const FileSystemURL& url,
+ FileSystemContext* context,
+ base::PlatformFileError* error_code) const {
+ scoped_ptr<FileSystemOperationContext> operation_context(
+ new FileSystemOperationContext(context));
+ return FileSystemOperation::Create(url, context, operation_context.Pass());
+}
+
+scoped_ptr<webkit_blob::FileStreamReader>
+PluginPrivateFileSystemBackend::CreateFileStreamReader(
+ const FileSystemURL& url,
+ int64 offset,
+ const base::Time& expected_modification_time,
+ FileSystemContext* context) const {
+ return scoped_ptr<webkit_blob::FileStreamReader>();
+}
+
+scoped_ptr<FileStreamWriter>
+PluginPrivateFileSystemBackend::CreateFileStreamWriter(
+ const FileSystemURL& url,
+ int64 offset,
+ FileSystemContext* context) const {
+ return scoped_ptr<FileStreamWriter>();
+}
+
+FileSystemQuotaUtil* PluginPrivateFileSystemBackend::GetQuotaUtil() {
+ return this;
+}
+
+base::PlatformFileError
+PluginPrivateFileSystemBackend::DeleteOriginDataOnFileThread(
+ FileSystemContext* context,
+ quota::QuotaManagerProxy* proxy,
+ const GURL& origin_url,
+ FileSystemType type) {
+ if (!CanHandleType(type))
+ return base::PLATFORM_FILE_ERROR_SECURITY;
+ bool result = obfuscated_file_util()->DeleteDirectoryForOriginAndType(
+ origin_url, std::string());
+ if (result)
+ return base::PLATFORM_FILE_OK;
+ return base::PLATFORM_FILE_ERROR_FAILED;
+}
+
+void PluginPrivateFileSystemBackend::GetOriginsForTypeOnFileThread(
+ FileSystemType type,
+ std::set<GURL>* origins) {
+ if (!CanHandleType(type))
+ return;
+ scoped_ptr<ObfuscatedFileUtil::AbstractOriginEnumerator> enumerator(
+ obfuscated_file_util()->CreateOriginEnumerator());
+ GURL origin;
+ while (!(origin = enumerator->Next()).is_empty())
+ origins->insert(origin);
+}
+
+void PluginPrivateFileSystemBackend::GetOriginsForHostOnFileThread(
+ FileSystemType type,
+ const std::string& host,
+ std::set<GURL>* origins) {
+ if (!CanHandleType(type))
+ return;
+ scoped_ptr<ObfuscatedFileUtil::AbstractOriginEnumerator> enumerator(
+ obfuscated_file_util()->CreateOriginEnumerator());
+ GURL origin;
+ while (!(origin = enumerator->Next()).is_empty()) {
+ if (host == net::GetHostOrSpecFromURL(origin))
+ origins->insert(origin);
+ }
+}
+
+int64 PluginPrivateFileSystemBackend::GetOriginUsageOnFileThread(
+ FileSystemContext* context,
+ const GURL& origin_url,
+ FileSystemType type) {
+ // We don't track usage on this filesystem.
+ return 0;
+}
+
+scoped_refptr<QuotaReservation>
+PluginPrivateFileSystemBackend::CreateQuotaReservationOnFileTaskRunner(
+ const GURL& origin_url,
+ FileSystemType type) {
+ // We don't track usage on this filesystem.
+ NOTREACHED();
+ return scoped_refptr<QuotaReservation>();
+}
+
+void PluginPrivateFileSystemBackend::AddFileUpdateObserver(
+ FileSystemType type,
+ FileUpdateObserver* observer,
+ base::SequencedTaskRunner* task_runner) {}
+
+void PluginPrivateFileSystemBackend::AddFileChangeObserver(
+ FileSystemType type,
+ FileChangeObserver* observer,
+ base::SequencedTaskRunner* task_runner) {}
+
+void PluginPrivateFileSystemBackend::AddFileAccessObserver(
+ FileSystemType type,
+ FileAccessObserver* observer,
+ base::SequencedTaskRunner* task_runner) {}
+
+const UpdateObserverList* PluginPrivateFileSystemBackend::GetUpdateObservers(
+ FileSystemType type) const {
+ return NULL;
+}
+
+const ChangeObserverList* PluginPrivateFileSystemBackend::GetChangeObservers(
+ FileSystemType type) const {
+ return NULL;
+}
+
+const AccessObserverList* PluginPrivateFileSystemBackend::GetAccessObservers(
+ FileSystemType type) const {
+ return NULL;
+}
+
+ObfuscatedFileUtil* PluginPrivateFileSystemBackend::obfuscated_file_util() {
+ return static_cast<ObfuscatedFileUtil*>(
+ static_cast<AsyncFileUtilAdapter*>(file_util_.get())->sync_file_util());
+}
+
+} // namespace fileapi
diff --git a/chromium/webkit/browser/fileapi/plugin_private_file_system_backend.h b/chromium/webkit/browser/fileapi/plugin_private_file_system_backend.h
new file mode 100644
index 00000000000..d41f4b7eced
--- /dev/null
+++ b/chromium/webkit/browser/fileapi/plugin_private_file_system_backend.h
@@ -0,0 +1,142 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef WEBKIT_BROWSER_FILEAPI_PLUGIN_PRIVATE_FILE_SYSTEM_BACKEND_H_
+#define WEBKIT_BROWSER_FILEAPI_PLUGIN_PRIVATE_FILE_SYSTEM_BACKEND_H_
+
+#include <set>
+#include <string>
+
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "webkit/browser/fileapi/file_system_backend.h"
+#include "webkit/browser/fileapi/file_system_options.h"
+#include "webkit/browser/fileapi/file_system_quota_util.h"
+
+namespace base {
+class SequencedTaskRunner;
+}
+
+namespace quota {
+class SpecialStoragePolicy;
+}
+
+namespace fileapi {
+
+class ObfuscatedFileUtil;
+
+class WEBKIT_STORAGE_BROWSER_EXPORT PluginPrivateFileSystemBackend
+ : public FileSystemBackend,
+ public FileSystemQuotaUtil {
+ public:
+ class FileSystemIDToPluginMap;
+ typedef base::Callback<void(base::PlatformFileError result)> StatusCallback;
+
+ PluginPrivateFileSystemBackend(
+ base::SequencedTaskRunner* file_task_runner,
+ const base::FilePath& profile_path,
+ quota::SpecialStoragePolicy* special_storage_policy,
+ const FileSystemOptions& file_system_options);
+ virtual ~PluginPrivateFileSystemBackend();
+
+ // This must be used to open 'private' filesystem instead of regular
+ // OpenFileSystem.
+ // |plugin_id| must be an identifier string for per-plugin
+ // isolation, e.g. name, MIME type etc.
+ // NOTE: |plugin_id| must be sanitized ASCII string that doesn't
+ // include *any* dangerous character like '/'.
+ void OpenPrivateFileSystem(
+ const GURL& origin_url,
+ FileSystemType type,
+ const std::string& filesystem_id,
+ const std::string& plugin_id,
+ OpenFileSystemMode mode,
+ const StatusCallback& callback);
+
+ // FileSystemBackend overrides.
+ virtual bool CanHandleType(FileSystemType type) const OVERRIDE;
+ virtual void Initialize(FileSystemContext* context) OVERRIDE;
+ virtual void OpenFileSystem(
+ const GURL& origin_url,
+ FileSystemType type,
+ OpenFileSystemMode mode,
+ const OpenFileSystemCallback& callback) OVERRIDE;
+ virtual AsyncFileUtil* GetAsyncFileUtil(FileSystemType type) OVERRIDE;
+ virtual CopyOrMoveFileValidatorFactory* GetCopyOrMoveFileValidatorFactory(
+ FileSystemType type,
+ base::PlatformFileError* error_code) OVERRIDE;
+ virtual FileSystemOperation* CreateFileSystemOperation(
+ const FileSystemURL& url,
+ FileSystemContext* context,
+ base::PlatformFileError* error_code) const OVERRIDE;
+ virtual scoped_ptr<webkit_blob::FileStreamReader> CreateFileStreamReader(
+ const FileSystemURL& url,
+ int64 offset,
+ const base::Time& expected_modification_time,
+ FileSystemContext* context) const OVERRIDE;
+ virtual scoped_ptr<FileStreamWriter> CreateFileStreamWriter(
+ const FileSystemURL& url,
+ int64 offset,
+ FileSystemContext* context) const OVERRIDE;
+ virtual FileSystemQuotaUtil* GetQuotaUtil() OVERRIDE;
+
+ // FileSystemQuotaUtil overrides.
+ virtual base::PlatformFileError DeleteOriginDataOnFileThread(
+ FileSystemContext* context,
+ quota::QuotaManagerProxy* proxy,
+ const GURL& origin_url,
+ FileSystemType type) OVERRIDE;
+ virtual void GetOriginsForTypeOnFileThread(
+ FileSystemType type,
+ std::set<GURL>* origins) OVERRIDE;
+ virtual void GetOriginsForHostOnFileThread(
+ FileSystemType type,
+ const std::string& host,
+ std::set<GURL>* origins) OVERRIDE;
+ virtual int64 GetOriginUsageOnFileThread(
+ FileSystemContext* context,
+ const GURL& origin_url,
+ FileSystemType type) OVERRIDE;
+ virtual scoped_refptr<QuotaReservation>
+ CreateQuotaReservationOnFileTaskRunner(
+ const GURL& origin_url,
+ FileSystemType type) OVERRIDE;
+ virtual void AddFileUpdateObserver(
+ FileSystemType type,
+ FileUpdateObserver* observer,
+ base::SequencedTaskRunner* task_runner) OVERRIDE;
+ virtual void AddFileChangeObserver(
+ FileSystemType type,
+ FileChangeObserver* observer,
+ base::SequencedTaskRunner* task_runner) OVERRIDE;
+ virtual void AddFileAccessObserver(
+ FileSystemType type,
+ FileAccessObserver* observer,
+ base::SequencedTaskRunner* task_runner) OVERRIDE;
+ virtual const UpdateObserverList* GetUpdateObservers(
+ FileSystemType type) const OVERRIDE;
+ virtual const ChangeObserverList* GetChangeObservers(
+ FileSystemType type) const OVERRIDE;
+ virtual const AccessObserverList* GetAccessObservers(
+ FileSystemType type) const OVERRIDE;
+
+ private:
+ friend class PluginPrivateFileSystemBackendTest;
+
+ ObfuscatedFileUtil* obfuscated_file_util();
+ const base::FilePath& base_path() const { return base_path_; }
+
+ scoped_refptr<base::SequencedTaskRunner> file_task_runner_;
+ const FileSystemOptions file_system_options_;
+ const base::FilePath base_path_;
+ scoped_ptr<AsyncFileUtil> file_util_;
+ FileSystemIDToPluginMap* plugin_map_; // Owned by file_util_.
+ base::WeakPtrFactory<PluginPrivateFileSystemBackend> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(PluginPrivateFileSystemBackend);
+};
+
+} // namespace fileapi
+
+#endif // WEBKIT_BROWSER_FILEAPI_PLUGIN_PRIVATE_FILE_SYSTEM_BACKEND_H_
diff --git a/chromium/webkit/browser/fileapi/quota/open_file_handle.cc b/chromium/webkit/browser/fileapi/quota/open_file_handle.cc
new file mode 100644
index 00000000000..f0f69c66587
--- /dev/null
+++ b/chromium/webkit/browser/fileapi/quota/open_file_handle.cc
@@ -0,0 +1,40 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "webkit/browser/fileapi/quota/open_file_handle.h"
+
+#include "webkit/browser/fileapi/quota/open_file_handle_context.h"
+#include "webkit/browser/fileapi/quota/quota_reservation.h"
+
+namespace fileapi {
+
+OpenFileHandle::~OpenFileHandle() {
+ DCHECK(sequence_checker_.CalledOnValidSequencedThread());
+}
+
+int64 OpenFileHandle::UpdateMaxWrittenOffset(int64 offset) {
+ DCHECK(sequence_checker_.CalledOnValidSequencedThread());
+
+ int64 new_file_size = 0;
+ int64 growth = 0;
+ context_->UpdateMaxWrittenOffset(offset, &new_file_size, &growth);
+
+ if (growth > 0)
+ reservation_->ConsumeReservation(growth);
+
+ return new_file_size;
+}
+
+int64 OpenFileHandle::base_file_size() const {
+ return context_->base_file_size();
+}
+
+OpenFileHandle::OpenFileHandle(QuotaReservation* reservation,
+ OpenFileHandleContext* context)
+ : reservation_(reservation),
+ context_(context) {
+ DCHECK(sequence_checker_.CalledOnValidSequencedThread());
+}
+
+} // namespace fileapi
diff --git a/chromium/webkit/browser/fileapi/quota/open_file_handle.h b/chromium/webkit/browser/fileapi/quota/open_file_handle.h
new file mode 100644
index 00000000000..79f1380a437
--- /dev/null
+++ b/chromium/webkit/browser/fileapi/quota/open_file_handle.h
@@ -0,0 +1,51 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef WEBKIT_BROWSER_FILEAPI_QUOTA_OPEN_FILE_HANDLE_H_
+#define WEBKIT_BROWSER_FILEAPI_QUOTA_OPEN_FILE_HANDLE_H_
+
+#include "base/basictypes.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "webkit/browser/webkit_storage_browser_export.h"
+
+namespace fileapi {
+
+class QuotaReservation;
+class OpenFileHandleContext;
+class QuotaReservationBuffer;
+
+// Represents an open file like a file descriptor.
+// This should be alive while a consumer keeps a file opened and should be
+// deleted when the plugin closes the file.
+class WEBKIT_STORAGE_BROWSER_EXPORT OpenFileHandle {
+ public:
+ ~OpenFileHandle();
+
+ // Updates cached file size and consumes quota for that.
+ // This should be called for each modified file before calling RefreshQuota
+ // and file close.
+ // Returns updated base file size that should be used to measure quota
+ // consumption by difference to this.
+ int64 UpdateMaxWrittenOffset(int64 offset);
+
+ int64 base_file_size() const;
+
+ private:
+ friend class QuotaReservationBuffer;
+
+ OpenFileHandle(QuotaReservation* reservation,
+ OpenFileHandleContext* context);
+
+ scoped_refptr<QuotaReservation> reservation_;
+ scoped_refptr<OpenFileHandleContext> context_;
+
+ base::SequenceChecker sequence_checker_;
+
+ DISALLOW_COPY_AND_ASSIGN(OpenFileHandle);
+};
+
+} // namespace fileapi
+
+#endif // WEBKIT_BROWSER_FILEAPI_QUOTA_OPEN_FILE_HANDLE_H_
diff --git a/chromium/webkit/browser/fileapi/quota/open_file_handle_context.cc b/chromium/webkit/browser/fileapi/quota/open_file_handle_context.cc
new file mode 100644
index 00000000000..0928fff7ee2
--- /dev/null
+++ b/chromium/webkit/browser/fileapi/quota/open_file_handle_context.cc
@@ -0,0 +1,60 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "webkit/browser/fileapi/quota/open_file_handle_context.h"
+
+#include "base/file_util.h"
+#include "webkit/browser/fileapi/quota/quota_reservation_buffer.h"
+
+namespace fileapi {
+
+OpenFileHandleContext::OpenFileHandleContext(
+ const base::FilePath& platform_path,
+ QuotaReservationBuffer* reservation_buffer)
+ : initial_file_size_(0),
+ maximum_written_offset_(0),
+ platform_path_(platform_path),
+ reservation_buffer_(reservation_buffer) {
+ DCHECK(sequence_checker_.CalledOnValidSequencedThread());
+
+ base::GetFileSize(platform_path, &initial_file_size_);
+ maximum_written_offset_ = initial_file_size_;
+}
+
+void OpenFileHandleContext::UpdateMaxWrittenOffset(
+ int64 offset,
+ int64* new_file_size,
+ int64* growth) {
+ DCHECK(sequence_checker_.CalledOnValidSequencedThread());
+ if (offset > maximum_written_offset_) {
+ *growth = offset - maximum_written_offset_;
+ maximum_written_offset_ = offset;
+ } else {
+ *growth = 0;
+ }
+
+ *new_file_size = maximum_written_offset_;
+}
+
+OpenFileHandleContext::~OpenFileHandleContext() {
+ DCHECK(sequence_checker_.CalledOnValidSequencedThread());
+
+ // TODO(tzik): Optimize this for single operation.
+
+ int64 file_size = 0;
+ base::GetFileSize(platform_path_, &file_size);
+ int64 usage_delta = file_size - initial_file_size_;
+
+ // |quota_consumption| may be greater than the recorded file growth when a
+ // plugin crashed before reporting its consumption.
+ // In this case, the reserved quota for the plugin should be handled as
+ // consumed quota.
+ int64 quota_consumption =
+ std::max(maximum_written_offset_, file_size) - initial_file_size_;
+
+ reservation_buffer_->CommitFileGrowth(quota_consumption, usage_delta);
+ reservation_buffer_->DetachOpenFileHandleContext(this);
+}
+
+} // namespace fileapi
diff --git a/chromium/webkit/browser/fileapi/quota/open_file_handle_context.h b/chromium/webkit/browser/fileapi/quota/open_file_handle_context.h
new file mode 100644
index 00000000000..4b5d3cc75cd
--- /dev/null
+++ b/chromium/webkit/browser/fileapi/quota/open_file_handle_context.h
@@ -0,0 +1,59 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef WEBKIT_BROWSER_FILEAPI_OPEN_FILE_HANDLE_CONTEXT_H_
+#define WEBKIT_BROWSER_FILEAPI_OPEN_FILE_HANDLE_CONTEXT_H_
+
+#include <map>
+
+#include "base/basictypes.h"
+#include "base/files/file_path.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "base/platform_file.h"
+#include "url/gurl.h"
+#include "webkit/browser/webkit_storage_browser_export.h"
+#include "webkit/common/fileapi/file_system_types.h"
+
+namespace fileapi {
+
+class QuotaReservationBuffer;
+
+// This class represents a underlying file of a managed FileSystem file.
+// The instance keeps alive while at least one consumer keeps an open file
+// handle.
+// This class is usually manipulated only via OpenFileHandle.
+class OpenFileHandleContext : public base::RefCounted<OpenFileHandleContext> {
+ public:
+ OpenFileHandleContext(const base::FilePath& platform_path,
+ QuotaReservationBuffer* reservation_buffer);
+
+ void UpdateMaxWrittenOffset(int64 offset,
+ int64* new_file_size,
+ int64* growth);
+
+ const base::FilePath& platform_path() const {
+ return platform_path_;
+ }
+
+ int64 base_file_size() const { return maximum_written_offset_; }
+
+ private:
+ friend class base::RefCounted<OpenFileHandleContext>;
+ virtual ~OpenFileHandleContext();
+
+ int64 initial_file_size_;
+ int64 maximum_written_offset_;
+ base::FilePath platform_path_;
+
+ scoped_refptr<QuotaReservationBuffer> reservation_buffer_;
+
+ base::SequenceChecker sequence_checker_;
+
+ DISALLOW_COPY_AND_ASSIGN(OpenFileHandleContext);
+};
+
+} // namespace fileapi
+
+#endif // WEBKIT_BROWSER_FILEAPI_OPEN_FILE_HANDLE_CONTEXT_H_
diff --git a/chromium/webkit/browser/fileapi/quota/quota_backend_impl.cc b/chromium/webkit/browser/fileapi/quota/quota_backend_impl.cc
new file mode 100644
index 00000000000..41cc95297d8
--- /dev/null
+++ b/chromium/webkit/browser/fileapi/quota/quota_backend_impl.cc
@@ -0,0 +1,156 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "webkit/browser/fileapi/quota/quota_backend_impl.h"
+
+#include <string>
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/logging.h"
+#include "base/sequenced_task_runner.h"
+#include "webkit/browser/fileapi/file_system_usage_cache.h"
+#include "webkit/browser/quota/quota_client.h"
+#include "webkit/browser/quota/quota_manager.h"
+#include "webkit/common/fileapi/file_system_util.h"
+
+namespace fileapi {
+
+QuotaBackendImpl::QuotaBackendImpl(
+ base::SequencedTaskRunner* file_task_runner,
+ ObfuscatedFileUtil* obfuscated_file_util,
+ FileSystemUsageCache* file_system_usage_cache,
+ quota::QuotaManagerProxy* quota_manager_proxy)
+ : file_task_runner_(file_task_runner),
+ obfuscated_file_util_(obfuscated_file_util),
+ file_system_usage_cache_(file_system_usage_cache),
+ quota_manager_proxy_(quota_manager_proxy),
+ weak_ptr_factory_(this) {
+}
+
+QuotaBackendImpl::~QuotaBackendImpl() {
+}
+
+void QuotaBackendImpl::ReserveQuota(const GURL& origin,
+ FileSystemType type,
+ int64 delta,
+ const ReserveQuotaCallback& callback) {
+ DCHECK(file_task_runner_->RunsTasksOnCurrentThread());
+ DCHECK(origin.is_valid());
+ if (!delta) {
+ callback.Run(base::PLATFORM_FILE_OK);
+ return;
+ }
+ DCHECK(quota_manager_proxy_);
+ quota_manager_proxy_->GetUsageAndQuota(
+ file_task_runner_, origin, FileSystemTypeToQuotaStorageType(type),
+ base::Bind(&QuotaBackendImpl::DidGetUsageAndQuotaForReserveQuota,
+ weak_ptr_factory_.GetWeakPtr(),
+ QuotaReservationInfo(origin, type, delta), callback));
+}
+
+void QuotaBackendImpl::ReleaseReservedQuota(const GURL& origin,
+ FileSystemType type,
+ int64 size) {
+ DCHECK(file_task_runner_->RunsTasksOnCurrentThread());
+ DCHECK(origin.is_valid());
+ DCHECK_LE(0, size);
+ if (!size)
+ return;
+ ReserveQuotaInternal(QuotaReservationInfo(origin, type, -size));
+}
+
+void QuotaBackendImpl::CommitQuotaUsage(const GURL& origin,
+ FileSystemType type,
+ int64 delta) {
+ DCHECK(file_task_runner_->RunsTasksOnCurrentThread());
+ DCHECK(origin.is_valid());
+ if (!delta)
+ return;
+ ReserveQuotaInternal(QuotaReservationInfo(origin, type, delta));
+ base::FilePath path;
+ if (GetUsageCachePath(origin, type, &path) != base::PLATFORM_FILE_OK)
+ return;
+ bool result = file_system_usage_cache_->AtomicUpdateUsageByDelta(path, delta);
+ DCHECK(result);
+}
+
+void QuotaBackendImpl::IncrementDirtyCount(const GURL& origin,
+ FileSystemType type) {
+ DCHECK(file_task_runner_->RunsTasksOnCurrentThread());
+ DCHECK(origin.is_valid());
+ base::FilePath path;
+ if (GetUsageCachePath(origin, type, &path) != base::PLATFORM_FILE_OK)
+ return;
+ DCHECK(file_system_usage_cache_);
+ file_system_usage_cache_->IncrementDirty(path);
+}
+
+void QuotaBackendImpl::DecrementDirtyCount(const GURL& origin,
+ FileSystemType type) {
+ DCHECK(file_task_runner_->RunsTasksOnCurrentThread());
+ DCHECK(origin.is_valid());
+ base::FilePath path;
+ if (GetUsageCachePath(origin, type, &path) != base::PLATFORM_FILE_OK)
+ return;
+ DCHECK(file_system_usage_cache_);
+ file_system_usage_cache_->DecrementDirty(path);
+}
+
+void QuotaBackendImpl::DidGetUsageAndQuotaForReserveQuota(
+ const QuotaReservationInfo& info,
+ const ReserveQuotaCallback& callback,
+ quota::QuotaStatusCode status, int64 usage, int64 quota) {
+ DCHECK(file_task_runner_->RunsTasksOnCurrentThread());
+ DCHECK(info.origin.is_valid());
+ if (status != quota::kQuotaStatusOk) {
+ callback.Run(base::PLATFORM_FILE_ERROR_FAILED);
+ return;
+ }
+
+ if (quota < usage + info.delta) {
+ callback.Run(base::PLATFORM_FILE_ERROR_NO_SPACE);
+ return;
+ }
+
+ ReserveQuotaInternal(info);
+ if (callback.Run(base::PLATFORM_FILE_OK))
+ return;
+ // The requester could not accept the reserved quota. Revert it.
+ ReserveQuotaInternal(
+ QuotaReservationInfo(info.origin, info.type, -info.delta));
+}
+
+void QuotaBackendImpl::ReserveQuotaInternal(const QuotaReservationInfo& info) {
+ DCHECK(file_task_runner_->RunsTasksOnCurrentThread());
+ DCHECK(info.origin.is_valid());
+ DCHECK(quota_manager_proxy_);
+ quota_manager_proxy_->NotifyStorageModified(
+ quota::QuotaClient::kFileSystem, info.origin,
+ FileSystemTypeToQuotaStorageType(info.type), info.delta);
+}
+
+base::PlatformFileError QuotaBackendImpl::GetUsageCachePath(
+ const GURL& origin,
+ FileSystemType type,
+ base::FilePath* usage_file_path) {
+ DCHECK(file_task_runner_->RunsTasksOnCurrentThread());
+ DCHECK(origin.is_valid());
+ DCHECK(usage_file_path);
+ base::PlatformFileError error = base::PLATFORM_FILE_OK;
+ *usage_file_path =
+ SandboxFileSystemBackendDelegate::GetUsageCachePathForOriginAndType(
+ obfuscated_file_util_, origin, type, &error);
+ return error;
+}
+
+QuotaBackendImpl::QuotaReservationInfo::QuotaReservationInfo(
+ const GURL& origin, FileSystemType type, int64 delta)
+ : origin(origin), type(type), delta(delta) {
+}
+
+QuotaBackendImpl::QuotaReservationInfo::~QuotaReservationInfo() {
+}
+
+} // namespace fileapi
diff --git a/chromium/webkit/browser/fileapi/quota/quota_backend_impl.h b/chromium/webkit/browser/fileapi/quota/quota_backend_impl.h
new file mode 100644
index 00000000000..10c38e7ea7c
--- /dev/null
+++ b/chromium/webkit/browser/fileapi/quota/quota_backend_impl.h
@@ -0,0 +1,103 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef WEBKIT_BROWSER_FILEAPI_QUOTA_QUOTA_BACKEND_IMPL_H_
+#define WEBKIT_BROWSER_FILEAPI_QUOTA_QUOTA_BACKEND_IMPL_H_
+
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "webkit/browser/fileapi/quota/quota_reservation_manager.h"
+#include "webkit/browser/fileapi/sandbox_file_system_backend_delegate.h"
+#include "webkit/browser/webkit_storage_browser_export.h"
+#include "webkit/common/quota/quota_status_code.h"
+
+namespace base {
+class SequencedTaskRunner;
+}
+
+namespace quota {
+class QuotaManagerProxy;
+}
+
+namespace fileapi {
+
+class FileSystemUsageCache;
+class ObfuscatedFileUtil;
+
+// An instance of this class is owned by QuotaReservationManager.
+class WEBKIT_STORAGE_BROWSER_EXPORT QuotaBackendImpl
+ : public QuotaReservationManager::QuotaBackend {
+ public:
+ typedef QuotaReservationManager::ReserveQuotaCallback
+ ReserveQuotaCallback;
+
+ QuotaBackendImpl(base::SequencedTaskRunner* file_task_runner,
+ ObfuscatedFileUtil* obfuscated_file_util,
+ FileSystemUsageCache* file_system_usage_cache,
+ quota::QuotaManagerProxy* quota_manager_proxy);
+ virtual ~QuotaBackendImpl();
+
+ // QuotaReservationManager::QuotaBackend overrides.
+ virtual void ReserveQuota(
+ const GURL& origin,
+ FileSystemType type,
+ int64 delta,
+ const ReserveQuotaCallback& callback) OVERRIDE;
+ virtual void ReleaseReservedQuota(
+ const GURL& origin,
+ FileSystemType type,
+ int64 size) OVERRIDE;
+ virtual void CommitQuotaUsage(
+ const GURL& origin,
+ FileSystemType type,
+ int64 delta) OVERRIDE;
+ virtual void IncrementDirtyCount(
+ const GURL& origin,
+ FileSystemType type) OVERRIDE;
+ virtual void DecrementDirtyCount(
+ const GURL& origin,
+ FileSystemType type) OVERRIDE;
+
+ private:
+ friend class QuotaBackendImplTest;
+
+ struct QuotaReservationInfo {
+ QuotaReservationInfo(const GURL& origin, FileSystemType type, int64 delta);
+ ~QuotaReservationInfo();
+
+ GURL origin;
+ FileSystemType type;
+ int64 delta;
+ };
+
+ void DidGetUsageAndQuotaForReserveQuota(
+ const QuotaReservationInfo& info,
+ const ReserveQuotaCallback& callback,
+ quota::QuotaStatusCode status,
+ int64 usage,
+ int64 quota);
+
+ void ReserveQuotaInternal(
+ const QuotaReservationInfo& info);
+ base::PlatformFileError GetUsageCachePath(
+ const GURL& origin,
+ FileSystemType type,
+ base::FilePath* usage_file_path);
+
+ scoped_refptr<base::SequencedTaskRunner> file_task_runner_;
+
+ // Owned by SandboxFileSystemBackendDelegate.
+ ObfuscatedFileUtil* obfuscated_file_util_;
+ FileSystemUsageCache* file_system_usage_cache_;
+
+ scoped_refptr<quota::QuotaManagerProxy> quota_manager_proxy_;
+
+ base::WeakPtrFactory<QuotaBackendImpl> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(QuotaBackendImpl);
+};
+
+} // namespace fileapi
+
+#endif // WEBKIT_BROWSER_FILEAPI_QUOTA_QUOTA_BACKEND_IMPL_H_
diff --git a/chromium/webkit/browser/fileapi/quota/quota_backend_impl_unittest.cc b/chromium/webkit/browser/fileapi/quota/quota_backend_impl_unittest.cc
new file mode 100644
index 00000000000..75e8db8fe8c
--- /dev/null
+++ b/chromium/webkit/browser/fileapi/quota/quota_backend_impl_unittest.cc
@@ -0,0 +1,248 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "webkit/browser/fileapi/quota/quota_backend_impl.h"
+
+#include <string>
+
+#include "base/files/scoped_temp_dir.h"
+#include "base/message_loop/message_loop.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "webkit/browser/fileapi/file_system_usage_cache.h"
+#include "webkit/browser/fileapi/obfuscated_file_util.h"
+#include "webkit/browser/quota/quota_manager.h"
+
+namespace fileapi {
+
+namespace {
+
+const char kOrigin[] = "http://example.com";
+
+bool DidReserveQuota(bool accepted,
+ base::PlatformFileError* error_out,
+ base::PlatformFileError error) {
+ DCHECK(error_out);
+ *error_out = error;
+ return accepted;
+}
+
+class MockQuotaManagerProxy : public quota::QuotaManagerProxy {
+ public:
+ MockQuotaManagerProxy()
+ : QuotaManagerProxy(NULL, NULL),
+ storage_modified_count_(0),
+ usage_(0), quota_(0) {}
+
+ // We don't mock them.
+ virtual void NotifyOriginInUse(const GURL& origin) OVERRIDE {}
+ virtual void NotifyOriginNoLongerInUse(const GURL& origin) OVERRIDE {}
+ virtual void SetUsageCacheEnabled(quota::QuotaClient::ID client_id,
+ const GURL& origin,
+ quota::StorageType type,
+ bool enabled) OVERRIDE {}
+
+ virtual void NotifyStorageModified(
+ quota::QuotaClient::ID client_id,
+ const GURL& origin,
+ quota::StorageType type,
+ int64 delta) OVERRIDE {
+ ++storage_modified_count_;
+ usage_ += delta;
+ ASSERT_LT(usage_, quota_);
+ }
+
+ virtual void GetUsageAndQuota(
+ base::SequencedTaskRunner* original_task_runner,
+ const GURL& origin,
+ quota::StorageType type,
+ const GetUsageAndQuotaCallback& callback) OVERRIDE {
+ callback.Run(quota::kQuotaStatusOk, usage_, quota_);
+ }
+
+ int storage_modified_count() { return storage_modified_count_; }
+ int64 usage() { return usage_; }
+ void set_usage(int64 usage) { usage_ = usage; }
+ void set_quota(int64 quota) { quota_ = quota; }
+
+ protected:
+ virtual ~MockQuotaManagerProxy() {}
+
+ private:
+ int storage_modified_count_;
+ int64 usage_;
+ int64 quota_;
+
+ DISALLOW_COPY_AND_ASSIGN(MockQuotaManagerProxy);
+};
+
+} // namespace
+
+class QuotaBackendImplTest : public testing::Test {
+ public:
+ QuotaBackendImplTest()
+ : file_system_usage_cache_(file_task_runner()),
+ quota_manager_proxy_(new MockQuotaManagerProxy) {}
+
+ virtual void SetUp() OVERRIDE {
+ ASSERT_TRUE(data_dir_.CreateUniqueTempDir());
+ file_util_.reset(ObfuscatedFileUtil::CreateForTesting(
+ NULL, data_dir_.path(), file_task_runner()));
+ backend_.reset(new QuotaBackendImpl(file_task_runner(),
+ file_util_.get(),
+ &file_system_usage_cache_,
+ quota_manager_proxy_.get()));
+ }
+
+ virtual void TearDown() OVERRIDE {
+ backend_.reset();
+ quota_manager_proxy_ = NULL;
+ file_util_.reset();
+ message_loop_.RunUntilIdle();
+ }
+
+ protected:
+ void InitializeForOriginAndType(const GURL& origin, FileSystemType type) {
+ ASSERT_TRUE(file_util_->InitOriginDatabase(origin, true /* create */));
+ ASSERT_TRUE(file_util_->origin_database_ != NULL);
+
+ std::string type_string =
+ SandboxFileSystemBackendDelegate::GetTypeString(type);
+ base::PlatformFileError error = base::PLATFORM_FILE_ERROR_FAILED;
+ base::FilePath path = file_util_->GetDirectoryForOriginAndType(
+ origin, type_string, true /* create */, &error);
+ ASSERT_EQ(base::PLATFORM_FILE_OK, error);
+
+ ASSERT_TRUE(file_system_usage_cache_.UpdateUsage(
+ GetUsageCachePath(origin, type), 0));
+ }
+
+ base::SequencedTaskRunner* file_task_runner() {
+ return base::MessageLoopProxy::current().get();
+ }
+
+ base::FilePath GetUsageCachePath(const GURL& origin, FileSystemType type) {
+ base::FilePath path;
+ base::PlatformFileError error =
+ backend_->GetUsageCachePath(origin, type, &path);
+ EXPECT_EQ(base::PLATFORM_FILE_OK, error);
+ EXPECT_FALSE(path.empty());
+ return path;
+ }
+
+ base::MessageLoop message_loop_;
+ base::ScopedTempDir data_dir_;
+ scoped_ptr<ObfuscatedFileUtil> file_util_;
+ FileSystemUsageCache file_system_usage_cache_;
+ scoped_refptr<MockQuotaManagerProxy> quota_manager_proxy_;
+ scoped_ptr<QuotaBackendImpl> backend_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(QuotaBackendImplTest);
+};
+
+TEST_F(QuotaBackendImplTest, ReserveQuota_Basic) {
+ FileSystemType type = fileapi::kFileSystemTypeTemporary;
+ InitializeForOriginAndType(GURL(kOrigin), type);
+ quota_manager_proxy_->set_quota(10000);
+
+ const int64 kDelta1 = 1000;
+ base::PlatformFileError error = base::PLATFORM_FILE_ERROR_FAILED;
+ backend_->ReserveQuota(GURL(kOrigin), type, kDelta1,
+ base::Bind(&DidReserveQuota, true, &error));
+ EXPECT_EQ(base::PLATFORM_FILE_OK, error);
+ EXPECT_EQ(kDelta1, quota_manager_proxy_->usage());
+
+ const int64 kDelta2 = -300;
+ error = base::PLATFORM_FILE_ERROR_FAILED;
+ backend_->ReserveQuota(GURL(kOrigin), type, kDelta2,
+ base::Bind(&DidReserveQuota, true, &error));
+ EXPECT_EQ(base::PLATFORM_FILE_OK, error);
+ EXPECT_EQ(kDelta1 + kDelta2, quota_manager_proxy_->usage());
+
+ EXPECT_EQ(2, quota_manager_proxy_->storage_modified_count());
+}
+
+TEST_F(QuotaBackendImplTest, ReserveQuota_NoSpace) {
+ FileSystemType type = fileapi::kFileSystemTypeTemporary;
+ InitializeForOriginAndType(GURL(kOrigin), type);
+ quota_manager_proxy_->set_quota(100);
+
+ const int64 kDelta = 1000;
+ base::PlatformFileError error = base::PLATFORM_FILE_ERROR_FAILED;
+ backend_->ReserveQuota(GURL(kOrigin), type, kDelta,
+ base::Bind(&DidReserveQuota, true, &error));
+ EXPECT_EQ(base::PLATFORM_FILE_ERROR_NO_SPACE, error);
+ EXPECT_EQ(0, quota_manager_proxy_->usage());
+
+ EXPECT_EQ(0, quota_manager_proxy_->storage_modified_count());
+}
+
+TEST_F(QuotaBackendImplTest, ReserveQuota_Revert) {
+ FileSystemType type = fileapi::kFileSystemTypeTemporary;
+ InitializeForOriginAndType(GURL(kOrigin), type);
+ quota_manager_proxy_->set_quota(10000);
+
+ const int64 kDelta = 1000;
+ base::PlatformFileError error = base::PLATFORM_FILE_ERROR_FAILED;
+ backend_->ReserveQuota(GURL(kOrigin), type, kDelta,
+ base::Bind(&DidReserveQuota, false, &error));
+ EXPECT_EQ(base::PLATFORM_FILE_OK, error);
+ EXPECT_EQ(0, quota_manager_proxy_->usage());
+
+ EXPECT_EQ(2, quota_manager_proxy_->storage_modified_count());
+}
+
+TEST_F(QuotaBackendImplTest, ReleaseReservedQuota) {
+ FileSystemType type = fileapi::kFileSystemTypeTemporary;
+ InitializeForOriginAndType(GURL(kOrigin), type);
+ const int64 kInitialUsage = 2000;
+ quota_manager_proxy_->set_usage(kInitialUsage);
+ quota_manager_proxy_->set_quota(10000);
+
+ const int64 kSize = 1000;
+ backend_->ReleaseReservedQuota(GURL(kOrigin), type, kSize);
+ EXPECT_EQ(kInitialUsage - kSize, quota_manager_proxy_->usage());
+
+ EXPECT_EQ(1, quota_manager_proxy_->storage_modified_count());
+}
+
+TEST_F(QuotaBackendImplTest, CommitQuotaUsage) {
+ FileSystemType type = fileapi::kFileSystemTypeTemporary;
+ InitializeForOriginAndType(GURL(kOrigin), type);
+ quota_manager_proxy_->set_quota(10000);
+ base::FilePath path = GetUsageCachePath(GURL(kOrigin), type);
+
+ const int64 kDelta1 = 1000;
+ backend_->CommitQuotaUsage(GURL(kOrigin), type, kDelta1);
+ EXPECT_EQ(kDelta1, quota_manager_proxy_->usage());
+ int64 usage = 0;
+ EXPECT_TRUE(file_system_usage_cache_.GetUsage(path, &usage));
+ EXPECT_EQ(kDelta1, usage);
+
+ const int64 kDelta2 = -300;
+ backend_->CommitQuotaUsage(GURL(kOrigin), type, kDelta2);
+ EXPECT_EQ(kDelta1 + kDelta2, quota_manager_proxy_->usage());
+ usage = 0;
+ EXPECT_TRUE(file_system_usage_cache_.GetUsage(path, &usage));
+ EXPECT_EQ(kDelta1 + kDelta2, usage);
+
+ EXPECT_EQ(2, quota_manager_proxy_->storage_modified_count());
+}
+
+TEST_F(QuotaBackendImplTest, DirtyCount) {
+ FileSystemType type = fileapi::kFileSystemTypeTemporary;
+ InitializeForOriginAndType(GURL(kOrigin), type);
+ base::FilePath path = GetUsageCachePath(GURL(kOrigin), type);
+
+ backend_->IncrementDirtyCount(GURL(kOrigin), type);
+ uint32 dirty = 0;
+ ASSERT_TRUE(file_system_usage_cache_.GetDirty(path, &dirty));
+ EXPECT_EQ(1u, dirty);
+
+ backend_->DecrementDirtyCount(GURL(kOrigin), type);
+ ASSERT_TRUE(file_system_usage_cache_.GetDirty(path, &dirty));
+ EXPECT_EQ(0u, dirty);
+}
+
+} // namespace fileapi
diff --git a/chromium/webkit/browser/fileapi/quota/quota_reservation.cc b/chromium/webkit/browser/fileapi/quota/quota_reservation.cc
new file mode 100644
index 00000000000..c5a22ab2614
--- /dev/null
+++ b/chromium/webkit/browser/fileapi/quota/quota_reservation.cc
@@ -0,0 +1,113 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "webkit/browser/fileapi/quota/quota_reservation.h"
+
+#include "base/bind.h"
+#include "webkit/browser/fileapi/quota/open_file_handle.h"
+#include "webkit/browser/fileapi/quota/quota_reservation_buffer.h"
+
+namespace fileapi {
+
+void QuotaReservation::RefreshReservation(
+ int64 size,
+ const StatusCallback& callback) {
+ DCHECK(sequence_checker_.CalledOnValidSequencedThread());
+ DCHECK(!running_refresh_request_);
+ if (!reservation_manager())
+ return;
+
+ running_refresh_request_ = true;
+
+ reservation_manager()->ReserveQuota(
+ origin(), type(), size - remaining_quota_,
+ base::Bind(&QuotaReservation::AdaptDidUpdateReservedQuota,
+ weak_ptr_factory_.GetWeakPtr(),
+ size, callback));
+
+ if (running_refresh_request_)
+ remaining_quota_ = 0;
+}
+
+scoped_ptr<OpenFileHandle> QuotaReservation::GetOpenFileHandle(
+ const base::FilePath& platform_path) {
+ DCHECK(sequence_checker_.CalledOnValidSequencedThread());
+ return reservation_buffer_->GetOpenFileHandle(this, platform_path);
+}
+
+void QuotaReservation::OnClientCrash() {
+ DCHECK(sequence_checker_.CalledOnValidSequencedThread());
+
+ if (remaining_quota_) {
+ reservation_buffer_->PutReservationToBuffer(remaining_quota_);
+ remaining_quota_ = 0;
+ }
+}
+
+void QuotaReservation::ConsumeReservation(int64 size) {
+ DCHECK(sequence_checker_.CalledOnValidSequencedThread());
+ DCHECK_LT(0, size);
+ DCHECK_LT(size, remaining_quota_);
+
+ remaining_quota_ -= size;
+ reservation_buffer_->PutReservationToBuffer(size);
+}
+
+QuotaReservationManager* QuotaReservation::reservation_manager() {
+ return reservation_buffer_->reservation_manager();
+}
+
+const GURL& QuotaReservation::origin() const {
+ return reservation_buffer_->origin();
+}
+
+FileSystemType QuotaReservation::type() const {
+ return reservation_buffer_->type();
+}
+
+QuotaReservation::QuotaReservation(
+ QuotaReservationBuffer* reservation_buffer)
+ : running_refresh_request_(false),
+ remaining_quota_(0),
+ reservation_buffer_(reservation_buffer),
+ weak_ptr_factory_(this) {
+ DCHECK(sequence_checker_.CalledOnValidSequencedThread());
+}
+
+QuotaReservation::~QuotaReservation() {
+ DCHECK(sequence_checker_.CalledOnValidSequencedThread());
+
+ if (remaining_quota_ && reservation_manager()) {
+ reservation_manager()->ReleaseReservedQuota(
+ origin(), type(), remaining_quota_);
+ }
+}
+
+// static
+bool QuotaReservation::AdaptDidUpdateReservedQuota(
+ const base::WeakPtr<QuotaReservation>& reservation,
+ int64 new_reserved_size,
+ const StatusCallback& callback,
+ base::PlatformFileError error) {
+ if (!reservation)
+ return false;
+
+ reservation->DidUpdateReservedQuota(new_reserved_size, callback, error);
+ return true;
+}
+
+void QuotaReservation::DidUpdateReservedQuota(
+ int64 new_reserved_size,
+ const StatusCallback& callback,
+ base::PlatformFileError error) {
+ DCHECK(sequence_checker_.CalledOnValidSequencedThread());
+ DCHECK(running_refresh_request_);
+ running_refresh_request_ = false;
+
+ if (error == base::PLATFORM_FILE_OK)
+ remaining_quota_ = new_reserved_size;
+ callback.Run(error);
+}
+
+} // namespace fileapi
diff --git a/chromium/webkit/browser/fileapi/quota/quota_reservation.h b/chromium/webkit/browser/fileapi/quota/quota_reservation.h
new file mode 100644
index 00000000000..d534a0dcc2c
--- /dev/null
+++ b/chromium/webkit/browser/fileapi/quota/quota_reservation.h
@@ -0,0 +1,89 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef WEBKIT_BROWSER_FILEAPI_QUOTA_QUOTA_RESERVATION_H_
+#define WEBKIT_BROWSER_FILEAPI_QUOTA_QUOTA_RESERVATION_H_
+
+#include "base/basictypes.h"
+#include "base/files/file_path.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "webkit/browser/fileapi/quota/quota_reservation_manager.h"
+#include "webkit/browser/webkit_storage_browser_export.h"
+#include "webkit/common/fileapi/file_system_types.h"
+
+class GURL;
+
+namespace fileapi {
+
+class QuotaReservationBuffer;
+class OpenFileHandle;
+
+// Represents a unit of quota reservation.
+class WEBKIT_STORAGE_BROWSER_EXPORT QuotaReservation
+ : public base::RefCounted<QuotaReservation> {
+ public:
+ typedef base::Callback<void(base::PlatformFileError error)> StatusCallback;
+
+ // Reclaims unused quota and reserves another |size| of quota. So that the
+ // resulting new |remaining_quota| will be same as |size|.
+ // Invokes |callback| upon completion.
+ void RefreshReservation(int64 size, const StatusCallback& callback);
+
+ // Associates |platform_path| to the QuotaReservation instance.
+ // Returns an OpenFileHandle instance that represents a quota managed file.
+ scoped_ptr<OpenFileHandle> GetOpenFileHandle(
+ const base::FilePath& platform_path);
+
+ // Should be called when the associated client is crashed.
+ // This implies the client can no longer report its consumption of the
+ // reserved quota.
+ // QuotaReservation puts all remaining quota to the QuotaReservationBuffer, so
+ // that the remaining quota will be reclaimed after all open files associated
+ // to the origin and type.
+ void OnClientCrash();
+
+ // Consumes |size| of reserved quota for a associated file.
+ // Consumed quota is sent to associated QuotaReservationBuffer for staging.
+ void ConsumeReservation(int64 size);
+
+ // Returns amount of unused reserved quota.
+ int64 remaining_quota() const { return remaining_quota_; }
+
+ QuotaReservationManager* reservation_manager();
+ const GURL& origin() const;
+ FileSystemType type() const;
+
+ private:
+ friend class QuotaReservationBuffer;
+
+ // Use QuotaReservationManager as the entry point.
+ explicit QuotaReservation(QuotaReservationBuffer* reservation_buffer);
+
+ friend class base::RefCounted<QuotaReservation>;
+ virtual ~QuotaReservation();
+
+ static bool AdaptDidUpdateReservedQuota(
+ const base::WeakPtr<QuotaReservation>& reservation,
+ int64 new_reserved_size,
+ const StatusCallback& callback,
+ base::PlatformFileError error);
+ void DidUpdateReservedQuota(int64 new_reserved_size,
+ const StatusCallback& callback,
+ base::PlatformFileError error);
+
+ bool running_refresh_request_;
+ int64 remaining_quota_;
+
+ scoped_refptr<QuotaReservationBuffer> reservation_buffer_;
+
+ base::SequenceChecker sequence_checker_;
+ base::WeakPtrFactory<QuotaReservation> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(QuotaReservation);
+};
+
+} // namespace fileapi
+
+#endif // WEBKIT_BROWSER_FILEAPI_QUOTA_QUOTA_RESERVATION_H_
diff --git a/chromium/webkit/browser/fileapi/quota/quota_reservation_buffer.cc b/chromium/webkit/browser/fileapi/quota/quota_reservation_buffer.cc
new file mode 100644
index 00000000000..14ea0d0cd81
--- /dev/null
+++ b/chromium/webkit/browser/fileapi/quota/quota_reservation_buffer.cc
@@ -0,0 +1,105 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "webkit/browser/fileapi/quota/quota_reservation_buffer.h"
+
+#include "base/bind.h"
+#include "webkit/browser/fileapi/quota/open_file_handle.h"
+#include "webkit/browser/fileapi/quota/open_file_handle_context.h"
+#include "webkit/browser/fileapi/quota/quota_reservation.h"
+
+namespace fileapi {
+
+QuotaReservationBuffer::QuotaReservationBuffer(
+ base::WeakPtr<QuotaReservationManager> reservation_manager,
+ const GURL& origin,
+ FileSystemType type)
+ : reservation_manager_(reservation_manager),
+ origin_(origin),
+ type_(type),
+ reserved_quota_(0) {
+ DCHECK(origin.is_valid());
+ DCHECK(sequence_checker_.CalledOnValidSequencedThread());
+ reservation_manager_->IncrementDirtyCount(origin, type);
+}
+
+scoped_refptr<QuotaReservation> QuotaReservationBuffer::CreateReservation() {
+ DCHECK(sequence_checker_.CalledOnValidSequencedThread());
+ return make_scoped_refptr(new QuotaReservation(this));
+}
+
+scoped_ptr<OpenFileHandle> QuotaReservationBuffer::GetOpenFileHandle(
+ QuotaReservation* reservation,
+ const base::FilePath& platform_path) {
+ DCHECK(sequence_checker_.CalledOnValidSequencedThread());
+ OpenFileHandleContext** open_file = &open_files_[platform_path];
+ if (!*open_file)
+ *open_file = new OpenFileHandleContext(platform_path, this);
+ return make_scoped_ptr(new OpenFileHandle(reservation, *open_file));
+}
+
+void QuotaReservationBuffer::CommitFileGrowth(int64 quota_consumption,
+ int64 usage_delta) {
+ DCHECK(sequence_checker_.CalledOnValidSequencedThread());
+ if (!reservation_manager_)
+ return;
+ reservation_manager_->CommitQuotaUsage(origin_, type_, usage_delta);
+
+ if (quota_consumption > 0) {
+ if (quota_consumption > reserved_quota_) {
+ LOG(ERROR) << "Detected over consumption of the storage quota beyond its"
+ << " reservation";
+ quota_consumption = reserved_quota_;
+ }
+
+ reserved_quota_ -= quota_consumption;
+ reservation_manager_->ReleaseReservedQuota(
+ origin_, type_, quota_consumption);
+ }
+}
+
+void QuotaReservationBuffer::DetachOpenFileHandleContext(
+ OpenFileHandleContext* open_file) {
+ DCHECK(sequence_checker_.CalledOnValidSequencedThread());
+ DCHECK_EQ(open_file, open_files_[open_file->platform_path()]);
+ open_files_.erase(open_file->platform_path());
+}
+
+void QuotaReservationBuffer::PutReservationToBuffer(int64 reservation) {
+ DCHECK(sequence_checker_.CalledOnValidSequencedThread());
+ DCHECK_LE(0, reservation);
+ reserved_quota_ += reservation;
+}
+
+QuotaReservationBuffer::~QuotaReservationBuffer() {
+ DCHECK(sequence_checker_.CalledOnValidSequencedThread());
+ if (!reservation_manager_)
+ return;
+
+ DCHECK_LE(0, reserved_quota_);
+ if (reserved_quota_ && reservation_manager_) {
+ reservation_manager_->ReserveQuota(
+ origin_, type_, -reserved_quota_,
+ base::Bind(&QuotaReservationBuffer::DecrementDirtyCount,
+ reservation_manager_, origin_, type_));
+ }
+ reservation_manager_->ReleaseReservationBuffer(this);
+}
+
+// static
+bool QuotaReservationBuffer::DecrementDirtyCount(
+ base::WeakPtr<QuotaReservationManager> reservation_manager,
+ const GURL& origin,
+ FileSystemType type,
+ base::PlatformFileError error) {
+ DCHECK(origin.is_valid());
+ if (error == base::PLATFORM_FILE_OK && reservation_manager) {
+ reservation_manager->DecrementDirtyCount(origin, type);
+ return true;
+ }
+ return false;
+}
+
+
+} // namespace fileapi
diff --git a/chromium/webkit/browser/fileapi/quota/quota_reservation_buffer.h b/chromium/webkit/browser/fileapi/quota/quota_reservation_buffer.h
new file mode 100644
index 00000000000..9a11fa5f842
--- /dev/null
+++ b/chromium/webkit/browser/fileapi/quota/quota_reservation_buffer.h
@@ -0,0 +1,86 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef WEBKIT_BROWSER_FILEAPI_QUOTA_QUOTA_RESERVATION_BUFFER_H_
+#define WEBKIT_BROWSER_FILEAPI_QUOTA_QUOTA_RESERVATION_BUFFER_H_
+
+#include <map>
+
+#include "base/basictypes.h"
+#include "base/files/file_path.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "base/platform_file.h"
+#include "url/gurl.h"
+#include "webkit/browser/webkit_storage_browser_export.h"
+#include "webkit/common/fileapi/file_system_types.h"
+
+namespace fileapi {
+
+class QuotaReservation;
+class OpenFileHandle;
+class OpenFileHandleContext;
+class QuotaReservationManager;
+
+// QuotaReservationBuffer manages QuotaReservation instances. All consumed
+// quota and leaked quota by associated QuotaReservation will be staged in
+// QuotaReservationBuffer, and will be committed on a modified file is closed.
+// The instance keeps alive while any associated QuotaReservation or
+// OpenFileHandle alive.
+// This class is usually manipulated only via OpenFileHandle and
+// QuotaReservation.
+class QuotaReservationBuffer : public base::RefCounted<QuotaReservationBuffer> {
+ public:
+ QuotaReservationBuffer(
+ base::WeakPtr<QuotaReservationManager> reservation_manager,
+ const GURL& origin,
+ FileSystemType type);
+
+ scoped_refptr<QuotaReservation> CreateReservation();
+ scoped_ptr<OpenFileHandle> GetOpenFileHandle(
+ QuotaReservation* reservation,
+ const base::FilePath& platform_path);
+ void CommitFileGrowth(int64 quota_consumption, int64 usage_delta);
+ void DetachOpenFileHandleContext(OpenFileHandleContext* context);
+ void PutReservationToBuffer(int64 size);
+
+ QuotaReservationManager* reservation_manager() {
+ return reservation_manager_.get();
+ }
+
+ const GURL& origin() const { return origin_; }
+ FileSystemType type() const { return type_; }
+
+ private:
+ friend class base::RefCounted<QuotaReservationBuffer>;
+ virtual ~QuotaReservationBuffer();
+
+ static bool DecrementDirtyCount(
+ base::WeakPtr<QuotaReservationManager> reservation_manager,
+ const GURL& origin,
+ FileSystemType type,
+ base::PlatformFileError error);
+
+ typedef std::map<base::FilePath, OpenFileHandleContext*>
+ OpenFileHandleContextByPath;
+
+ // Not owned. The destructor of OpenFileHandler should erase itself from
+ // |open_files_|.
+ OpenFileHandleContextByPath open_files_;
+
+ base::WeakPtr<QuotaReservationManager> reservation_manager_;
+
+ GURL origin_;
+ fileapi::FileSystemType type_;
+
+ int64 reserved_quota_;
+
+ base::SequenceChecker sequence_checker_;
+
+ DISALLOW_COPY_AND_ASSIGN(QuotaReservationBuffer);
+};
+
+} // namespace fileapi
+
+#endif // WEBKIT_BROWSER_FILEAPI_QUOTA_QUOTA_RESERVATION_BUFFER_H_
diff --git a/chromium/webkit/browser/fileapi/quota/quota_reservation_manager.cc b/chromium/webkit/browser/fileapi/quota/quota_reservation_manager.cc
new file mode 100644
index 00000000000..efb54b2225b
--- /dev/null
+++ b/chromium/webkit/browser/fileapi/quota/quota_reservation_manager.cc
@@ -0,0 +1,91 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "webkit/browser/fileapi/quota/quota_reservation_manager.h"
+
+#include "webkit/browser/fileapi/quota/quota_reservation.h"
+#include "webkit/browser/fileapi/quota/quota_reservation_buffer.h"
+
+namespace fileapi {
+
+QuotaReservationManager::QuotaReservationManager(
+ scoped_ptr<QuotaBackend> backend)
+ : backend_(backend.Pass()),
+ weak_ptr_factory_(this) {
+ sequence_checker_.DetachFromSequence();
+}
+
+QuotaReservationManager::~QuotaReservationManager() {
+ DCHECK(sequence_checker_.CalledOnValidSequencedThread());
+}
+
+void QuotaReservationManager::ReserveQuota(
+ const GURL& origin,
+ FileSystemType type,
+ int64 size,
+ const ReserveQuotaCallback& callback) {
+ DCHECK(origin.is_valid());
+ backend_->ReserveQuota(origin, type, size, callback);
+}
+
+void QuotaReservationManager::ReleaseReservedQuota(
+ const GURL& origin,
+ FileSystemType type,
+ int64 size) {
+ DCHECK(origin.is_valid());
+ backend_->ReleaseReservedQuota(origin, type, size);
+}
+
+void QuotaReservationManager::CommitQuotaUsage(
+ const GURL& origin,
+ FileSystemType type,
+ int64 delta) {
+ DCHECK(origin.is_valid());
+ backend_->CommitQuotaUsage(origin, type, delta);
+}
+
+void QuotaReservationManager::IncrementDirtyCount(const GURL& origin,
+ FileSystemType type) {
+ DCHECK(origin.is_valid());
+ backend_->IncrementDirtyCount(origin, type);
+}
+
+void QuotaReservationManager::DecrementDirtyCount(const GURL& origin,
+ FileSystemType type) {
+ DCHECK(origin.is_valid());
+ backend_->DecrementDirtyCount(origin, type);
+}
+
+scoped_refptr<QuotaReservationBuffer>
+QuotaReservationManager::GetReservationBuffer(
+ const GURL& origin,
+ FileSystemType type) {
+ DCHECK(sequence_checker_.CalledOnValidSequencedThread());
+ DCHECK(origin.is_valid());
+ QuotaReservationBuffer** buffer =
+ &reservation_buffers_[std::make_pair(origin, type)];
+ if (!*buffer) {
+ *buffer = new QuotaReservationBuffer(
+ weak_ptr_factory_.GetWeakPtr(), origin, type);
+ }
+ return make_scoped_refptr(*buffer);
+}
+
+void QuotaReservationManager::ReleaseReservationBuffer(
+ QuotaReservationBuffer* reservation_buffer) {
+ DCHECK(sequence_checker_.CalledOnValidSequencedThread());
+ std::pair<GURL, FileSystemType> key(reservation_buffer->origin(),
+ reservation_buffer->type());
+ DCHECK_EQ(reservation_buffers_[key], reservation_buffer);
+ reservation_buffers_.erase(key);
+}
+
+scoped_refptr<QuotaReservation> QuotaReservationManager::CreateReservation(
+ const GURL& origin,
+ FileSystemType type) {
+ DCHECK(origin.is_valid());
+ return GetReservationBuffer(origin, type)->CreateReservation();;
+}
+
+} // namespace fileapi
diff --git a/chromium/webkit/browser/fileapi/quota/quota_reservation_manager.h b/chromium/webkit/browser/fileapi/quota/quota_reservation_manager.h
new file mode 100644
index 00000000000..07beacc3277
--- /dev/null
+++ b/chromium/webkit/browser/fileapi/quota/quota_reservation_manager.h
@@ -0,0 +1,123 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef WEBKIT_BROWSER_FILEAPI_QUOTA_QUOTA_RESERVATION_MANAGER_H_
+#define WEBKIT_BROWSER_FILEAPI_QUOTA_QUOTA_RESERVATION_MANAGER_H_
+
+#include <map>
+#include <utility>
+
+#include "base/basictypes.h"
+#include "base/callback_forward.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "base/platform_file.h"
+#include "url/gurl.h"
+#include "webkit/browser/webkit_storage_browser_export.h"
+#include "webkit/common/fileapi/file_system_types.h"
+
+namespace fileapi {
+
+class QuotaReservation;
+class QuotaReservationBuffer;
+class OpenFileHandle;
+class OpenFileHandleContext;
+
+class WEBKIT_STORAGE_BROWSER_EXPORT QuotaReservationManager {
+ public:
+ // Callback for ReserveQuota. When this callback returns false, ReserveQuota
+ // operation should be reverted.
+ typedef base::Callback<bool(base::PlatformFileError error)>
+ ReserveQuotaCallback;
+
+ // An abstraction of backing quota system.
+ class WEBKIT_STORAGE_BROWSER_EXPORT QuotaBackend {
+ public:
+ QuotaBackend() {}
+ virtual ~QuotaBackend() {}
+
+ // Reserves or reclaims |delta| of quota for |origin| and |type| pair.
+ // Reserved quota should be counted as usage, but it should be on-memory
+ // and be cleared by a browser restart.
+ // Invokes |callback| upon completion with an error code.
+ // |callback| should return false if it can't accept the reservation, in
+ // that case, the backend should roll back the reservation.
+ virtual void ReserveQuota(const GURL& origin,
+ FileSystemType type,
+ int64 delta,
+ const ReserveQuotaCallback& callback) = 0;
+
+ // Reclaims |size| of quota for |origin| and |type|.
+ virtual void ReleaseReservedQuota(const GURL& origin,
+ FileSystemType type,
+ int64 size) = 0;
+
+ // Updates disk usage of |origin| and |type|.
+ // Invokes |callback| upon completion with an error code.
+ virtual void CommitQuotaUsage(const GURL& origin,
+ FileSystemType type,
+ int64 delta) = 0;
+
+ virtual void IncrementDirtyCount(const GURL& origin,
+ FileSystemType type) = 0;
+ virtual void DecrementDirtyCount(const GURL& origin,
+ FileSystemType type) = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(QuotaBackend);
+ };
+
+ explicit QuotaReservationManager(scoped_ptr<QuotaBackend> backend);
+ ~QuotaReservationManager();
+
+ // The entry point of the quota reservation. Creates new reservation object
+ // for |origin| and |type|.
+ scoped_refptr<QuotaReservation> CreateReservation(
+ const GURL& origin,
+ FileSystemType type);
+
+ private:
+ typedef std::map<std::pair<GURL, FileSystemType>, QuotaReservationBuffer*>
+ ReservationBufferByOriginAndType;
+
+ friend class QuotaReservation;
+ friend class QuotaReservationBuffer;
+ friend class QuotaReservationManagerTest;
+
+ void ReserveQuota(const GURL& origin,
+ FileSystemType type,
+ int64 delta,
+ const ReserveQuotaCallback& callback);
+
+ void ReleaseReservedQuota(const GURL& origin,
+ FileSystemType type,
+ int64 size);
+
+ void CommitQuotaUsage(const GURL& origin,
+ FileSystemType type,
+ int64 delta);
+
+ void IncrementDirtyCount(const GURL& origin, FileSystemType type);
+ void DecrementDirtyCount(const GURL& origin, FileSystemType type);
+
+ scoped_refptr<QuotaReservationBuffer> GetReservationBuffer(
+ const GURL& origin,
+ FileSystemType type);
+ void ReleaseReservationBuffer(QuotaReservationBuffer* reservation_pool);
+
+ scoped_ptr<QuotaBackend> backend_;
+
+ // Not owned. The destructor of ReservationBuffer should erase itself from
+ // |reservation_buffers_| by calling ReleaseReservationBuffer.
+ ReservationBufferByOriginAndType reservation_buffers_;
+
+ base::SequenceChecker sequence_checker_;
+ base::WeakPtrFactory<QuotaReservationManager> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(QuotaReservationManager);
+};
+
+} // namespace fileapi
+
+#endif // WEBKIT_BROWSER_FILEAPI_QUOTA_QUOTA_RESERVATION_MANAGER_H_
diff --git a/chromium/webkit/browser/fileapi/quota/quota_reservation_manager_unittest.cc b/chromium/webkit/browser/fileapi/quota/quota_reservation_manager_unittest.cc
new file mode 100644
index 00000000000..6cdc062d16a
--- /dev/null
+++ b/chromium/webkit/browser/fileapi/quota/quota_reservation_manager_unittest.cc
@@ -0,0 +1,358 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "webkit/browser/fileapi/quota/quota_reservation_manager.h"
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/file_util.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "webkit/browser/fileapi/quota/open_file_handle.h"
+#include "webkit/browser/fileapi/quota/quota_reservation.h"
+
+namespace fileapi {
+
+namespace {
+
+const char kOrigin[] = "http://example.com";
+const FileSystemType kType = kFileSystemTypeTemporary;
+const int64 kInitialFileSize = 30;
+
+typedef QuotaReservationManager::ReserveQuotaCallback ReserveQuotaCallback;
+
+class FakeBackend : public QuotaReservationManager::QuotaBackend {
+ public:
+ FakeBackend()
+ : on_memory_usage_(0),
+ on_disk_usage_(0) {}
+ virtual ~FakeBackend() {}
+
+ virtual void ReserveQuota(const GURL& origin,
+ FileSystemType type,
+ int64 delta,
+ const ReserveQuotaCallback& callback) OVERRIDE {
+ EXPECT_EQ(GURL(kOrigin), origin);
+ EXPECT_EQ(kType, type);
+ on_memory_usage_ += delta;
+ base::MessageLoopProxy::current()->PostTask(
+ FROM_HERE,
+ base::Bind(base::IgnoreResult(callback), base::PLATFORM_FILE_OK));
+ }
+
+ virtual void ReleaseReservedQuota(const GURL& origin,
+ FileSystemType type,
+ int64 size) OVERRIDE {
+ EXPECT_LE(0, size);
+ EXPECT_EQ(GURL(kOrigin), origin);
+ EXPECT_EQ(kType, type);
+ on_memory_usage_ -= size;
+ }
+
+ virtual void CommitQuotaUsage(const GURL& origin,
+ FileSystemType type,
+ int64 delta) OVERRIDE {
+ EXPECT_EQ(GURL(kOrigin), origin);
+ EXPECT_EQ(kType, type);
+ on_disk_usage_ += delta;
+ }
+
+ virtual void IncrementDirtyCount(const GURL& origin,
+ FileSystemType type) OVERRIDE {}
+ virtual void DecrementDirtyCount(const GURL& origin,
+ FileSystemType type) OVERRIDE {}
+
+ int64 on_memory_usage() { return on_memory_usage_; }
+ int64 on_disk_usage() { return on_disk_usage_; }
+
+ private:
+ int64 on_memory_usage_;
+ int64 on_disk_usage_;
+
+ DISALLOW_COPY_AND_ASSIGN(FakeBackend);
+};
+
+void ExpectSuccess(bool* done, base::PlatformFileError error) {
+ EXPECT_FALSE(*done);
+ *done = true;
+ EXPECT_EQ(base::PLATFORM_FILE_OK, error);
+}
+
+void RefreshQuota(QuotaReservation* reservation, int64 size) {
+ DCHECK(reservation);
+
+ bool done = false;
+ reservation->RefreshReservation(size, base::Bind(&ExpectSuccess, &done));
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(done);
+}
+
+} // namespace
+
+class QuotaReservationManagerTest : public testing::Test {
+ public:
+ QuotaReservationManagerTest() {}
+ virtual ~QuotaReservationManagerTest() {}
+
+ virtual void SetUp() OVERRIDE {
+ ASSERT_TRUE(work_dir_.CreateUniqueTempDir());
+ file_path_ = work_dir_.path().Append(FILE_PATH_LITERAL("hoge"));
+ SetFileSize(kInitialFileSize);
+
+ scoped_ptr<QuotaReservationManager::QuotaBackend> backend(new FakeBackend);
+ reservation_manager_.reset(new QuotaReservationManager(backend.Pass()));
+ }
+
+ virtual void TearDown() OVERRIDE {
+ reservation_manager_.reset();
+ }
+
+ int64 GetFileSize() {
+ int64 size = 0;
+ base::GetFileSize(file_path_, &size);
+ return size;
+ }
+
+ void SetFileSize(int64 size) {
+ bool created = false;
+ base::PlatformFileError error = base::PLATFORM_FILE_ERROR_FAILED;
+ base::PlatformFile file = CreatePlatformFile(
+ file_path_,
+ base::PLATFORM_FILE_OPEN_ALWAYS | base::PLATFORM_FILE_WRITE,
+ &created, &error);
+ ASSERT_EQ(base::PLATFORM_FILE_OK, error);
+ ASSERT_TRUE(base::TruncatePlatformFile(file, size));
+ ASSERT_TRUE(base::ClosePlatformFile(file));
+ }
+
+ void ExtendFileTo(int64 size) {
+ if (GetFileSize() < size)
+ SetFileSize(size);
+ }
+
+ FakeBackend* fake_backend() {
+ return static_cast<FakeBackend*>(reservation_manager_->backend_.get());
+ }
+
+ QuotaReservationManager* reservation_manager() {
+ return reservation_manager_.get();
+ }
+
+ const base::FilePath& file_path() const {
+ return file_path_;
+ }
+
+ private:
+ base::MessageLoop message_loop_;
+ base::ScopedTempDir work_dir_;
+ base::FilePath file_path_;
+ scoped_ptr<QuotaReservationManager> reservation_manager_;
+
+ DISALLOW_COPY_AND_ASSIGN(QuotaReservationManagerTest);
+};
+
+TEST_F(QuotaReservationManagerTest, BasicTest) {
+ GURL origin(kOrigin);
+ FileSystemType type = kType;
+
+ // Create Reservation channel for the origin and type.
+ // Reservation holds remaining quota reservation and provides a method to
+ // refresh it.
+ scoped_refptr<QuotaReservation> reservation =
+ reservation_manager()->CreateReservation(origin, type);
+ EXPECT_EQ(0, reservation->remaining_quota());
+
+ RefreshQuota(reservation, 100);
+ EXPECT_EQ(100, reservation->remaining_quota());
+
+ {
+ // For each open file for write, the client should create OpenFileHandle
+ // object.
+ // It's OK to create multiple OpenFileHandle for single file.
+ scoped_ptr<OpenFileHandle> open_file =
+ reservation->GetOpenFileHandle(file_path());
+
+ // Before reserved quota ran out, the client can perform any number of
+ // operation for the file.
+ // The client should calculate how much quota is consumed by itself.
+ int64 remaining_quota = reservation->remaining_quota();
+ int64 base_file_size = open_file->base_file_size();
+ int64 max_written_offset = base_file_size;
+ ExtendFileTo(90);
+ max_written_offset = 90;
+ remaining_quota -= max_written_offset - base_file_size;
+
+ // When the reserved quota ran out, the client can request quota refresh
+ // through Reservation. Before requesting another portion of quota, the
+ // client should report maximum written offset for each modified files.
+ open_file->UpdateMaxWrittenOffset(max_written_offset);
+ EXPECT_EQ(remaining_quota, reservation->remaining_quota());
+
+ RefreshQuota(reservation, 100);
+ EXPECT_EQ(100, reservation->remaining_quota());
+ }
+
+ EXPECT_EQ(90, GetFileSize());
+ EXPECT_EQ(100, fake_backend()->on_memory_usage());
+ EXPECT_EQ(90 - kInitialFileSize, fake_backend()->on_disk_usage());
+
+ reservation = NULL;
+
+ EXPECT_EQ(90, GetFileSize());
+ EXPECT_EQ(0, fake_backend()->on_memory_usage());
+ EXPECT_EQ(90 - kInitialFileSize, fake_backend()->on_disk_usage());
+}
+
+TEST_F(QuotaReservationManagerTest, MultipleWriter) {
+ GURL origin(kOrigin);
+ FileSystemType type = kType;
+
+ scoped_refptr<QuotaReservation> reservation =
+ reservation_manager()->CreateReservation(origin, type);
+ EXPECT_EQ(0, reservation->remaining_quota());
+
+ RefreshQuota(reservation, 100);
+ EXPECT_EQ(100, reservation->remaining_quota());
+
+ {
+ scoped_ptr<OpenFileHandle> open_file1 =
+ reservation->GetOpenFileHandle(file_path());
+ scoped_ptr<OpenFileHandle> open_file2 =
+ reservation->GetOpenFileHandle(file_path());
+
+ int64 remaining_quota = reservation->remaining_quota();
+
+ int64 base_file_size_for_file1 = open_file1->base_file_size();
+ int64 max_written_offset_for_file1 = base_file_size_for_file1;
+
+ int64 base_file_size_for_file2 = open_file2->base_file_size();
+ int64 max_written_offset_for_file2 = base_file_size_for_file2;
+
+ // Each writer should maintain max_written_offset and base_file_size
+ // independently even if there are multiple writers for the same file.
+ max_written_offset_for_file1 = 50;
+ ExtendFileTo(max_written_offset_for_file1);
+ remaining_quota -= max_written_offset_for_file1 - base_file_size_for_file1;
+ base_file_size_for_file1 = max_written_offset_for_file1;
+
+ max_written_offset_for_file2 = 90;
+ ExtendFileTo(max_written_offset_for_file2);
+ remaining_quota -= max_written_offset_for_file2 - base_file_size_for_file2;
+ base_file_size_for_file2 = max_written_offset_for_file2;
+
+ // Before requesting quota refresh, each writer should report their
+ // maximum_written_offset. UpdateMaxWrittenOffset returns updated
+ // base_file_size that the writer should calculate quota consumption based
+ // on that.
+ base_file_size_for_file1 =
+ open_file1->UpdateMaxWrittenOffset(max_written_offset_for_file1);
+ max_written_offset_for_file1 = base_file_size_for_file1;
+ EXPECT_EQ(100 - (50 - kInitialFileSize), reservation->remaining_quota());
+
+ base_file_size_for_file2 =
+ open_file2->UpdateMaxWrittenOffset(max_written_offset_for_file2);
+ max_written_offset_for_file2 = base_file_size_for_file2;
+ EXPECT_EQ(100 - (50 - kInitialFileSize) - (90 - 50),
+ reservation->remaining_quota());
+
+ RefreshQuota(reservation, 100);
+ EXPECT_EQ(100, reservation->remaining_quota());
+ }
+
+ EXPECT_EQ(90, GetFileSize());
+ EXPECT_EQ(100, fake_backend()->on_memory_usage());
+ EXPECT_EQ(90 - kInitialFileSize, fake_backend()->on_disk_usage());
+
+ reservation = NULL;
+
+ EXPECT_EQ(90, GetFileSize());
+ EXPECT_EQ(0, fake_backend()->on_memory_usage());
+ EXPECT_EQ(90 - kInitialFileSize, fake_backend()->on_disk_usage());
+}
+
+TEST_F(QuotaReservationManagerTest, MultipleClient) {
+ GURL origin(kOrigin);
+ FileSystemType type = kType;
+
+ scoped_refptr<QuotaReservation> reservation1 =
+ reservation_manager()->CreateReservation(origin, type);
+ EXPECT_EQ(0, reservation1->remaining_quota());
+ RefreshQuota(reservation1, 100);
+ EXPECT_EQ(100, reservation1->remaining_quota());
+
+ scoped_refptr<QuotaReservation> reservation2 =
+ reservation_manager()->CreateReservation(origin, type);
+ EXPECT_EQ(0, reservation2->remaining_quota());
+ RefreshQuota(reservation2, 500);
+ EXPECT_EQ(500, reservation2->remaining_quota());
+
+ // Attach a file to both of two reservations.
+ scoped_ptr<OpenFileHandle> open_file1 =
+ reservation1->GetOpenFileHandle(file_path());
+ scoped_ptr<OpenFileHandle> open_file2 =
+ reservation2->GetOpenFileHandle(file_path());
+
+ // Each client should manage reserved quota and its consumption separately.
+ int64 remaining_quota1 = reservation1->remaining_quota();
+ int64 base_file_size1 = open_file1->base_file_size();
+ int64 max_written_offset1 = base_file_size1;
+
+ int64 remaining_quota2 = reservation2->remaining_quota();
+ int64 base_file_size2 = open_file2->base_file_size();
+ int64 max_written_offset2 = base_file_size2;
+
+ max_written_offset1 = 50;
+ remaining_quota1 -= max_written_offset1 - base_file_size1;
+ base_file_size1 = max_written_offset1;
+ ExtendFileTo(max_written_offset1);
+
+ max_written_offset2 = 400;
+ remaining_quota2 -= max_written_offset2 - base_file_size2;
+ base_file_size2 = max_written_offset2;
+ ExtendFileTo(max_written_offset2);
+
+ // For multiple Reservation case, RefreshQuota needs usage report only from
+ // associated OpenFile's.
+ base_file_size1 =
+ open_file1->UpdateMaxWrittenOffset(max_written_offset1);
+ max_written_offset1 = base_file_size1;
+ EXPECT_EQ(100 - (50 - kInitialFileSize), reservation1->remaining_quota());
+
+ RefreshQuota(reservation1, 200);
+ EXPECT_EQ(200, reservation1->remaining_quota());
+
+ base_file_size2 =
+ open_file2->UpdateMaxWrittenOffset(max_written_offset2);
+ max_written_offset2 = base_file_size2;
+ EXPECT_EQ(500 - (400 - 50), reservation2->remaining_quota());
+
+ RefreshQuota(reservation2, 150);
+ EXPECT_EQ(150, reservation2->remaining_quota());
+
+ open_file1.reset();
+ open_file2.reset();
+
+ EXPECT_EQ(400, GetFileSize());
+ EXPECT_EQ(200 + 150, fake_backend()->on_memory_usage());
+ EXPECT_EQ(400 - kInitialFileSize, fake_backend()->on_disk_usage());
+
+ reservation1 = NULL;
+
+ EXPECT_EQ(400, GetFileSize());
+ EXPECT_EQ(150, fake_backend()->on_memory_usage());
+ EXPECT_EQ(400 - kInitialFileSize, fake_backend()->on_disk_usage());
+
+ reservation2 = NULL;
+
+ EXPECT_EQ(400, GetFileSize());
+ EXPECT_EQ(0, fake_backend()->on_memory_usage());
+ EXPECT_EQ(400 - kInitialFileSize, fake_backend()->on_disk_usage());
+}
+
+// TODO(tzik): Add Truncate test.
+// TODO(tzik): Add PluginCrash test and DropReservationManager test.
+
+} // namespace fileapi
diff --git a/chromium/webkit/browser/fileapi/recursive_operation_delegate.cc b/chromium/webkit/browser/fileapi/recursive_operation_delegate.cc
index 81f26ff1c71..7adc59680b0 100644
--- a/chromium/webkit/browser/fileapi/recursive_operation_delegate.cc
+++ b/chromium/webkit/browser/fileapi/recursive_operation_delegate.cc
@@ -27,6 +27,7 @@ RecursiveOperationDelegate::~RecursiveOperationDelegate() {
void RecursiveOperationDelegate::Cancel() {
canceled_ = true;
+ OnCancel();
}
void RecursiveOperationDelegate::StartRecursiveOperation(
@@ -48,6 +49,9 @@ FileSystemOperationRunner* RecursiveOperationDelegate::operation_runner() {
return file_system_context_->operation_runner();
}
+void RecursiveOperationDelegate::OnCancel() {
+}
+
void RecursiveOperationDelegate::DidTryProcessFile(
const FileSystemURL& root,
base::PlatformFileError error) {
diff --git a/chromium/webkit/browser/fileapi/recursive_operation_delegate.h b/chromium/webkit/browser/fileapi/recursive_operation_delegate.h
index a5266777341..08e30507bce 100644
--- a/chromium/webkit/browser/fileapi/recursive_operation_delegate.h
+++ b/chromium/webkit/browser/fileapi/recursive_operation_delegate.h
@@ -115,6 +115,10 @@ class WEBKIT_STORAGE_BROWSER_EXPORT RecursiveOperationDelegate
FileSystemOperationRunner* operation_runner();
+ // Called when Cancel() is called. This is a hook to do something more
+ // in a derived class. By default, do nothing.
+ virtual void OnCancel();
+
private:
void DidTryProcessFile(const FileSystemURL& root,
base::PlatformFileError error);
diff --git a/chromium/webkit/browser/fileapi/recursive_operation_delegate_unittest.cc b/chromium/webkit/browser/fileapi/recursive_operation_delegate_unittest.cc
deleted file mode 100644
index b3842279420..00000000000
--- a/chromium/webkit/browser/fileapi/recursive_operation_delegate_unittest.cc
+++ /dev/null
@@ -1,280 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "webkit/browser/fileapi/recursive_operation_delegate.h"
-
-#include <vector>
-
-#include "base/basictypes.h"
-#include "base/bind.h"
-#include "base/callback.h"
-#include "base/files/scoped_temp_dir.h"
-#include "base/message_loop/message_loop.h"
-#include "base/message_loop/message_loop_proxy.h"
-#include "base/run_loop.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "webkit/browser/fileapi/file_system_file_util.h"
-#include "webkit/browser/fileapi/file_system_operation.h"
-#include "webkit/browser/fileapi/file_system_operation_runner.h"
-#include "webkit/browser/fileapi/sandbox_file_system_test_helper.h"
-
-namespace fileapi {
-namespace {
-
-class LoggingRecursiveOperation : public RecursiveOperationDelegate {
- public:
- struct LogEntry {
- enum Type {
- PROCESS_FILE,
- PROCESS_DIRECTORY,
- POST_PROCESS_DIRECTORY
- };
- Type type;
- FileSystemURL url;
- };
-
- LoggingRecursiveOperation(FileSystemContext* file_system_context,
- const FileSystemURL& root,
- const StatusCallback& callback)
- : RecursiveOperationDelegate(file_system_context),
- root_(root),
- callback_(callback),
- weak_factory_(this) {
- }
- virtual ~LoggingRecursiveOperation() {}
-
- const std::vector<LogEntry>& log_entries() const { return log_entries_; }
-
- // RecursiveOperationDelegate overrides.
- virtual void Run() OVERRIDE {
- NOTREACHED();
- }
-
- virtual void RunRecursively() OVERRIDE {
- StartRecursiveOperation(root_, callback_);
- }
-
- virtual void ProcessFile(const FileSystemURL& url,
- const StatusCallback& callback) OVERRIDE {
- RecordLogEntry(LogEntry::PROCESS_FILE, url);
- operation_runner()->GetMetadata(
- url,
- base::Bind(&LoggingRecursiveOperation::DidGetMetadata,
- weak_factory_.GetWeakPtr(), callback));
- }
-
- virtual void ProcessDirectory(const FileSystemURL& url,
- const StatusCallback& callback) OVERRIDE {
- RecordLogEntry(LogEntry::PROCESS_DIRECTORY, url);
- callback.Run(base::PLATFORM_FILE_OK);
- }
-
- virtual void PostProcessDirectory(const FileSystemURL& url,
- const StatusCallback& callback) OVERRIDE {
- RecordLogEntry(LogEntry::POST_PROCESS_DIRECTORY, url);
- callback.Run(base::PLATFORM_FILE_OK);
- }
-
- private:
- void RecordLogEntry(LogEntry::Type type, const FileSystemURL& url) {
- LogEntry entry;
- entry.type = type;
- entry.url = url;
- log_entries_.push_back(entry);
- }
-
- void DidGetMetadata(const StatusCallback& callback,
- base::PlatformFileError result,
- const base::PlatformFileInfo& file_info) {
- if (result != base::PLATFORM_FILE_OK) {
- callback.Run(result);
- return;
- }
-
- callback.Run(file_info.is_directory ?
- base::PLATFORM_FILE_ERROR_NOT_A_FILE :
- base::PLATFORM_FILE_OK);
- }
-
- FileSystemURL root_;
- StatusCallback callback_;
- std::vector<LogEntry> log_entries_;
-
- base::WeakPtrFactory<LoggingRecursiveOperation> weak_factory_;
- DISALLOW_COPY_AND_ASSIGN(LoggingRecursiveOperation);
-};
-
-void ReportStatus(base::PlatformFileError* out_error,
- base::PlatformFileError error) {
- DCHECK(out_error);
- *out_error = error;
-}
-
-// To test the Cancel() during operation, calls Cancel() of |operation|
-// after |counter| times message posting.
-void CallCancelLater(RecursiveOperationDelegate* operation, int counter) {
- if (counter > 0) {
- base::MessageLoopProxy::current()->PostTask(
- FROM_HERE,
- base::Bind(&CallCancelLater, base::Unretained(operation), counter - 1));
- return;
- }
-
- operation->Cancel();
-}
-
-} // namespace
-
-class RecursiveOperationDelegateTest : public testing::Test {
- protected:
- virtual void SetUp() OVERRIDE {
- EXPECT_TRUE(base_.CreateUniqueTempDir());
- sandbox_file_system_.SetUp(base_.path().AppendASCII("filesystem"));
- }
-
- virtual void TearDown() OVERRIDE {
- sandbox_file_system_.TearDown();
- }
-
- scoped_ptr<FileSystemOperationContext> NewContext() {
- FileSystemOperationContext* context =
- sandbox_file_system_.NewOperationContext();
- // Grant enough quota for all test cases.
- context->set_allowed_bytes_growth(1000000);
- return make_scoped_ptr(context);
- }
-
- FileSystemFileUtil* file_util() {
- return sandbox_file_system_.file_util();
- }
-
- FileSystemURL URLForPath(const std::string& path) const {
- return sandbox_file_system_.CreateURLFromUTF8(path);
- }
-
- FileSystemURL CreateFile(const std::string& path) {
- FileSystemURL url = URLForPath(path);
- bool created = false;
- EXPECT_EQ(base::PLATFORM_FILE_OK,
- file_util()->EnsureFileExists(NewContext().get(),
- url, &created));
- EXPECT_TRUE(created);
- return url;
- }
-
- FileSystemURL CreateDirectory(const std::string& path) {
- FileSystemURL url = URLForPath(path);
- EXPECT_EQ(base::PLATFORM_FILE_OK,
- file_util()->CreateDirectory(NewContext().get(), url,
- false /* exclusive */, true));
- return url;
- }
-
- private:
- base::MessageLoop message_loop_;
-
- // Common temp base for nondestructive uses.
- base::ScopedTempDir base_;
- SandboxFileSystemTestHelper sandbox_file_system_;
-};
-
-TEST_F(RecursiveOperationDelegateTest, RootIsFile) {
- FileSystemURL src_file(CreateFile("src"));
-
- base::PlatformFileError error = base::PLATFORM_FILE_ERROR_FAILED;
- scoped_ptr<FileSystemOperationContext> context = NewContext();
- scoped_ptr<LoggingRecursiveOperation> operation(
- new LoggingRecursiveOperation(
- context->file_system_context(), src_file,
- base::Bind(&ReportStatus, &error)));
- operation->RunRecursively();
- base::RunLoop().RunUntilIdle();
- ASSERT_EQ(base::PLATFORM_FILE_OK, error);
-
- const std::vector<LoggingRecursiveOperation::LogEntry>& log_entries =
- operation->log_entries();
- ASSERT_EQ(1U, log_entries.size());
- const LoggingRecursiveOperation::LogEntry& entry = log_entries[0];
- EXPECT_EQ(LoggingRecursiveOperation::LogEntry::PROCESS_FILE, entry.type);
- EXPECT_EQ(src_file, entry.url);
-}
-
-TEST_F(RecursiveOperationDelegateTest, RootIsDirectory) {
- FileSystemURL src_root(CreateDirectory("src"));
- FileSystemURL src_dir1(CreateDirectory("src/dir1"));
- FileSystemURL src_file1(CreateFile("src/file1"));
- FileSystemURL src_file2(CreateFile("src/dir1/file2"));
- FileSystemURL src_file3(CreateFile("src/dir1/file3"));
-
- base::PlatformFileError error = base::PLATFORM_FILE_ERROR_FAILED;
- scoped_ptr<FileSystemOperationContext> context = NewContext();
- scoped_ptr<LoggingRecursiveOperation> operation(
- new LoggingRecursiveOperation(
- context->file_system_context(), src_root,
- base::Bind(&ReportStatus, &error)));
- operation->RunRecursively();
- base::RunLoop().RunUntilIdle();
- ASSERT_EQ(base::PLATFORM_FILE_OK, error);
-
- const std::vector<LoggingRecursiveOperation::LogEntry>& log_entries =
- operation->log_entries();
- ASSERT_EQ(8U, log_entries.size());
-
- EXPECT_EQ(LoggingRecursiveOperation::LogEntry::PROCESS_FILE,
- log_entries[0].type);
- EXPECT_EQ(src_root, log_entries[0].url);
-
- EXPECT_EQ(LoggingRecursiveOperation::LogEntry::PROCESS_DIRECTORY,
- log_entries[1].type);
- EXPECT_EQ(src_root, log_entries[1].url);
-
- EXPECT_EQ(LoggingRecursiveOperation::LogEntry::PROCESS_FILE,
- log_entries[2].type);
- EXPECT_EQ(src_file1, log_entries[2].url);
-
- EXPECT_EQ(LoggingRecursiveOperation::LogEntry::PROCESS_DIRECTORY,
- log_entries[3].type);
- EXPECT_EQ(src_dir1, log_entries[3].url);
-
- // The order of src/dir1/file2 and src/dir1/file3 depends on the file system
- // implementation (can be swapped).
- EXPECT_EQ(LoggingRecursiveOperation::LogEntry::PROCESS_FILE,
- log_entries[4].type);
- EXPECT_EQ(LoggingRecursiveOperation::LogEntry::PROCESS_FILE,
- log_entries[5].type);
- EXPECT_TRUE((src_file2 == log_entries[4].url &&
- src_file3 == log_entries[5].url) ||
- (src_file3 == log_entries[4].url &&
- src_file2 == log_entries[5].url));
-
- EXPECT_EQ(LoggingRecursiveOperation::LogEntry::POST_PROCESS_DIRECTORY,
- log_entries[6].type);
- EXPECT_EQ(src_dir1, log_entries[6].url);
-
- EXPECT_EQ(LoggingRecursiveOperation::LogEntry::POST_PROCESS_DIRECTORY,
- log_entries[7].type);
- EXPECT_EQ(src_root, log_entries[7].url);
-}
-
-TEST_F(RecursiveOperationDelegateTest, Cancel) {
- FileSystemURL src_root(CreateDirectory("src"));
- FileSystemURL src_dir1(CreateDirectory("src/dir1"));
- FileSystemURL src_file1(CreateFile("src/file1"));
- FileSystemURL src_file2(CreateFile("src/dir1/file2"));
-
- base::PlatformFileError error = base::PLATFORM_FILE_ERROR_FAILED;
- scoped_ptr<FileSystemOperationContext> context = NewContext();
- scoped_ptr<LoggingRecursiveOperation> operation(
- new LoggingRecursiveOperation(
- context->file_system_context(), src_root,
- base::Bind(&ReportStatus, &error)));
- operation->RunRecursively();
-
- // Invoke Cancel(), after 5 times message posting.
- CallCancelLater(operation.get(), 5);
- base::RunLoop().RunUntilIdle();
- ASSERT_EQ(base::PLATFORM_FILE_ERROR_ABORT, error);
-}
-
-} // namespace fileapi
diff --git a/chromium/webkit/browser/fileapi/sandbox_database_test_helper.cc b/chromium/webkit/browser/fileapi/sandbox_database_test_helper.cc
index 6364b2bd7f5..5c9176c0878 100644
--- a/chromium/webkit/browser/fileapi/sandbox_database_test_helper.cc
+++ b/chromium/webkit/browser/fileapi/sandbox_database_test_helper.cc
@@ -94,7 +94,6 @@ void DeleteDatabaseFile(const base::FilePath& db_path,
// We may have multiple files for the same type, so don't break here.
}
}
-
}
} // namespace fileapi
diff --git a/chromium/webkit/browser/fileapi/sandbox_directory_database.cc b/chromium/webkit/browser/fileapi/sandbox_directory_database.cc
index 06ab1e50acf..dd376116eef 100644
--- a/chromium/webkit/browser/fileapi/sandbox_directory_database.cc
+++ b/chromium/webkit/browser/fileapi/sandbox_directory_database.cc
@@ -244,7 +244,7 @@ bool DatabaseCheckHelper::ScanDatabase() {
// Ensure the backing file exists as a normal file.
base::PlatformFileInfo platform_file_info;
- if (!file_util::GetFileInfo(
+ if (!base::GetFileInfo(
path_.Append(file_info.data_path), &platform_file_info) ||
platform_file_info.is_directory ||
platform_file_info.is_symbolic_link) {
@@ -536,8 +536,10 @@ base::PlatformFileError SandboxDirectoryDatabase::AddFileInfo(
return base::PLATFORM_FILE_ERROR_NOT_FOUND;
}
- if (!VerifyIsDirectory(info.parent_id))
+ if (!IsDirectory(info.parent_id)) {
+ LOG(ERROR) << "New parent directory is a file!";
return base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY;
+ }
// This would be a fine place to limit the number of files in a directory, if
// we decide to add that restriction.
@@ -586,7 +588,7 @@ bool SandboxDirectoryDatabase::UpdateFileInfo(
if (!GetFileInfo(file_id, &old_info))
return false;
if (old_info.parent_id != new_info.parent_id &&
- !VerifyIsDirectory(new_info.parent_id))
+ !IsDirectory(new_info.parent_id))
return false;
if (old_info.parent_id != new_info.parent_id ||
old_info.name != new_info.name) {
@@ -751,7 +753,7 @@ bool SandboxDirectoryDatabase::Init(RecoveryOption recovery_option) {
LOG(WARNING) << "Clearing SandboxDirectoryDatabase.";
if (!base::DeleteFile(filesystem_data_directory_, true))
return false;
- if (!file_util::CreateDirectory(filesystem_data_directory_))
+ if (!base::CreateDirectory(filesystem_data_directory_))
return false;
return Init(FAIL_ON_CORRUPTION);
}
@@ -774,6 +776,17 @@ bool SandboxDirectoryDatabase::RepairDatabase(const std::string& db_path) {
return false;
}
+bool SandboxDirectoryDatabase::IsDirectory(FileId file_id) {
+ FileInfo info;
+ if (!file_id)
+ return true; // The root is a directory.
+ if (!GetFileInfo(file_id, &info))
+ return false;
+ if (!info.is_directory())
+ return false;
+ return true;
+}
+
bool SandboxDirectoryDatabase::IsFileSystemConsistent() {
if (!Init(FAIL_ON_CORRUPTION))
return false;
@@ -856,19 +869,6 @@ bool SandboxDirectoryDatabase::GetLastFileId(FileId* file_id) {
return true;
}
-bool SandboxDirectoryDatabase::VerifyIsDirectory(FileId file_id) {
- FileInfo info;
- if (!file_id)
- return true; // The root is a directory.
- if (!GetFileInfo(file_id, &info))
- return false;
- if (!info.is_directory()) {
- LOG(ERROR) << "New parent directory is a file!";
- return false;
- }
- return true;
-}
-
// This does very few safety checks!
bool SandboxDirectoryDatabase::AddFileInfoHelper(
const FileInfo& info, FileId file_id, leveldb::WriteBatch* batch) {
diff --git a/chromium/webkit/browser/fileapi/sandbox_directory_database.h b/chromium/webkit/browser/fileapi/sandbox_directory_database.h
index 0ad948d630f..67be4328781 100644
--- a/chromium/webkit/browser/fileapi/sandbox_directory_database.h
+++ b/chromium/webkit/browser/fileapi/sandbox_directory_database.h
@@ -88,6 +88,8 @@ class WEBKIT_STORAGE_BROWSER_EXPORT_PRIVATE SandboxDirectoryDatabase {
// creation/destruction of SandboxDirectoryDatabase objects.
bool GetNextInteger(int64* next);
+ bool IsDirectory(FileId file_id);
+
// Returns true if the database looks consistent with local filesystem.
bool IsFileSystemConsistent();
@@ -108,7 +110,6 @@ class WEBKIT_STORAGE_BROWSER_EXPORT_PRIVATE SandboxDirectoryDatabase {
void ReportInitStatus(const leveldb::Status& status);
bool StoreDefaultValues();
bool GetLastFileId(FileId* file_id);
- bool VerifyIsDirectory(FileId file_id);
bool AddFileInfoHelper(
const FileInfo& info, FileId file_id, leveldb::WriteBatch* batch);
bool RemoveFileInfoHelper(FileId file_id, leveldb::WriteBatch* batch);
diff --git a/chromium/webkit/browser/fileapi/sandbox_directory_database_unittest.cc b/chromium/webkit/browser/fileapi/sandbox_directory_database_unittest.cc
index 9281446e2fd..b43dc23ee74 100644
--- a/chromium/webkit/browser/fileapi/sandbox_directory_database_unittest.cc
+++ b/chromium/webkit/browser/fileapi/sandbox_directory_database_unittest.cc
@@ -83,7 +83,7 @@ class SandboxDirectoryDatabaseTest : public testing::Test {
base::FilePath local_path = path().Append(data_path);
if (!base::DirectoryExists(local_path.DirName()))
- ASSERT_TRUE(file_util::CreateDirectory(local_path.DirName()));
+ ASSERT_TRUE(base::CreateDirectory(local_path.DirName()));
bool created = false;
base::PlatformFileError error = base::PLATFORM_FILE_ERROR_FAILED;
@@ -102,7 +102,7 @@ class SandboxDirectoryDatabaseTest : public testing::Test {
void ClearDatabaseAndDirectory() {
db_.reset();
ASSERT_TRUE(base::DeleteFile(path(), true /* recursive */));
- ASSERT_TRUE(file_util::CreateDirectory(path()));
+ ASSERT_TRUE(base::CreateDirectory(path()));
db_.reset(new SandboxDirectoryDatabase(path()));
}
@@ -141,6 +141,7 @@ class SandboxDirectoryDatabaseTest : public testing::Test {
base::ScopedTempDir base_;
scoped_ptr<SandboxDirectoryDatabase> db_;
+ private:
DISALLOW_COPY_AND_ASSIGN(SandboxDirectoryDatabaseTest);
};
diff --git a/chromium/webkit/browser/fileapi/sandbox_file_system_backend.cc b/chromium/webkit/browser/fileapi/sandbox_file_system_backend.cc
index a5adc63e85d..cc022788aa4 100644
--- a/chromium/webkit/browser/fileapi/sandbox_file_system_backend.cc
+++ b/chromium/webkit/browser/fileapi/sandbox_file_system_backend.cc
@@ -49,18 +49,12 @@ void SandboxFileSystemBackend::Initialize(FileSystemContext* context) {
DCHECK(delegate_);
// Set quota observers.
- delegate_->AddFileUpdateObserver(
- fileapi::kFileSystemTypeTemporary,
- delegate_->quota_observer(),
- delegate_->file_task_runner());
+ delegate_->RegisterQuotaUpdateObserver(fileapi::kFileSystemTypeTemporary);
delegate_->AddFileAccessObserver(
fileapi::kFileSystemTypeTemporary,
delegate_->quota_observer(), NULL);
- delegate_->AddFileUpdateObserver(
- fileapi::kFileSystemTypePersistent,
- delegate_->quota_observer(),
- delegate_->file_task_runner());
+ delegate_->RegisterQuotaUpdateObserver(fileapi::kFileSystemTypePersistent);
delegate_->AddFileAccessObserver(
fileapi::kFileSystemTypePersistent,
delegate_->quota_observer(), NULL);
diff --git a/chromium/webkit/browser/fileapi/sandbox_file_system_backend_delegate.cc b/chromium/webkit/browser/fileapi/sandbox_file_system_backend_delegate.cc
index 1cb61bb3d60..bb4d48e41d1 100644
--- a/chromium/webkit/browser/fileapi/sandbox_file_system_backend_delegate.cc
+++ b/chromium/webkit/browser/fileapi/sandbox_file_system_backend_delegate.cc
@@ -4,6 +4,8 @@
#include "webkit/browser/fileapi/sandbox_file_system_backend_delegate.h"
+#include <vector>
+
#include "base/command_line.h"
#include "base/file_util.h"
#include "base/metrics/histogram.h"
@@ -17,6 +19,9 @@
#include "webkit/browser/fileapi/file_system_url.h"
#include "webkit/browser/fileapi/file_system_usage_cache.h"
#include "webkit/browser/fileapi/obfuscated_file_util.h"
+#include "webkit/browser/fileapi/quota/quota_backend_impl.h"
+#include "webkit/browser/fileapi/quota/quota_reservation.h"
+#include "webkit/browser/fileapi/quota/quota_reservation_manager.h"
#include "webkit/browser/fileapi/sandbox_file_stream_writer.h"
#include "webkit/browser/fileapi/sandbox_file_system_backend.h"
#include "webkit/browser/fileapi/sandbox_quota_observer.h"
@@ -36,6 +41,18 @@ const char kOpenFileSystemDetailNonThrottledLabel[] =
"FileSystem.OpenFileSystemDetailNonthrottled";
int64 kMinimumStatsCollectionIntervalHours = 1;
+// For type directory names in ObfuscatedFileUtil.
+// TODO(kinuko,nhiroki): Each type string registration should be done
+// via its own backend.
+const char kTemporaryDirectoryName[] = "t";
+const char kPersistentDirectoryName[] = "p";
+const char kSyncableDirectoryName[] = "s";
+
+const char* kPrepopulateTypes[] = {
+ kPersistentDirectoryName,
+ kTemporaryDirectoryName
+};
+
enum FileSystemError {
kOK = 0,
kIncognito,
@@ -57,6 +74,18 @@ const base::FilePath::CharType kRestrictedChars[] = {
FILE_PATH_LITERAL('/'), FILE_PATH_LITERAL('\\'),
};
+std::string GetTypeStringForURL(const FileSystemURL& url) {
+ return SandboxFileSystemBackendDelegate::GetTypeString(url.type());
+}
+
+std::set<std::string> GetKnownTypeStrings() {
+ std::set<std::string> known_type_strings;
+ known_type_strings.insert(kTemporaryDirectoryName);
+ known_type_strings.insert(kPersistentDirectoryName);
+ known_type_strings.insert(kSyncableDirectoryName);
+ return known_type_strings;
+}
+
class ObfuscatedOriginEnumerator
: public SandboxFileSystemBackendDelegate::OriginEnumerator {
public:
@@ -70,7 +99,8 @@ class ObfuscatedOriginEnumerator
}
virtual bool HasFileSystemType(FileSystemType type) const OVERRIDE {
- return enum_->HasFileSystemType(type);
+ return enum_->HasTypeDirectory(
+ SandboxFileSystemBackendDelegate::GetTypeString(type));
}
private:
@@ -85,7 +115,9 @@ void OpenFileSystemOnFileThread(
base::PlatformFileError* error_ptr) {
DCHECK(error_ptr);
const bool create = (mode == OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT);
- file_util->GetDirectoryForOriginAndType(origin_url, type, create, error_ptr);
+ file_util->GetDirectoryForOriginAndType(
+ origin_url, SandboxFileSystemBackendDelegate::GetTypeString(type),
+ create, error_ptr);
if (*error_ptr != base::PLATFORM_FILE_OK) {
UMA_HISTOGRAM_ENUMERATION(kOpenFileSystemLabel,
kCreateDirectoryError,
@@ -107,12 +139,36 @@ void DidOpenFileSystem(
callback.Run(*error);
}
+template <typename T>
+void DeleteSoon(base::SequencedTaskRunner* runner, T* ptr) {
+ if (!runner->DeleteSoon(FROM_HERE, ptr))
+ delete ptr;
+}
+
} // namespace
const base::FilePath::CharType
SandboxFileSystemBackendDelegate::kFileSystemDirectory[] =
FILE_PATH_LITERAL("File System");
+// static
+std::string SandboxFileSystemBackendDelegate::GetTypeString(
+ FileSystemType type) {
+ switch (type) {
+ case kFileSystemTypeTemporary:
+ return kTemporaryDirectoryName;
+ case kFileSystemTypePersistent:
+ return kPersistentDirectoryName;
+ case kFileSystemTypeSyncable:
+ case kFileSystemTypeSyncableForInternalSync:
+ return kSyncableDirectoryName;
+ case kFileSystemTypeUnknown:
+ default:
+ NOTREACHED() << "Unknown filesystem type requested:" << type;
+ return std::string();
+ }
+}
+
SandboxFileSystemBackendDelegate::SandboxFileSystemBackendDelegate(
quota::QuotaManagerProxy* quota_manager_proxy,
base::SequencedTaskRunner* file_task_runner,
@@ -124,83 +180,50 @@ SandboxFileSystemBackendDelegate::SandboxFileSystemBackendDelegate(
new ObfuscatedFileUtil(
special_storage_policy,
profile_path.Append(kFileSystemDirectory),
- file_task_runner))),
+ file_task_runner,
+ base::Bind(&GetTypeStringForURL),
+ GetKnownTypeStrings(),
+ this))),
file_system_usage_cache_(new FileSystemUsageCache(file_task_runner)),
quota_observer_(new SandboxQuotaObserver(
quota_manager_proxy,
file_task_runner,
obfuscated_file_util(),
usage_cache())),
+ quota_reservation_manager_(new QuotaReservationManager(
+ scoped_ptr<QuotaReservationManager::QuotaBackend>(
+ new QuotaBackendImpl(file_task_runner_,
+ obfuscated_file_util(),
+ usage_cache(),
+ quota_manager_proxy)))),
special_storage_policy_(special_storage_policy),
file_system_options_(file_system_options),
is_filesystem_opened_(false),
weak_factory_(this) {
-}
-
-SandboxFileSystemBackendDelegate::~SandboxFileSystemBackendDelegate() {
- io_thread_checker_.DetachFromThread();
+ // Prepopulate database only if it can run asynchronously (i.e. the current
+ // thread is not file_task_runner). Usually this is the case but may not
+ // in test code.
if (!file_task_runner_->RunsTasksOnCurrentThread()) {
- AsyncFileUtil* sandbox_file_util = sandbox_file_util_.release();
- SandboxQuotaObserver* quota_observer = quota_observer_.release();
- FileSystemUsageCache* file_system_usage_cache =
- file_system_usage_cache_.release();
- if (!file_task_runner_->DeleteSoon(FROM_HERE, sandbox_file_util))
- delete sandbox_file_util;
- if (!file_task_runner_->DeleteSoon(FROM_HERE, quota_observer))
- delete quota_observer;
- if (!file_task_runner_->DeleteSoon(FROM_HERE, file_system_usage_cache))
- delete file_system_usage_cache;
+ std::vector<std::string> types_to_prepopulate(
+ &kPrepopulateTypes[0],
+ &kPrepopulateTypes[arraysize(kPrepopulateTypes)]);
+ file_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&ObfuscatedFileUtil::MaybePrepopulateDatabase,
+ base::Unretained(obfuscated_file_util()),
+ types_to_prepopulate));
}
}
-bool SandboxFileSystemBackendDelegate::IsAccessValid(
- const FileSystemURL& url) const {
- if (!IsAllowedScheme(url.origin()))
- return false;
-
- if (url.path().ReferencesParent())
- return false;
-
- // Return earlier if the path is '/', because VirtualPath::BaseName()
- // returns '/' for '/' and we fail the "basename != '/'" check below.
- // (We exclude '.' because it's disallowed by spec.)
- if (VirtualPath::IsRootPath(url.path()) &&
- url.path() != base::FilePath(base::FilePath::kCurrentDirectory))
- return true;
-
- // Restricted names specified in
- // http://dev.w3.org/2009/dap/file-system/file-dir-sys.html#naming-restrictions
- base::FilePath filename = VirtualPath::BaseName(url.path());
- // See if the name is allowed to create.
- for (size_t i = 0; i < arraysize(kRestrictedNames); ++i) {
- if (filename.value() == kRestrictedNames[i])
- return false;
- }
- for (size_t i = 0; i < arraysize(kRestrictedChars); ++i) {
- if (filename.value().find(kRestrictedChars[i]) !=
- base::FilePath::StringType::npos)
- return false;
- }
-
- return true;
-}
-
-bool SandboxFileSystemBackendDelegate::IsAllowedScheme(const GURL& url) const {
- // Basically we only accept http or https. We allow file:// URLs
- // only if --allow-file-access-from-files flag is given.
- if (url.SchemeIsHTTPOrHTTPS())
- return true;
- if (url.SchemeIsFileSystem())
- return url.inner_url() && IsAllowedScheme(*url.inner_url());
+SandboxFileSystemBackendDelegate::~SandboxFileSystemBackendDelegate() {
+ io_thread_checker_.DetachFromThread();
- for (size_t i = 0;
- i < file_system_options_.additional_allowed_schemes().size();
- ++i) {
- if (url.SchemeIs(
- file_system_options_.additional_allowed_schemes()[i].c_str()))
- return true;
+ if (!file_task_runner_->RunsTasksOnCurrentThread()) {
+ DeleteSoon(file_task_runner_.get(), quota_reservation_manager_.release());
+ DeleteSoon(file_task_runner_.get(), sandbox_file_util_.release());
+ DeleteSoon(file_task_runner_.get(), quota_observer_.release());
+ DeleteSoon(file_task_runner_.get(), file_system_usage_cache_.release());
}
- return false;
}
SandboxFileSystemBackendDelegate::OriginEnumerator*
@@ -215,7 +238,7 @@ SandboxFileSystemBackendDelegate::GetBaseDirectoryForOriginAndType(
bool create) {
base::PlatformFileError error = base::PLATFORM_FILE_OK;
base::FilePath path = obfuscated_file_util()->GetDirectoryForOriginAndType(
- origin_url, type, create, &error);
+ origin_url, GetTypeString(type), create, &error);
if (error != base::PLATFORM_FILE_OK)
return base::FilePath();
return path;
@@ -309,7 +332,7 @@ SandboxFileSystemBackendDelegate::DeleteOriginDataOnFileThread(
file_system_context, origin_url, type);
usage_cache()->CloseCacheFiles();
bool result = obfuscated_file_util()->DeleteDirectoryForOriginAndType(
- origin_url, type);
+ origin_url, GetTypeString(type));
if (result && proxy) {
proxy->NotifyStorageModified(
quota::QuotaClient::kFileSystem,
@@ -395,6 +418,15 @@ int64 SandboxFileSystemBackendDelegate::GetOriginUsageOnFileThread(
return usage;
}
+scoped_refptr<QuotaReservation>
+SandboxFileSystemBackendDelegate::CreateQuotaReservationOnFileTaskRunner(
+ const GURL& origin,
+ FileSystemType type) {
+ DCHECK(file_task_runner_->RunsTasksOnCurrentThread());
+ DCHECK(quota_reservation_manager_);
+ return quota_reservation_manager_->CreateReservation(origin, type);
+}
+
void SandboxFileSystemBackendDelegate::AddFileUpdateObserver(
FileSystemType type,
FileUpdateObserver* observer,
@@ -449,6 +481,11 @@ const AccessObserverList* SandboxFileSystemBackendDelegate::GetAccessObservers(
return &iter->second;
}
+void SandboxFileSystemBackendDelegate::RegisterQuotaUpdateObserver(
+ FileSystemType type) {
+ AddFileUpdateObserver(type, quota_observer_.get(), file_task_runner_.get());
+}
+
void SandboxFileSystemBackendDelegate::InvalidateUsageCache(
const GURL& origin,
FileSystemType type) {
@@ -472,6 +509,56 @@ FileSystemFileUtil* SandboxFileSystemBackendDelegate::sync_file_util() {
return static_cast<AsyncFileUtilAdapter*>(file_util())->sync_file_util();
}
+bool SandboxFileSystemBackendDelegate::IsAccessValid(
+ const FileSystemURL& url) const {
+ if (!IsAllowedScheme(url.origin()))
+ return false;
+
+ if (url.path().ReferencesParent())
+ return false;
+
+ // Return earlier if the path is '/', because VirtualPath::BaseName()
+ // returns '/' for '/' and we fail the "basename != '/'" check below.
+ // (We exclude '.' because it's disallowed by spec.)
+ if (VirtualPath::IsRootPath(url.path()) &&
+ url.path() != base::FilePath(base::FilePath::kCurrentDirectory))
+ return true;
+
+ // Restricted names specified in
+ // http://dev.w3.org/2009/dap/file-system/file-dir-sys.html#naming-restrictions
+ base::FilePath filename = VirtualPath::BaseName(url.path());
+ // See if the name is allowed to create.
+ for (size_t i = 0; i < arraysize(kRestrictedNames); ++i) {
+ if (filename.value() == kRestrictedNames[i])
+ return false;
+ }
+ for (size_t i = 0; i < arraysize(kRestrictedChars); ++i) {
+ if (filename.value().find(kRestrictedChars[i]) !=
+ base::FilePath::StringType::npos)
+ return false;
+ }
+
+ return true;
+}
+
+bool SandboxFileSystemBackendDelegate::IsAllowedScheme(const GURL& url) const {
+ // Basically we only accept http or https. We allow file:// URLs
+ // only if --allow-file-access-from-files flag is given.
+ if (url.SchemeIsHTTPOrHTTPS())
+ return true;
+ if (url.SchemeIsFileSystem())
+ return url.inner_url() && IsAllowedScheme(*url.inner_url());
+
+ for (size_t i = 0;
+ i < file_system_options_.additional_allowed_schemes().size();
+ ++i) {
+ if (url.SchemeIs(
+ file_system_options_.additional_allowed_schemes()[i].c_str()))
+ return true;
+ }
+ return false;
+}
+
base::FilePath
SandboxFileSystemBackendDelegate::GetUsageCachePathForOriginAndType(
const GURL& origin_url,
@@ -494,7 +581,7 @@ SandboxFileSystemBackendDelegate::GetUsageCachePathForOriginAndType(
DCHECK(error_out);
*error_out = base::PLATFORM_FILE_OK;
base::FilePath base_path = sandbox_file_util->GetDirectoryForOriginAndType(
- origin_url, type, false /* create */, error_out);
+ origin_url, GetTypeString(type), false /* create */, error_out);
if (*error_out != base::PLATFORM_FILE_OK)
return base::FilePath();
return base_path.Append(FileSystemUsageCache::kUsageFileName);
@@ -563,4 +650,18 @@ ObfuscatedFileUtil* SandboxFileSystemBackendDelegate::obfuscated_file_util() {
return static_cast<ObfuscatedFileUtil*>(sync_file_util());
}
+// Declared in obfuscated_file_util.h.
+// static
+ObfuscatedFileUtil* ObfuscatedFileUtil::CreateForTesting(
+ quota::SpecialStoragePolicy* special_storage_policy,
+ const base::FilePath& file_system_directory,
+ base::SequencedTaskRunner* file_task_runner) {
+ return new ObfuscatedFileUtil(special_storage_policy,
+ file_system_directory,
+ file_task_runner,
+ base::Bind(&GetTypeStringForURL),
+ GetKnownTypeStrings(),
+ NULL);
+}
+
} // namespace fileapi
diff --git a/chromium/webkit/browser/fileapi/sandbox_file_system_backend_delegate.h b/chromium/webkit/browser/fileapi/sandbox_file_system_backend_delegate.h
index 33d791e5920..dd5e11f1837 100644
--- a/chromium/webkit/browser/fileapi/sandbox_file_system_backend_delegate.h
+++ b/chromium/webkit/browser/fileapi/sandbox_file_system_backend_delegate.h
@@ -11,6 +11,7 @@
#include <utility>
#include "base/files/file_path.h"
+#include "base/gtest_prod_util.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
@@ -43,6 +44,7 @@ class FileSystemOperationContext;
class FileSystemURL;
class FileSystemUsageCache;
class ObfuscatedFileUtil;
+class QuotaReservationManager;
class SandboxFileSystemBackend;
class SandboxFileSystemTestHelper;
class SandboxQuotaObserver;
@@ -70,6 +72,9 @@ class WEBKIT_STORAGE_BROWSER_EXPORT SandboxFileSystemBackendDelegate
virtual bool HasFileSystemType(FileSystemType type) const = 0;
};
+ // Returns the type directory name in sandbox directory for given |type|.
+ static std::string GetTypeString(FileSystemType type);
+
SandboxFileSystemBackendDelegate(
quota::QuotaManagerProxy* quota_manager_proxy,
base::SequencedTaskRunner* file_task_runner,
@@ -79,14 +84,6 @@ class WEBKIT_STORAGE_BROWSER_EXPORT SandboxFileSystemBackendDelegate
virtual ~SandboxFileSystemBackendDelegate();
- // Performs API-specific validity checks on the given path |url|.
- // Returns true if access to |url| is valid in this filesystem.
- bool IsAccessValid(const FileSystemURL& url) const;
-
- // Returns true if the given |url|'s scheme is allowed to access
- // filesystem.
- bool IsAllowedScheme(const GURL& url) const;
-
// Returns an origin enumerator of sandbox filesystem.
// This method can only be called on the file thread.
OriginEnumerator* CreateOriginEnumerator();
@@ -141,6 +138,10 @@ class WEBKIT_STORAGE_BROWSER_EXPORT SandboxFileSystemBackendDelegate
FileSystemContext* context,
const GURL& origin_url,
FileSystemType type) OVERRIDE;
+ virtual scoped_refptr<QuotaReservation>
+ CreateQuotaReservationOnFileTaskRunner(
+ const GURL& origin_url,
+ FileSystemType type) OVERRIDE;
virtual void AddFileUpdateObserver(
FileSystemType type,
FileUpdateObserver* observer,
@@ -160,6 +161,9 @@ class WEBKIT_STORAGE_BROWSER_EXPORT SandboxFileSystemBackendDelegate
virtual const AccessObserverList* GetAccessObservers(
FileSystemType type) const OVERRIDE;
+ // Registers quota observer for file updates on filesystem of |type|.
+ void RegisterQuotaUpdateObserver(FileSystemType type);
+
void InvalidateUsageCache(const GURL& origin_url,
FileSystemType type);
void StickyInvalidateUsageCache(const GURL& origin_url,
@@ -188,6 +192,16 @@ class WEBKIT_STORAGE_BROWSER_EXPORT SandboxFileSystemBackendDelegate
private:
friend class SandboxQuotaObserver;
friend class SandboxFileSystemTestHelper;
+ friend class QuotaBackendImpl;
+ FRIEND_TEST_ALL_PREFIXES(SandboxFileSystemBackendDelegateTest, IsAccessValid);
+
+ // Performs API-specific validity checks on the given path |url|.
+ // Returns true if access to |url| is valid in this filesystem.
+ bool IsAccessValid(const FileSystemURL& url) const;
+
+ // Returns true if the given |url|'s scheme is allowed to access
+ // filesystem.
+ bool IsAllowedScheme(const GURL& url) const;
// Returns a path to the usage cache file.
base::FilePath GetUsageCachePathForOriginAndType(
@@ -212,6 +226,7 @@ class WEBKIT_STORAGE_BROWSER_EXPORT SandboxFileSystemBackendDelegate
scoped_ptr<AsyncFileUtil> sandbox_file_util_;
scoped_ptr<FileSystemUsageCache> file_system_usage_cache_;
scoped_ptr<SandboxQuotaObserver> quota_observer_;
+ scoped_ptr<QuotaReservationManager> quota_reservation_manager_;
scoped_refptr<quota::SpecialStoragePolicy> special_storage_policy_;
diff --git a/chromium/webkit/browser/fileapi/sandbox_file_system_backend_delegate_unittest.cc b/chromium/webkit/browser/fileapi/sandbox_file_system_backend_delegate_unittest.cc
deleted file mode 100644
index 48c3b8c4e70..00000000000
--- a/chromium/webkit/browser/fileapi/sandbox_file_system_backend_delegate_unittest.cc
+++ /dev/null
@@ -1,82 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "webkit/browser/fileapi/sandbox_file_system_backend_delegate.h"
-
-#include "base/basictypes.h"
-#include "base/file_util.h"
-#include "base/files/scoped_temp_dir.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/message_loop/message_loop.h"
-#include "base/message_loop/message_loop_proxy.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "url/gurl.h"
-#include "webkit/browser/fileapi/file_system_url.h"
-#include "webkit/browser/fileapi/mock_file_system_options.h"
-
-namespace fileapi {
-
-namespace {
-
-FileSystemURL CreateFileSystemURL(const char* path) {
- const GURL kOrigin("http://foo/");
- return FileSystemURL::CreateForTest(
- kOrigin, kFileSystemTypeTemporary, base::FilePath::FromUTF8Unsafe(path));
-}
-
-} // namespace
-
-class SandboxFileSystemBackendDelegateTest : public testing::Test {
- protected:
- virtual void SetUp() {
- ASSERT_TRUE(data_dir_.CreateUniqueTempDir());
- delegate_.reset(new SandboxFileSystemBackendDelegate(
- NULL /* quota_manager_proxy */,
- base::MessageLoopProxy::current().get(),
- data_dir_.path(),
- NULL /* special_storage_policy */,
- CreateAllowFileAccessOptions()));
- }
-
- base::ScopedTempDir data_dir_;
- base::MessageLoop message_loop_;
- scoped_ptr<SandboxFileSystemBackendDelegate> delegate_;
-};
-
-TEST_F(SandboxFileSystemBackendDelegateTest, IsAccessValid) {
- // Normal case.
- EXPECT_TRUE(delegate_->IsAccessValid(CreateFileSystemURL("a")));
-
- // Access to a path with parent references ('..') should be disallowed.
- EXPECT_FALSE(delegate_->IsAccessValid(CreateFileSystemURL("a/../b")));
-
- // Access from non-allowed scheme should be disallowed.
- EXPECT_FALSE(delegate_->IsAccessValid(
- FileSystemURL::CreateForTest(
- GURL("unknown://bar"), kFileSystemTypeTemporary,
- base::FilePath::FromUTF8Unsafe("foo"))));
-
- // Access with restricted name should be disallowed.
- EXPECT_FALSE(delegate_->IsAccessValid(CreateFileSystemURL(".")));
- EXPECT_FALSE(delegate_->IsAccessValid(CreateFileSystemURL("..")));
-
- // This is also disallowed due to Windows XP parent path handling.
- EXPECT_FALSE(delegate_->IsAccessValid(CreateFileSystemURL("...")));
-
- // These are identified as unsafe cases due to weird path handling
- // on Windows.
- EXPECT_FALSE(delegate_->IsAccessValid(CreateFileSystemURL(" ..")));
- EXPECT_FALSE(delegate_->IsAccessValid(CreateFileSystemURL(".. ")));
-
- // Similar but safe cases.
- EXPECT_TRUE(delegate_->IsAccessValid(CreateFileSystemURL(" .")));
- EXPECT_TRUE(delegate_->IsAccessValid(CreateFileSystemURL(". ")));
- EXPECT_TRUE(delegate_->IsAccessValid(CreateFileSystemURL("b.")));
- EXPECT_TRUE(delegate_->IsAccessValid(CreateFileSystemURL(".b")));
-
- // A path that looks like a drive letter.
- EXPECT_TRUE(delegate_->IsAccessValid(CreateFileSystemURL("c:")));
-}
-
-} // namespace fileapi
diff --git a/chromium/webkit/browser/fileapi/sandbox_file_system_backend_unittest.cc b/chromium/webkit/browser/fileapi/sandbox_file_system_backend_unittest.cc
deleted file mode 100644
index ed06d17ad70..00000000000
--- a/chromium/webkit/browser/fileapi/sandbox_file_system_backend_unittest.cc
+++ /dev/null
@@ -1,325 +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/browser/fileapi/sandbox_file_system_backend.h"
-
-#include <set>
-
-#include "base/basictypes.h"
-#include "base/file_util.h"
-#include "base/files/scoped_temp_dir.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/message_loop/message_loop_proxy.h"
-#include "base/run_loop.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "url/gurl.h"
-#include "webkit/browser/fileapi/file_system_backend.h"
-#include "webkit/browser/fileapi/file_system_url.h"
-#include "webkit/browser/fileapi/mock_file_system_options.h"
-#include "webkit/browser/fileapi/sandbox_file_system_backend_delegate.h"
-#include "webkit/common/fileapi/file_system_util.h"
-
-// PS stands for path separator.
-#if defined(FILE_PATH_USES_WIN_SEPARATORS)
-#define PS "\\"
-#else
-#define PS "/"
-#endif
-
-namespace fileapi {
-
-namespace {
-
-const struct RootPathTest {
- fileapi::FileSystemType type;
- const char* origin_url;
- const char* expected_path;
-} kRootPathTestCases[] = {
- { fileapi::kFileSystemTypeTemporary, "http://foo:1/",
- "000" PS "t" },
- { fileapi::kFileSystemTypePersistent, "http://foo:1/",
- "000" PS "p" },
- { fileapi::kFileSystemTypeTemporary, "http://bar.com/",
- "001" PS "t" },
- { fileapi::kFileSystemTypePersistent, "http://bar.com/",
- "001" PS "p" },
- { fileapi::kFileSystemTypeTemporary, "https://foo:2/",
- "002" PS "t" },
- { fileapi::kFileSystemTypePersistent, "https://foo:2/",
- "002" PS "p" },
- { fileapi::kFileSystemTypeTemporary, "https://bar.com/",
- "003" PS "t" },
- { fileapi::kFileSystemTypePersistent, "https://bar.com/",
- "003" PS "p" },
-};
-
-const struct RootPathFileURITest {
- fileapi::FileSystemType type;
- const char* origin_url;
- const char* expected_path;
- const char* virtual_path;
-} kRootPathFileURITestCases[] = {
- { fileapi::kFileSystemTypeTemporary, "file:///",
- "000" PS "t", NULL },
- { fileapi::kFileSystemTypePersistent, "file:///",
- "000" PS "p", NULL },
-};
-
-FileSystemURL CreateFileSystemURL(const char* path) {
- const GURL kOrigin("http://foo/");
- return FileSystemURL::CreateForTest(
- kOrigin, kFileSystemTypeTemporary, base::FilePath::FromUTF8Unsafe(path));
-}
-
-void DidOpenFileSystem(base::PlatformFileError* error_out,
- const GURL& origin_url,
- const std::string& name,
- base::PlatformFileError error) {
- *error_out = error;
-}
-
-} // namespace
-
-class SandboxFileSystemBackendTest : public testing::Test {
- protected:
- virtual void SetUp() {
- ASSERT_TRUE(data_dir_.CreateUniqueTempDir());
- SetUpNewDelegate(CreateAllowFileAccessOptions());
- }
-
- void SetUpNewDelegate(const FileSystemOptions& options) {
- delegate_.reset(new SandboxFileSystemBackendDelegate(
- NULL /* quota_manager_proxy */,
- base::MessageLoopProxy::current().get(),
- data_dir_.path(),
- NULL /* special_storage_policy */,
- options));
- }
-
- void SetUpNewBackend(const FileSystemOptions& options) {
- SetUpNewDelegate(options);
- backend_.reset(new SandboxFileSystemBackend(delegate_.get()));
- }
-
- SandboxFileSystemBackendDelegate::OriginEnumerator*
- CreateOriginEnumerator() const {
- return backend_->CreateOriginEnumerator();
- }
-
- void CreateOriginTypeDirectory(const GURL& origin,
- fileapi::FileSystemType type) {
- base::FilePath target = delegate_->
- GetBaseDirectoryForOriginAndType(origin, type, true);
- ASSERT_TRUE(!target.empty());
- ASSERT_TRUE(base::DirectoryExists(target));
- }
-
- bool GetRootPath(const GURL& origin_url,
- fileapi::FileSystemType type,
- OpenFileSystemMode mode,
- base::FilePath* root_path) {
- base::PlatformFileError error = base::PLATFORM_FILE_OK;
- backend_->OpenFileSystem(
- origin_url, type, mode,
- base::Bind(&DidOpenFileSystem, &error));
- base::RunLoop().RunUntilIdle();
- if (error != base::PLATFORM_FILE_OK)
- return false;
- base::FilePath returned_root_path =
- delegate_->GetBaseDirectoryForOriginAndType(
- origin_url, type, false /* create */);
- if (root_path)
- *root_path = returned_root_path;
- return !returned_root_path.empty();
- }
-
- base::FilePath file_system_path() const {
- return data_dir_.path().Append(
- SandboxFileSystemBackendDelegate::kFileSystemDirectory);
- }
-
- base::ScopedTempDir data_dir_;
- base::MessageLoop message_loop_;
- scoped_ptr<SandboxFileSystemBackendDelegate> delegate_;
- scoped_ptr<SandboxFileSystemBackend> backend_;
-};
-
-TEST_F(SandboxFileSystemBackendTest, Empty) {
- SetUpNewBackend(CreateAllowFileAccessOptions());
- scoped_ptr<SandboxFileSystemBackendDelegate::OriginEnumerator> enumerator(
- CreateOriginEnumerator());
- ASSERT_TRUE(enumerator->Next().is_empty());
-}
-
-TEST_F(SandboxFileSystemBackendTest, EnumerateOrigins) {
- SetUpNewBackend(CreateAllowFileAccessOptions());
- const char* temporary_origins[] = {
- "http://www.bar.com/",
- "http://www.foo.com/",
- "http://www.foo.com:1/",
- "http://www.example.com:8080/",
- "http://www.google.com:80/",
- };
- const char* persistent_origins[] = {
- "http://www.bar.com/",
- "http://www.foo.com:8080/",
- "http://www.foo.com:80/",
- };
- size_t temporary_size = ARRAYSIZE_UNSAFE(temporary_origins);
- size_t persistent_size = ARRAYSIZE_UNSAFE(persistent_origins);
- std::set<GURL> temporary_set, persistent_set;
- for (size_t i = 0; i < temporary_size; ++i) {
- CreateOriginTypeDirectory(GURL(temporary_origins[i]),
- fileapi::kFileSystemTypeTemporary);
- temporary_set.insert(GURL(temporary_origins[i]));
- }
- for (size_t i = 0; i < persistent_size; ++i) {
- CreateOriginTypeDirectory(GURL(persistent_origins[i]),
- kFileSystemTypePersistent);
- persistent_set.insert(GURL(persistent_origins[i]));
- }
-
- scoped_ptr<SandboxFileSystemBackendDelegate::OriginEnumerator> enumerator(
- CreateOriginEnumerator());
- size_t temporary_actual_size = 0;
- size_t persistent_actual_size = 0;
- GURL current;
- while (!(current = enumerator->Next()).is_empty()) {
- SCOPED_TRACE(testing::Message() << "EnumerateOrigin " << current.spec());
- if (enumerator->HasFileSystemType(kFileSystemTypeTemporary)) {
- ASSERT_TRUE(temporary_set.find(current) != temporary_set.end());
- ++temporary_actual_size;
- }
- if (enumerator->HasFileSystemType(kFileSystemTypePersistent)) {
- ASSERT_TRUE(persistent_set.find(current) != persistent_set.end());
- ++persistent_actual_size;
- }
- }
-
- EXPECT_EQ(temporary_size, temporary_actual_size);
- EXPECT_EQ(persistent_size, persistent_actual_size);
-}
-
-TEST_F(SandboxFileSystemBackendTest, GetRootPathCreateAndExamine) {
- std::vector<base::FilePath> returned_root_path(
- ARRAYSIZE_UNSAFE(kRootPathTestCases));
- SetUpNewBackend(CreateAllowFileAccessOptions());
-
- // Create a new root directory.
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kRootPathTestCases); ++i) {
- SCOPED_TRACE(testing::Message() << "RootPath (create) #" << i << " "
- << kRootPathTestCases[i].expected_path);
-
- base::FilePath root_path;
- EXPECT_TRUE(GetRootPath(GURL(kRootPathTestCases[i].origin_url),
- kRootPathTestCases[i].type,
- OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
- &root_path));
-
- base::FilePath expected = file_system_path().AppendASCII(
- kRootPathTestCases[i].expected_path);
- EXPECT_EQ(expected.value(), root_path.value());
- EXPECT_TRUE(base::DirectoryExists(root_path));
- ASSERT_TRUE(returned_root_path.size() > i);
- returned_root_path[i] = root_path;
- }
-
- // Get the root directory with create=false and see if we get the
- // same directory.
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kRootPathTestCases); ++i) {
- SCOPED_TRACE(testing::Message() << "RootPath (get) #" << i << " "
- << kRootPathTestCases[i].expected_path);
-
- base::FilePath root_path;
- EXPECT_TRUE(GetRootPath(GURL(kRootPathTestCases[i].origin_url),
- kRootPathTestCases[i].type,
- OPEN_FILE_SYSTEM_FAIL_IF_NONEXISTENT,
- &root_path));
- ASSERT_TRUE(returned_root_path.size() > i);
- EXPECT_EQ(returned_root_path[i].value(), root_path.value());
- }
-}
-
-TEST_F(SandboxFileSystemBackendTest,
- GetRootPathCreateAndExamineWithNewBackend) {
- std::vector<base::FilePath> returned_root_path(
- ARRAYSIZE_UNSAFE(kRootPathTestCases));
- SetUpNewBackend(CreateAllowFileAccessOptions());
-
- GURL origin_url("http://foo.com:1/");
-
- base::FilePath root_path1;
- EXPECT_TRUE(GetRootPath(origin_url, kFileSystemTypeTemporary,
- OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
- &root_path1));
-
- SetUpNewBackend(CreateDisallowFileAccessOptions());
- base::FilePath root_path2;
- EXPECT_TRUE(GetRootPath(origin_url, kFileSystemTypeTemporary,
- OPEN_FILE_SYSTEM_FAIL_IF_NONEXISTENT,
- &root_path2));
-
- EXPECT_EQ(root_path1.value(), root_path2.value());
-}
-
-TEST_F(SandboxFileSystemBackendTest, GetRootPathGetWithoutCreate) {
- SetUpNewBackend(CreateDisallowFileAccessOptions());
-
- // Try to get a root directory without creating.
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kRootPathTestCases); ++i) {
- SCOPED_TRACE(testing::Message() << "RootPath (create=false) #" << i << " "
- << kRootPathTestCases[i].expected_path);
- EXPECT_FALSE(GetRootPath(GURL(kRootPathTestCases[i].origin_url),
- kRootPathTestCases[i].type,
- OPEN_FILE_SYSTEM_FAIL_IF_NONEXISTENT,
- NULL));
- }
-}
-
-TEST_F(SandboxFileSystemBackendTest, GetRootPathInIncognito) {
- SetUpNewBackend(CreateIncognitoFileSystemOptions());
-
- // Try to get a root directory.
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kRootPathTestCases); ++i) {
- SCOPED_TRACE(testing::Message() << "RootPath (incognito) #" << i << " "
- << kRootPathTestCases[i].expected_path);
- EXPECT_FALSE(
- GetRootPath(GURL(kRootPathTestCases[i].origin_url),
- kRootPathTestCases[i].type,
- OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
- NULL));
- }
-}
-
-TEST_F(SandboxFileSystemBackendTest, GetRootPathFileURI) {
- SetUpNewBackend(CreateDisallowFileAccessOptions());
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kRootPathFileURITestCases); ++i) {
- SCOPED_TRACE(testing::Message() << "RootPathFileURI (disallow) #"
- << i << " " << kRootPathFileURITestCases[i].expected_path);
- EXPECT_FALSE(
- GetRootPath(GURL(kRootPathFileURITestCases[i].origin_url),
- kRootPathFileURITestCases[i].type,
- OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
- NULL));
- }
-}
-
-TEST_F(SandboxFileSystemBackendTest, GetRootPathFileURIWithAllowFlag) {
- SetUpNewBackend(CreateAllowFileAccessOptions());
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kRootPathFileURITestCases); ++i) {
- SCOPED_TRACE(testing::Message() << "RootPathFileURI (allow) #"
- << i << " " << kRootPathFileURITestCases[i].expected_path);
- base::FilePath root_path;
- EXPECT_TRUE(GetRootPath(GURL(kRootPathFileURITestCases[i].origin_url),
- kRootPathFileURITestCases[i].type,
- OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
- &root_path));
- base::FilePath expected = file_system_path().AppendASCII(
- kRootPathFileURITestCases[i].expected_path);
- EXPECT_EQ(expected.value(), root_path.value());
- EXPECT_TRUE(base::DirectoryExists(root_path));
- }
-}
-
-} // namespace fileapi
diff --git a/chromium/webkit/browser/fileapi/sandbox_file_system_test_helper.cc b/chromium/webkit/browser/fileapi/sandbox_file_system_test_helper.cc
deleted file mode 100644
index df579e488e4..00000000000
--- a/chromium/webkit/browser/fileapi/sandbox_file_system_test_helper.cc
+++ /dev/null
@@ -1,152 +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/browser/fileapi/sandbox_file_system_test_helper.h"
-
-#include "base/file_util.h"
-#include "base/message_loop/message_loop_proxy.h"
-#include "base/run_loop.h"
-#include "url/gurl.h"
-#include "webkit/browser/fileapi/file_system_context.h"
-#include "webkit/browser/fileapi/file_system_file_util.h"
-#include "webkit/browser/fileapi/file_system_operation_context.h"
-#include "webkit/browser/fileapi/file_system_operation_runner.h"
-#include "webkit/browser/fileapi/file_system_url.h"
-#include "webkit/browser/fileapi/file_system_usage_cache.h"
-#include "webkit/browser/fileapi/mock_file_system_context.h"
-#include "webkit/browser/fileapi/sandbox_file_system_backend.h"
-#include "webkit/browser/quota/mock_special_storage_policy.h"
-#include "webkit/common/fileapi/file_system_util.h"
-
-namespace fileapi {
-
-SandboxFileSystemTestHelper::SandboxFileSystemTestHelper(
- const GURL& origin, FileSystemType type)
- : origin_(origin), type_(type), file_util_(NULL) {
-}
-
-SandboxFileSystemTestHelper::SandboxFileSystemTestHelper()
- : origin_(GURL("http://foo.com")),
- type_(kFileSystemTypeTemporary),
- file_util_(NULL) {
-}
-
-SandboxFileSystemTestHelper::~SandboxFileSystemTestHelper() {
-}
-
-void SandboxFileSystemTestHelper::SetUp(const base::FilePath& base_dir) {
- SetUp(base_dir, NULL);
-}
-
-void SandboxFileSystemTestHelper::SetUp(
- FileSystemContext* file_system_context) {
- file_system_context_ = file_system_context;
-
- SetUpFileSystem();
-}
-
-void SandboxFileSystemTestHelper::SetUp(
- const base::FilePath& base_dir,
- quota::QuotaManagerProxy* quota_manager_proxy) {
- file_system_context_ = CreateFileSystemContextForTesting(
- quota_manager_proxy, base_dir);
-
- SetUpFileSystem();
-}
-
-void SandboxFileSystemTestHelper::TearDown() {
- file_system_context_ = NULL;
- base::RunLoop().RunUntilIdle();
-}
-
-base::FilePath SandboxFileSystemTestHelper::GetOriginRootPath() {
- return file_system_context_->sandbox_delegate()->
- GetBaseDirectoryForOriginAndType(origin_, type_, false);
-}
-
-base::FilePath SandboxFileSystemTestHelper::GetLocalPath(
- const base::FilePath& path) {
- DCHECK(file_util_);
- base::FilePath local_path;
- scoped_ptr<FileSystemOperationContext> context(NewOperationContext());
- file_util_->GetLocalFilePath(context.get(), CreateURL(path), &local_path);
- return local_path;
-}
-
-base::FilePath SandboxFileSystemTestHelper::GetLocalPathFromASCII(
- const std::string& path) {
- return GetLocalPath(base::FilePath().AppendASCII(path));
-}
-
-base::FilePath SandboxFileSystemTestHelper::GetUsageCachePath() const {
- return file_system_context_->sandbox_delegate()->
- GetUsageCachePathForOriginAndType(origin_, type_);
-}
-
-FileSystemURL SandboxFileSystemTestHelper::CreateURL(
- const base::FilePath& path) const {
- return file_system_context_->CreateCrackedFileSystemURL(origin_, type_, path);
-}
-
-int64 SandboxFileSystemTestHelper::GetCachedOriginUsage() const {
- return file_system_context_->GetQuotaUtil(type_)
- ->GetOriginUsageOnFileThread(file_system_context_.get(), origin_, type_);
-}
-
-int64 SandboxFileSystemTestHelper::ComputeCurrentOriginUsage() {
- usage_cache()->CloseCacheFiles();
- int64 size = base::ComputeDirectorySize(GetOriginRootPath());
- if (base::PathExists(GetUsageCachePath()))
- size -= FileSystemUsageCache::kUsageFileSize;
- return size;
-}
-
-int64
-SandboxFileSystemTestHelper::ComputeCurrentDirectoryDatabaseUsage() {
- return base::ComputeDirectorySize(
- GetOriginRootPath().AppendASCII("Paths"));
-}
-
-FileSystemOperationRunner* SandboxFileSystemTestHelper::operation_runner() {
- return file_system_context_->operation_runner();
-}
-
-FileSystemOperationContext*
-SandboxFileSystemTestHelper::NewOperationContext() {
- DCHECK(file_system_context_.get());
- FileSystemOperationContext* context =
- new FileSystemOperationContext(file_system_context_.get());
- context->set_update_observers(
- *file_system_context_->GetUpdateObservers(type_));
- return context;
-}
-
-void SandboxFileSystemTestHelper::AddFileChangeObserver(
- FileChangeObserver* observer) {
- file_system_context_->sandbox_backend()->GetQuotaUtil()->
- AddFileChangeObserver(type_, observer, NULL);
-}
-
-FileSystemUsageCache* SandboxFileSystemTestHelper::usage_cache() {
- return file_system_context()->sandbox_delegate()->usage_cache();
-}
-
-void SandboxFileSystemTestHelper::SetUpFileSystem() {
- DCHECK(file_system_context_.get());
- DCHECK(file_system_context_->sandbox_backend()->CanHandleType(type_));
-
- file_util_ = file_system_context_->sandbox_delegate()->sync_file_util();
- DCHECK(file_util_);
-
- // Prepare the origin's root directory.
- file_system_context_->sandbox_delegate()->
- GetBaseDirectoryForOriginAndType(origin_, type_, true /* create */);
-
- // Initialize the usage cache file.
- base::FilePath usage_cache_path = GetUsageCachePath();
- if (!usage_cache_path.empty())
- usage_cache()->UpdateUsage(usage_cache_path, 0);
-}
-
-} // namespace fileapi
diff --git a/chromium/webkit/browser/fileapi/sandbox_file_system_test_helper.h b/chromium/webkit/browser/fileapi/sandbox_file_system_test_helper.h
deleted file mode 100644
index 5a48872326c..00000000000
--- a/chromium/webkit/browser/fileapi/sandbox_file_system_test_helper.h
+++ /dev/null
@@ -1,103 +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_BROWSER_FILEAPI_SANDBOX_FILE_SYSTEM_TEST_HELPER_H_
-#define WEBKIT_BROWSER_FILEAPI_SANDBOX_FILE_SYSTEM_TEST_HELPER_H_
-
-#include <string>
-
-#include "base/files/file_path.h"
-#include "base/memory/ref_counted.h"
-#include "url/gurl.h"
-#include "webkit/browser/fileapi/file_system_url.h"
-#include "webkit/browser/fileapi/file_system_usage_cache.h"
-#include "webkit/browser/fileapi/task_runner_bound_observer_list.h"
-#include "webkit/common/fileapi/file_system_types.h"
-#include "webkit/common/fileapi/file_system_util.h"
-#include "webkit/common/quota/quota_types.h"
-
-namespace base {
-class FilePath;
-}
-
-namespace quota {
-class QuotaManagerProxy;
-}
-
-namespace fileapi {
-
-class FileSystemContext;
-class FileSystemFileUtil;
-class FileSystemOperationContext;
-class FileSystemOperationRunner;
-
-// Filesystem test helper class that encapsulates test environment for
-// a given {origin, type} pair. This helper only works for sandboxed
-// file systems (Temporary or Persistent).
-class SandboxFileSystemTestHelper {
- public:
- SandboxFileSystemTestHelper(const GURL& origin, FileSystemType type);
- SandboxFileSystemTestHelper();
- ~SandboxFileSystemTestHelper();
-
- void SetUp(const base::FilePath& base_dir);
- // If you want to use more than one SandboxFileSystemTestHelper in
- // a single base directory, they have to share a context, so that they don't
- // have multiple databases fighting over the lock to the origin directory
- // [deep down inside ObfuscatedFileUtil].
- void SetUp(FileSystemContext* file_system_context);
- void SetUp(const base::FilePath& base_dir,
- quota::QuotaManagerProxy* quota_manager_proxy);
- void TearDown();
-
- base::FilePath GetOriginRootPath();
- base::FilePath GetLocalPath(const base::FilePath& path);
- base::FilePath GetLocalPathFromASCII(const std::string& path);
-
- // Returns empty path if filesystem type is neither temporary nor persistent.
- base::FilePath GetUsageCachePath() const;
-
- FileSystemURL CreateURL(const base::FilePath& path) const;
- FileSystemURL CreateURLFromUTF8(const std::string& utf8) const {
- return CreateURL(base::FilePath::FromUTF8Unsafe(utf8));
- }
-
- // This returns cached usage size returned by QuotaUtil.
- int64 GetCachedOriginUsage() const;
-
- // This doesn't work with OFSFU.
- int64 ComputeCurrentOriginUsage();
-
- int64 ComputeCurrentDirectoryDatabaseUsage();
-
- FileSystemOperationRunner* operation_runner();
- FileSystemOperationContext* NewOperationContext();
-
- void AddFileChangeObserver(FileChangeObserver* observer);
-
- FileSystemContext* file_system_context() const {
- return file_system_context_.get();
- }
-
- const GURL& origin() const { return origin_; }
- FileSystemType type() const { return type_; }
- quota::StorageType storage_type() const {
- return FileSystemTypeToQuotaStorageType(type_);
- }
- FileSystemFileUtil* file_util() const { return file_util_; }
- FileSystemUsageCache* usage_cache();
-
- private:
- void SetUpFileSystem();
-
- scoped_refptr<FileSystemContext> file_system_context_;
-
- const GURL origin_;
- const FileSystemType type_;
- FileSystemFileUtil* file_util_;
-};
-
-} // namespace fileapi
-
-#endif // WEBKIT_BROWSER_FILEAPI_SANDBOX_FILE_SYSTEM_TEST_HELPER_H_
diff --git a/chromium/webkit/browser/fileapi/sandbox_isolated_origin_database.cc b/chromium/webkit/browser/fileapi/sandbox_isolated_origin_database.cc
index 7ed4e8ce4af..901c4fd61bc 100644
--- a/chromium/webkit/browser/fileapi/sandbox_isolated_origin_database.cc
+++ b/chromium/webkit/browser/fileapi/sandbox_isolated_origin_database.cc
@@ -12,14 +12,17 @@ namespace fileapi {
// Special directory name for isolated origin.
const base::FilePath::CharType
-SandboxIsolatedOriginDatabase::kOriginDirectory[] = FILE_PATH_LITERAL("iso");
+SandboxIsolatedOriginDatabase::kObsoleteOriginDirectory[] =
+ FILE_PATH_LITERAL("iso");
SandboxIsolatedOriginDatabase::SandboxIsolatedOriginDatabase(
const std::string& origin,
- const base::FilePath& file_system_directory)
+ const base::FilePath& file_system_directory,
+ const base::FilePath& origin_directory)
: migration_checked_(false),
origin_(origin),
- file_system_directory_(file_system_directory) {
+ file_system_directory_(file_system_directory),
+ origin_directory_(origin_directory) {
}
SandboxIsolatedOriginDatabase::~SandboxIsolatedOriginDatabase() {
@@ -27,16 +30,14 @@ SandboxIsolatedOriginDatabase::~SandboxIsolatedOriginDatabase() {
bool SandboxIsolatedOriginDatabase::HasOriginPath(
const std::string& origin) {
- MigrateDatabaseIfNeeded();
return (origin_ == origin);
}
bool SandboxIsolatedOriginDatabase::GetPathForOrigin(
const std::string& origin, base::FilePath* directory) {
- MigrateDatabaseIfNeeded();
if (origin != origin_)
return false;
- *directory = base::FilePath(kOriginDirectory);
+ *directory = origin_directory_;
return true;
}
@@ -47,20 +48,19 @@ bool SandboxIsolatedOriginDatabase::RemovePathForOrigin(
bool SandboxIsolatedOriginDatabase::ListAllOrigins(
std::vector<OriginRecord>* origins) {
- MigrateDatabaseIfNeeded();
- origins->push_back(OriginRecord(origin_, base::FilePath(kOriginDirectory)));
+ origins->push_back(OriginRecord(origin_, origin_directory_));
return true;
}
void SandboxIsolatedOriginDatabase::DropDatabase() {
}
-void SandboxIsolatedOriginDatabase::MigrateBackDatabase(
+void SandboxIsolatedOriginDatabase::MigrateBackFromObsoleteOriginDatabase(
const std::string& origin,
const base::FilePath& file_system_directory,
SandboxOriginDatabase* database) {
base::FilePath isolated_directory =
- file_system_directory.Append(kOriginDirectory);
+ file_system_directory.Append(kObsoleteOriginDirectory);
if (database->HasOriginPath(origin)) {
// Don't bother.
@@ -77,29 +77,4 @@ void SandboxIsolatedOriginDatabase::MigrateBackDatabase(
}
}
-void SandboxIsolatedOriginDatabase::MigrateDatabaseIfNeeded() {
- if (migration_checked_)
- return;
-
- migration_checked_ = true;
- // See if we have non-isolated version of sandbox database.
- scoped_ptr<SandboxOriginDatabase> database(
- new SandboxOriginDatabase(file_system_directory_));
- if (!database->HasOriginPath(origin_))
- return;
-
- base::FilePath directory_name;
- if (database->GetPathForOrigin(origin_, &directory_name) &&
- directory_name != base::FilePath(kOriginDirectory)) {
- base::FilePath from_path = file_system_directory_.Append(directory_name);
- base::FilePath to_path = file_system_directory_.Append(kOriginDirectory);
-
- if (base::PathExists(to_path))
- base::DeleteFile(to_path, true /* recursive */);
- base::Move(from_path, to_path);
- }
-
- database->RemoveDatabase();
-}
-
} // namespace fileapi
diff --git a/chromium/webkit/browser/fileapi/sandbox_isolated_origin_database.h b/chromium/webkit/browser/fileapi/sandbox_isolated_origin_database.h
index 2505659b064..d3a882a5ed4 100644
--- a/chromium/webkit/browser/fileapi/sandbox_isolated_origin_database.h
+++ b/chromium/webkit/browser/fileapi/sandbox_isolated_origin_database.h
@@ -5,20 +5,28 @@
#ifndef WEBKIT_BROWSER_FILEAPI_SANDBOX_ISOLATED_ORIGIN_DATABASE_H_
#define WEBKIT_BROWSER_FILEAPI_SANDBOX_ISOLATED_ORIGIN_DATABASE_H_
+#include <string>
+#include <vector>
+
#include "webkit/browser/fileapi/sandbox_origin_database_interface.h"
namespace fileapi {
class SandboxOriginDatabase;
+// This origin database implementation supports only one origin
+// (therefore is expected to run very fast).
class WEBKIT_STORAGE_BROWSER_EXPORT_PRIVATE SandboxIsolatedOriginDatabase
: public SandboxOriginDatabaseInterface {
public:
- static const base::FilePath::CharType kOriginDirectory[];
+ static const base::FilePath::CharType kObsoleteOriginDirectory[];
- explicit SandboxIsolatedOriginDatabase(
+ // Initialize this database for |origin| which makes GetPathForOrigin return
+ // |origin_directory| (in |file_system_directory|).
+ SandboxIsolatedOriginDatabase(
const std::string& origin,
- const base::FilePath& file_system_directory);
+ const base::FilePath& file_system_directory,
+ const base::FilePath& origin_directory);
virtual ~SandboxIsolatedOriginDatabase();
// SandboxOriginDatabaseInterface overrides.
@@ -29,17 +37,21 @@ class WEBKIT_STORAGE_BROWSER_EXPORT_PRIVATE SandboxIsolatedOriginDatabase
virtual bool ListAllOrigins(std::vector<OriginRecord>* origins) OVERRIDE;
virtual void DropDatabase() OVERRIDE;
- static void MigrateBackDatabase(
+ // TODO(kinuko): Deprecate this after a few release cycles, e.g. around M33.
+ static void MigrateBackFromObsoleteOriginDatabase(
const std::string& origin,
const base::FilePath& file_system_directory,
SandboxOriginDatabase* origin_database);
+ const std::string& origin() const { return origin_; }
+
private:
void MigrateDatabaseIfNeeded();
bool migration_checked_;
const std::string origin_;
const base::FilePath file_system_directory_;
+ const base::FilePath origin_directory_;
DISALLOW_COPY_AND_ASSIGN(SandboxIsolatedOriginDatabase);
};
diff --git a/chromium/webkit/browser/fileapi/sandbox_isolated_origin_database_unittest.cc b/chromium/webkit/browser/fileapi/sandbox_isolated_origin_database_unittest.cc
index aad2c7e6cc3..047a9612636 100644
--- a/chromium/webkit/browser/fileapi/sandbox_isolated_origin_database_unittest.cc
+++ b/chromium/webkit/browser/fileapi/sandbox_isolated_origin_database_unittest.cc
@@ -11,12 +11,17 @@
namespace fileapi {
+namespace {
+const base::FilePath::CharType kOriginDirectory[] = FILE_PATH_LITERAL("iso");
+} // namespace
+
TEST(SandboxIsolatedOriginDatabaseTest, BasicTest) {
base::ScopedTempDir dir;
ASSERT_TRUE(dir.CreateUniqueTempDir());
std::string kOrigin("origin");
- SandboxIsolatedOriginDatabase database(kOrigin, dir.path());
+ SandboxIsolatedOriginDatabase database(kOrigin, dir.path(),
+ base::FilePath(kOriginDirectory));
EXPECT_TRUE(database.HasOriginPath(kOrigin));
@@ -33,55 +38,4 @@ TEST(SandboxIsolatedOriginDatabaseTest, BasicTest) {
EXPECT_EQ(path1, path2);
}
-TEST(SandboxIsolatedOriginDatabaseTest, MigrationTest) {
- base::ScopedTempDir dir;
- ASSERT_TRUE(dir.CreateUniqueTempDir());
-
- std::string kOrigin("origin");
- std::string kFakeDirectoryData("0123456789");
- base::FilePath path;
- base::FilePath old_db_path;
-
- // Initialize the directory with one origin using the regular
- // SandboxOriginDatabase.
- {
- SandboxOriginDatabase database_old(dir.path());
- old_db_path = database_old.GetDatabasePath();
- EXPECT_FALSE(base::PathExists(old_db_path));
- EXPECT_TRUE(database_old.GetPathForOrigin(kOrigin, &path));
- EXPECT_FALSE(path.empty());
- EXPECT_TRUE(base::DirectoryExists(old_db_path));
-
- // Populate the origin directory with some fake data.
- base::FilePath directory_db_path = dir.path().Append(path);
- ASSERT_TRUE(file_util::CreateDirectory(directory_db_path));
- EXPECT_EQ(static_cast<int>(kFakeDirectoryData.size()),
- file_util::WriteFile(directory_db_path.AppendASCII("dummy"),
- kFakeDirectoryData.data(),
- kFakeDirectoryData.size()));
- }
-
- // Re-open the directory using sandboxIsolatedOriginDatabase.
- SandboxIsolatedOriginDatabase database(kOrigin, dir.path());
-
- // The database is migrated from the old one, so we should still
- // see the same origin.
- EXPECT_TRUE(database.HasOriginPath(kOrigin));
- EXPECT_TRUE(database.GetPathForOrigin(kOrigin, &path));
- EXPECT_FALSE(path.empty());
-
- // The directory content must be kept (or migrated if necessary),
- // so we should see the same fake data.
- std::string origin_db_data;
- base::FilePath directory_db_path = dir.path().Append(path);
- EXPECT_TRUE(base::DirectoryExists(directory_db_path));
- EXPECT_TRUE(base::PathExists(directory_db_path.AppendASCII("dummy")));
- EXPECT_TRUE(base::ReadFileToString(
- directory_db_path.AppendASCII("dummy"), &origin_db_data));
- EXPECT_EQ(kFakeDirectoryData, origin_db_data);
-
- // After the migration the database must be gone.
- EXPECT_FALSE(base::PathExists(old_db_path));
-}
-
} // namespace fileapi
diff --git a/chromium/webkit/browser/fileapi/sandbox_origin_database.cc b/chromium/webkit/browser/fileapi/sandbox_origin_database.cc
index 4ce83017cc0..ee01d227914 100644
--- a/chromium/webkit/browser/fileapi/sandbox_origin_database.cc
+++ b/chromium/webkit/browser/fileapi/sandbox_origin_database.cc
@@ -111,7 +111,7 @@ bool SandboxOriginDatabase::Init(InitOption init_option,
case DELETE_ON_CORRUPTION:
if (!base::DeleteFile(file_system_directory_, true))
return false;
- if (!file_util::CreateDirectory(file_system_directory_))
+ if (!base::CreateDirectory(file_system_directory_))
return false;
return Init(init_option, FAIL_ON_CORRUPTION);
}
diff --git a/chromium/webkit/browser/fileapi/sandbox_origin_database.h b/chromium/webkit/browser/fileapi/sandbox_origin_database.h
index 94cde472ade..dd3b32c95c3 100644
--- a/chromium/webkit/browser/fileapi/sandbox_origin_database.h
+++ b/chromium/webkit/browser/fileapi/sandbox_origin_database.h
@@ -5,6 +5,9 @@
#ifndef WEBKIT_BROWSER_FILEAPI_SANDBOX_ORIGIN_DATABASE_H_
#define WEBKIT_BROWSER_FILEAPI_SANDBOX_ORIGIN_DATABASE_H_
+#include <string>
+#include <vector>
+
#include "base/memory/scoped_ptr.h"
#include "base/time/time.h"
#include "webkit/browser/fileapi/sandbox_origin_database_interface.h"
diff --git a/chromium/webkit/browser/fileapi/sandbox_origin_database_unittest.cc b/chromium/webkit/browser/fileapi/sandbox_origin_database_unittest.cc
index 867dc273aad..340baf22409 100644
--- a/chromium/webkit/browser/fileapi/sandbox_origin_database_unittest.cc
+++ b/chromium/webkit/browser/fileapi/sandbox_origin_database_unittest.cc
@@ -6,6 +6,7 @@
#include <functional>
#include <limits>
#include <string>
+#include <vector>
#include "base/file_util.h"
#include "base/files/file_path.h"
@@ -33,7 +34,7 @@ TEST(SandboxOriginDatabaseTest, BasicTest) {
ASSERT_TRUE(dir.CreateUniqueTempDir());
const base::FilePath kFSDir = dir.path().Append(kFileSystemDirName);
EXPECT_FALSE(base::PathExists(kFSDir));
- EXPECT_TRUE(file_util::CreateDirectory(kFSDir));
+ EXPECT_TRUE(base::CreateDirectory(kFSDir));
SandboxOriginDatabase database(kFSDir);
std::string origin("origin");
@@ -63,7 +64,7 @@ TEST(SandboxOriginDatabaseTest, TwoPathTest) {
ASSERT_TRUE(dir.CreateUniqueTempDir());
const base::FilePath kFSDir = dir.path().Append(kFileSystemDirName);
EXPECT_FALSE(base::PathExists(kFSDir));
- EXPECT_TRUE(file_util::CreateDirectory(kFSDir));
+ EXPECT_TRUE(base::CreateDirectory(kFSDir));
SandboxOriginDatabase database(kFSDir);
std::string origin0("origin0");
@@ -91,7 +92,7 @@ TEST(SandboxOriginDatabaseTest, DropDatabaseTest) {
ASSERT_TRUE(dir.CreateUniqueTempDir());
const base::FilePath kFSDir = dir.path().Append(kFileSystemDirName);
EXPECT_FALSE(base::PathExists(kFSDir));
- EXPECT_TRUE(file_util::CreateDirectory(kFSDir));
+ EXPECT_TRUE(base::CreateDirectory(kFSDir));
SandboxOriginDatabase database(kFSDir);
std::string origin("origin");
@@ -119,7 +120,7 @@ TEST(SandboxOriginDatabaseTest, DeleteOriginTest) {
ASSERT_TRUE(dir.CreateUniqueTempDir());
const base::FilePath kFSDir = dir.path().Append(kFileSystemDirName);
EXPECT_FALSE(base::PathExists(kFSDir));
- EXPECT_TRUE(file_util::CreateDirectory(kFSDir));
+ EXPECT_TRUE(base::CreateDirectory(kFSDir));
SandboxOriginDatabase database(kFSDir);
std::string origin("origin");
@@ -146,7 +147,7 @@ TEST(SandboxOriginDatabaseTest, ListOriginsTest) {
ASSERT_TRUE(dir.CreateUniqueTempDir());
const base::FilePath kFSDir = dir.path().Append(kFileSystemDirName);
EXPECT_FALSE(base::PathExists(kFSDir));
- EXPECT_TRUE(file_util::CreateDirectory(kFSDir));
+ EXPECT_TRUE(base::CreateDirectory(kFSDir));
std::vector<SandboxOriginDatabase::OriginRecord> origins;
@@ -196,7 +197,7 @@ TEST(SandboxOriginDatabaseTest, DatabaseRecoveryTest) {
const base::FilePath kFSDir = dir.path().Append(kFileSystemDirName);
const base::FilePath kDBDir = kFSDir.Append(kOriginDatabaseName);
EXPECT_FALSE(base::PathExists(kFSDir));
- EXPECT_TRUE(file_util::CreateDirectory(kFSDir));
+ EXPECT_TRUE(base::CreateDirectory(kFSDir));
const std::string kOrigins[] = {
"foo.example.com",
@@ -216,13 +217,13 @@ TEST(SandboxOriginDatabaseTest, DatabaseRecoveryTest) {
EXPECT_TRUE(database->GetPathForOrigin(kOrigins[i], &path));
if (i != 1)
- EXPECT_TRUE(file_util::CreateDirectory(kFSDir.Append(path)));
+ EXPECT_TRUE(base::CreateDirectory(kFSDir.Append(path)));
}
database.reset();
const base::FilePath kGarbageDir = kFSDir.AppendASCII("foo");
const base::FilePath kGarbageFile = kGarbageDir.AppendASCII("bar");
- EXPECT_TRUE(file_util::CreateDirectory(kGarbageDir));
+ EXPECT_TRUE(base::CreateDirectory(kGarbageDir));
bool created = false;
base::PlatformFileError error;
base::PlatformFile file = base::CreatePlatformFile(
@@ -276,7 +277,7 @@ TEST(SandboxOriginDatabaseTest, DatabaseRecoveryForMissingDBFileTest) {
const base::FilePath kFSDir = dir.path().Append(kFileSystemDirName);
const base::FilePath kDBDir = kFSDir.Append(kOriginDatabaseName);
EXPECT_FALSE(base::PathExists(kFSDir));
- EXPECT_TRUE(file_util::CreateDirectory(kFSDir));
+ EXPECT_TRUE(base::CreateDirectory(kFSDir));
const std::string kOrigin = "foo.example.com";
base::FilePath path;
@@ -287,7 +288,7 @@ TEST(SandboxOriginDatabaseTest, DatabaseRecoveryForMissingDBFileTest) {
EXPECT_TRUE(database->GetPathForOrigin(kOrigin, &path));
EXPECT_FALSE(path.empty());
EXPECT_TRUE(database->GetPathForOrigin(kOrigin, &path));
- EXPECT_TRUE(file_util::CreateDirectory(kFSDir.Append(path)));
+ EXPECT_TRUE(base::CreateDirectory(kFSDir.Append(path)));
database.reset();
DeleteDatabaseFile(kDBDir, kLevelDBFileTypes[i]);
diff --git a/chromium/webkit/browser/fileapi/sandbox_prioritized_origin_database.cc b/chromium/webkit/browser/fileapi/sandbox_prioritized_origin_database.cc
new file mode 100644
index 00000000000..06a44a07080
--- /dev/null
+++ b/chromium/webkit/browser/fileapi/sandbox_prioritized_origin_database.cc
@@ -0,0 +1,229 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "webkit/browser/fileapi/sandbox_prioritized_origin_database.h"
+
+#include "base/file_util.h"
+#include "base/files/file_path.h"
+#include "base/files/scoped_platform_file_closer.h"
+#include "base/logging.h"
+#include "base/pickle.h"
+#include "base/platform_file.h"
+#include "webkit/browser/fileapi/sandbox_isolated_origin_database.h"
+#include "webkit/browser/fileapi/sandbox_origin_database.h"
+
+namespace fileapi {
+
+namespace {
+
+const base::FilePath::CharType kPrimaryDirectory[] =
+ FILE_PATH_LITERAL("primary");
+const base::FilePath::CharType kPrimaryOriginFile[] =
+ FILE_PATH_LITERAL("primary.origin");
+
+bool WritePrimaryOriginFile(const base::FilePath& path,
+ const std::string& origin) {
+ base::PlatformFileError error = base::PLATFORM_FILE_ERROR_FAILED;
+ bool created;
+ base::PlatformFile file = base::CreatePlatformFile(
+ path,
+ base::PLATFORM_FILE_OPEN_ALWAYS |
+ base::PLATFORM_FILE_WRITE,
+ &created, &error);
+ base::ScopedPlatformFileCloser closer(&file);
+ if (error != base::PLATFORM_FILE_OK ||
+ file == base::kInvalidPlatformFileValue)
+ return false;
+ base::TruncatePlatformFile(file, 0);
+ Pickle pickle;
+ pickle.WriteString(origin);
+ base::WritePlatformFile(file, 0, static_cast<const char*>(pickle.data()),
+ pickle.size());
+ base::FlushPlatformFile(file);
+ return true;
+}
+
+bool ReadPrimaryOriginFile(const base::FilePath& path,
+ std::string* origin) {
+ std::string buffer;
+ if (!base::ReadFileToString(path, &buffer))
+ return false;
+ Pickle pickle(buffer.data(), buffer.size());
+ PickleIterator iter(pickle);
+ return pickle.ReadString(&iter, origin) && !origin->empty();
+}
+
+} // namespace
+
+SandboxPrioritizedOriginDatabase::SandboxPrioritizedOriginDatabase(
+ const base::FilePath& file_system_directory)
+ : file_system_directory_(file_system_directory),
+ primary_origin_file_(
+ file_system_directory_.Append(kPrimaryOriginFile)) {
+}
+
+SandboxPrioritizedOriginDatabase::~SandboxPrioritizedOriginDatabase() {
+}
+
+bool SandboxPrioritizedOriginDatabase::InitializePrimaryOrigin(
+ const std::string& origin) {
+ if (!primary_origin_database_) {
+ if (!MaybeLoadPrimaryOrigin() && ResetPrimaryOrigin(origin)) {
+ MaybeMigrateDatabase(origin);
+ primary_origin_database_.reset(
+ new SandboxIsolatedOriginDatabase(
+ origin,
+ file_system_directory_,
+ base::FilePath(kPrimaryDirectory)));
+ return true;
+ }
+ }
+
+ if (primary_origin_database_)
+ return primary_origin_database_->HasOriginPath(origin);
+
+ return false;
+}
+
+std::string SandboxPrioritizedOriginDatabase::GetPrimaryOrigin() {
+ MaybeLoadPrimaryOrigin();
+ if (primary_origin_database_)
+ return primary_origin_database_->origin();
+ return std::string();
+}
+
+bool SandboxPrioritizedOriginDatabase::HasOriginPath(
+ const std::string& origin) {
+ MaybeInitializeDatabases(false);
+ if (primary_origin_database_ &&
+ primary_origin_database_->HasOriginPath(origin))
+ return true;
+ if (origin_database_)
+ return origin_database_->HasOriginPath(origin);
+ return false;
+}
+
+bool SandboxPrioritizedOriginDatabase::GetPathForOrigin(
+ const std::string& origin, base::FilePath* directory) {
+ MaybeInitializeDatabases(true);
+ if (primary_origin_database_ &&
+ primary_origin_database_->GetPathForOrigin(origin, directory))
+ return true;
+ DCHECK(origin_database_);
+ return origin_database_->GetPathForOrigin(origin, directory);
+}
+
+bool SandboxPrioritizedOriginDatabase::RemovePathForOrigin(
+ const std::string& origin) {
+ MaybeInitializeDatabases(false);
+ if (primary_origin_database_ &&
+ primary_origin_database_->HasOriginPath(origin)) {
+ primary_origin_database_.reset();
+ base::DeleteFile(file_system_directory_.Append(kPrimaryOriginFile),
+ true /* recursive */);
+ return true;
+ }
+ if (origin_database_)
+ return origin_database_->RemovePathForOrigin(origin);
+ return true;
+}
+
+bool SandboxPrioritizedOriginDatabase::ListAllOrigins(
+ std::vector<OriginRecord>* origins) {
+ // SandboxOriginDatabase may clear the |origins|, so call this before
+ // primary_origin_database_.
+ MaybeInitializeDatabases(false);
+ if (origin_database_ && !origin_database_->ListAllOrigins(origins))
+ return false;
+ if (primary_origin_database_)
+ return primary_origin_database_->ListAllOrigins(origins);
+ return true;
+}
+
+void SandboxPrioritizedOriginDatabase::DropDatabase() {
+ primary_origin_database_.reset();
+ origin_database_.reset();
+}
+
+bool SandboxPrioritizedOriginDatabase::MaybeLoadPrimaryOrigin() {
+ if (primary_origin_database_)
+ return true;
+ std::string saved_origin;
+ if (!ReadPrimaryOriginFile(primary_origin_file_, &saved_origin))
+ return false;
+ primary_origin_database_.reset(
+ new SandboxIsolatedOriginDatabase(
+ saved_origin,
+ file_system_directory_,
+ base::FilePath(kPrimaryDirectory)));
+ return true;
+}
+
+bool SandboxPrioritizedOriginDatabase::ResetPrimaryOrigin(
+ const std::string& origin) {
+ DCHECK(!primary_origin_database_);
+ if (!WritePrimaryOriginFile(primary_origin_file_, origin))
+ return false;
+ // We reset the primary origin directory too.
+ // (This means the origin file corruption causes data loss
+ // We could keep the directory there as the same origin will likely
+ // become the primary origin, but let's play conservatively.)
+ base::DeleteFile(file_system_directory_.Append(kPrimaryDirectory),
+ true /* recursive */);
+ return true;
+}
+
+void SandboxPrioritizedOriginDatabase::MaybeMigrateDatabase(
+ const std::string& origin) {
+ MaybeInitializeNonPrimaryDatabase(false);
+ if (!origin_database_)
+ return;
+ if (origin_database_->HasOriginPath(origin)) {
+ base::FilePath directory_name;
+ if (origin_database_->GetPathForOrigin(origin, &directory_name) &&
+ directory_name != base::FilePath(kPrimaryOriginFile)) {
+ base::FilePath from_path = file_system_directory_.Append(directory_name);
+ base::FilePath to_path = file_system_directory_.Append(kPrimaryDirectory);
+
+ if (base::PathExists(to_path))
+ base::DeleteFile(to_path, true /* recursive */);
+ base::Move(from_path, to_path);
+ }
+
+ origin_database_->RemovePathForOrigin(origin);
+ }
+
+ std::vector<OriginRecord> origins;
+ origin_database_->ListAllOrigins(&origins);
+ if (origins.empty()) {
+ origin_database_->RemoveDatabase();
+ origin_database_.reset();
+ }
+}
+
+void SandboxPrioritizedOriginDatabase::MaybeInitializeDatabases(
+ bool create) {
+ MaybeLoadPrimaryOrigin();
+ MaybeInitializeNonPrimaryDatabase(create);
+}
+
+void SandboxPrioritizedOriginDatabase::MaybeInitializeNonPrimaryDatabase(
+ bool create) {
+ if (origin_database_)
+ return;
+
+ origin_database_.reset(new SandboxOriginDatabase(file_system_directory_));
+ if (!create && !base::DirectoryExists(origin_database_->GetDatabasePath())) {
+ origin_database_.reset();
+ return;
+ }
+}
+
+SandboxOriginDatabase*
+SandboxPrioritizedOriginDatabase::GetSandboxOriginDatabase() {
+ MaybeInitializeNonPrimaryDatabase(true);
+ return origin_database_.get();
+}
+
+} // namespace fileapi
diff --git a/chromium/webkit/browser/fileapi/sandbox_prioritized_origin_database.h b/chromium/webkit/browser/fileapi/sandbox_prioritized_origin_database.h
new file mode 100644
index 00000000000..5509d0f75be
--- /dev/null
+++ b/chromium/webkit/browser/fileapi/sandbox_prioritized_origin_database.h
@@ -0,0 +1,67 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef WEBKIT_BROWSER_FILEAPI_SANDBOX_PRIORITIZED_ORIGIN_DATABASE_H_
+#define WEBKIT_BROWSER_FILEAPI_SANDBOX_PRIORITIZED_ORIGIN_DATABASE_H_
+
+#include <string>
+#include <vector>
+
+#include "base/memory/scoped_ptr.h"
+#include "webkit/browser/fileapi/sandbox_origin_database_interface.h"
+
+namespace fileapi {
+
+class ObfuscatedFileUtil;
+class SandboxIsolatedOriginDatabase;
+class SandboxOriginDatabase;
+
+class WEBKIT_STORAGE_BROWSER_EXPORT_PRIVATE SandboxPrioritizedOriginDatabase
+ : public SandboxOriginDatabaseInterface {
+ public:
+ explicit SandboxPrioritizedOriginDatabase(
+ const base::FilePath& file_system_directory);
+ virtual ~SandboxPrioritizedOriginDatabase();
+
+ // Sets |origin| as primary origin in this database (e.g. may
+ // allow faster access).
+ // Returns false if this database already has a primary origin
+ // which is different from |origin|.
+ bool InitializePrimaryOrigin(const std::string& origin);
+ std::string GetPrimaryOrigin();
+
+ // SandboxOriginDatabaseInterface overrides.
+ virtual bool HasOriginPath(const std::string& origin) OVERRIDE;
+ virtual bool GetPathForOrigin(const std::string& origin,
+ base::FilePath* directory) OVERRIDE;
+ virtual bool RemovePathForOrigin(const std::string& origin) OVERRIDE;
+ virtual bool ListAllOrigins(std::vector<OriginRecord>* origins) OVERRIDE;
+ virtual void DropDatabase() OVERRIDE;
+
+ const base::FilePath& primary_origin_file() const {
+ return primary_origin_file_;
+ }
+
+ private:
+ bool MaybeLoadPrimaryOrigin();
+ bool ResetPrimaryOrigin(const std::string& origin);
+ void MaybeMigrateDatabase(const std::string& origin);
+ void MaybeInitializeDatabases(bool create);
+ void MaybeInitializeNonPrimaryDatabase(bool create);
+
+ // For migration.
+ friend class ObfuscatedFileUtil;
+ SandboxOriginDatabase* GetSandboxOriginDatabase();
+
+ const base::FilePath file_system_directory_;
+ const base::FilePath primary_origin_file_;
+ scoped_ptr<SandboxOriginDatabase> origin_database_;
+ scoped_ptr<SandboxIsolatedOriginDatabase> primary_origin_database_;
+
+ DISALLOW_COPY_AND_ASSIGN(SandboxPrioritizedOriginDatabase);
+};
+
+} // namespace fileapi
+
+#endif // WEBKIT_BROWSER_FILEAPI_SANDBOX_PRIORITIZED_ORIGIN_DATABASE_H_
diff --git a/chromium/webkit/browser/fileapi/sandbox_prioritized_origin_database_unittest.cc b/chromium/webkit/browser/fileapi/sandbox_prioritized_origin_database_unittest.cc
new file mode 100644
index 00000000000..fc0b9589d85
--- /dev/null
+++ b/chromium/webkit/browser/fileapi/sandbox_prioritized_origin_database_unittest.cc
@@ -0,0 +1,215 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/basictypes.h"
+#include "base/file_util.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/platform_file.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "webkit/browser/fileapi/sandbox_origin_database.h"
+#include "webkit/browser/fileapi/sandbox_prioritized_origin_database.h"
+
+namespace fileapi {
+
+TEST(SandboxPrioritizedOriginDatabaseTest, BasicTest) {
+ base::ScopedTempDir dir;
+ base::FilePath path;
+ ASSERT_TRUE(dir.CreateUniqueTempDir());
+
+ const std::string kOrigin1("origin1");
+ const std::string kOrigin2("origin2");
+
+ SandboxPrioritizedOriginDatabase database(dir.path());
+
+ // Set the kOrigin1 as a parimary origin.
+ EXPECT_TRUE(database.InitializePrimaryOrigin(kOrigin1));
+
+ // Add two origins.
+ EXPECT_TRUE(database.GetPathForOrigin(kOrigin1, &path));
+ EXPECT_TRUE(database.GetPathForOrigin(kOrigin2, &path));
+
+ // Verify them.
+ EXPECT_TRUE(database.HasOriginPath(kOrigin1));
+ EXPECT_TRUE(database.GetPathForOrigin(kOrigin1, &path));
+ EXPECT_FALSE(path.empty());
+ EXPECT_TRUE(database.HasOriginPath(kOrigin2));
+ EXPECT_TRUE(database.GetPathForOrigin(kOrigin2, &path));
+ EXPECT_FALSE(path.empty());
+
+ std::vector<SandboxOriginDatabaseInterface::OriginRecord> origins;
+ database.ListAllOrigins(&origins);
+ ASSERT_EQ(2U, origins.size());
+ EXPECT_TRUE(origins[0].origin == kOrigin1 ||
+ origins[1].origin == kOrigin1);
+ EXPECT_TRUE(origins[0].origin == kOrigin2 ||
+ origins[1].origin == kOrigin2);
+ EXPECT_NE(origins[0].path, origins[1].path);
+
+ // Try remove path for kOrigin1.
+ database.RemovePathForOrigin(kOrigin1);
+
+ // Verify the removal.
+ EXPECT_FALSE(database.HasOriginPath(kOrigin1));
+ EXPECT_TRUE(database.HasOriginPath(kOrigin2));
+ database.ListAllOrigins(&origins);
+ ASSERT_EQ(1U, origins.size());
+ EXPECT_EQ(kOrigin2, origins[0].origin);
+
+ // Try remove path for kOrigin2.
+ database.RemovePathForOrigin(kOrigin2);
+
+ // Verify the removal.
+ EXPECT_FALSE(database.HasOriginPath(kOrigin1));
+ EXPECT_FALSE(database.HasOriginPath(kOrigin2));
+ database.ListAllOrigins(&origins);
+ EXPECT_TRUE(origins.empty());
+}
+
+TEST(SandboxPrioritizedOriginDatabaseTest, SetPrimaryLaterTest) {
+ base::ScopedTempDir dir;
+ base::FilePath path;
+ ASSERT_TRUE(dir.CreateUniqueTempDir());
+
+ const std::string kOrigin1("origin1");
+ const std::string kOrigin2("origin2");
+
+ SandboxPrioritizedOriginDatabase database(dir.path());
+
+ EXPECT_TRUE(database.GetPrimaryOrigin().empty());
+
+ EXPECT_TRUE(database.GetPathForOrigin(kOrigin1, &path));
+ EXPECT_TRUE(database.GetPathForOrigin(kOrigin2, &path));
+
+ // Set the kOrigin1 as a parimary origin.
+ EXPECT_TRUE(database.InitializePrimaryOrigin(kOrigin1));
+ EXPECT_EQ(kOrigin1, database.GetPrimaryOrigin());
+
+ // Regardless of whether it is initialized as primary or not
+ // they should just work.
+ EXPECT_TRUE(database.HasOriginPath(kOrigin1));
+ EXPECT_TRUE(database.GetPathForOrigin(kOrigin1, &path));
+ EXPECT_FALSE(path.empty());
+ EXPECT_TRUE(database.HasOriginPath(kOrigin2));
+ EXPECT_TRUE(database.GetPathForOrigin(kOrigin2, &path));
+ EXPECT_FALSE(path.empty());
+}
+
+TEST(SandboxPrioritizedOriginDatabaseTest, LostPrimaryOriginFileTest) {
+ base::ScopedTempDir dir;
+ base::FilePath path;
+ ASSERT_TRUE(dir.CreateUniqueTempDir());
+
+ const std::string kOrigin1("origin1");
+ const std::string kData("foo");
+
+ SandboxPrioritizedOriginDatabase database(dir.path());
+
+ EXPECT_TRUE(database.GetPrimaryOrigin().empty());
+
+ // Set the kOrigin1 as a parimary origin.
+ EXPECT_TRUE(database.InitializePrimaryOrigin(kOrigin1));
+ EXPECT_EQ(kOrigin1, database.GetPrimaryOrigin());
+
+ // Make sure it works.
+ EXPECT_TRUE(database.HasOriginPath(kOrigin1));
+ EXPECT_TRUE(database.GetPathForOrigin(kOrigin1, &path));
+
+ // Reset the database.
+ database.DropDatabase();
+
+ // kOrigin1 should still be marked as primary.
+ EXPECT_TRUE(database.HasOriginPath(kOrigin1));
+ EXPECT_TRUE(database.GetPathForOrigin(kOrigin1, &path));
+
+ // Corrupt the primary origin file.
+ file_util::WriteFile(
+ database.primary_origin_file(), kData.data(), kData.size());
+
+ // Reset the database.
+ database.DropDatabase();
+
+ // kOrigin1 is no longer marked as primary, and unfortunately we fail
+ // to find the data for the origin.
+ EXPECT_FALSE(database.HasOriginPath(kOrigin1));
+}
+
+TEST(SandboxPrioritizedOriginDatabaseTest, MigrationTest) {
+ base::ScopedTempDir dir;
+ ASSERT_TRUE(dir.CreateUniqueTempDir());
+
+ const std::string kOrigin1("origin1");
+ const std::string kOrigin2("origin2");
+ const std::string kFakeDirectoryData1("0123456789");
+ const std::string kFakeDirectoryData2("abcde");
+ base::FilePath old_dir_db_path1, old_dir_db_path2;
+ base::FilePath path1, path2;
+
+ // Initialize the directory with two origins using the regular
+ // SandboxOriginDatabase.
+ {
+ SandboxOriginDatabase database_old(dir.path());
+ base::FilePath old_db_path = database_old.GetDatabasePath();
+ EXPECT_FALSE(base::PathExists(old_db_path));
+
+ // Initialize paths for kOrigin1 and kOrigin2.
+ EXPECT_TRUE(database_old.GetPathForOrigin(kOrigin1, &path1));
+ EXPECT_FALSE(path1.empty());
+ EXPECT_TRUE(database_old.GetPathForOrigin(kOrigin2, &path2));
+ EXPECT_FALSE(path2.empty());
+
+ EXPECT_TRUE(base::DirectoryExists(old_db_path));
+
+ // Populate the origin directory with some fake data.
+ old_dir_db_path1 = dir.path().Append(path1);
+ ASSERT_TRUE(base::CreateDirectory(old_dir_db_path1));
+ EXPECT_EQ(static_cast<int>(kFakeDirectoryData1.size()),
+ file_util::WriteFile(old_dir_db_path1.AppendASCII("dummy"),
+ kFakeDirectoryData1.data(),
+ kFakeDirectoryData1.size()));
+ old_dir_db_path2 = dir.path().Append(path2);
+ ASSERT_TRUE(base::CreateDirectory(old_dir_db_path2));
+ EXPECT_EQ(static_cast<int>(kFakeDirectoryData2.size()),
+ file_util::WriteFile(old_dir_db_path2.AppendASCII("dummy"),
+ kFakeDirectoryData2.data(),
+ kFakeDirectoryData2.size()));
+ }
+
+ // Re-open the directory using sandboxPrioritizedOriginDatabase.
+ SandboxPrioritizedOriginDatabase database(dir.path());
+
+ // Set the kOrigin1 as a parimary origin.
+ // (Trying to initialize another origin should fail).
+ EXPECT_TRUE(database.InitializePrimaryOrigin(kOrigin1));
+ EXPECT_FALSE(database.InitializePrimaryOrigin(kOrigin2));
+
+ EXPECT_EQ(kOrigin1, database.GetPrimaryOrigin());
+
+ // Regardless of whether the origin is registered as primary or not
+ // it should just work.
+ EXPECT_TRUE(database.HasOriginPath(kOrigin1));
+ EXPECT_TRUE(database.GetPathForOrigin(kOrigin1, &path1));
+ EXPECT_TRUE(database.HasOriginPath(kOrigin2));
+ EXPECT_TRUE(database.GetPathForOrigin(kOrigin2, &path2));
+
+ // The directory content must be kept (or migrated if necessary) as well.
+ std::string origin_db_data;
+ base::FilePath dir_db_path = dir.path().Append(path1);
+ EXPECT_TRUE(base::PathExists(dir_db_path.AppendASCII("dummy")));
+ EXPECT_TRUE(base::ReadFileToString(
+ dir_db_path.AppendASCII("dummy"), &origin_db_data));
+ EXPECT_EQ(kFakeDirectoryData1, origin_db_data);
+
+ origin_db_data.clear();
+ dir_db_path = dir.path().Append(path2);
+ EXPECT_TRUE(base::PathExists(dir_db_path.AppendASCII("dummy")));
+ EXPECT_TRUE(base::ReadFileToString(
+ dir_db_path.AppendASCII("dummy"), &origin_db_data));
+ EXPECT_EQ(kFakeDirectoryData2, origin_db_data);
+
+ // After the migration the kOrigin1 directory database path must be gone.
+ EXPECT_FALSE(base::PathExists(old_dir_db_path1));
+ EXPECT_TRUE(base::PathExists(old_dir_db_path2));
+}
+
+} // namespace fileapi
diff --git a/chromium/webkit/browser/fileapi/test_file_set.cc b/chromium/webkit/browser/fileapi/test_file_set.cc
index 7b0b0f0a7b7..109a0558491 100644
--- a/chromium/webkit/browser/fileapi/test_file_set.cc
+++ b/chromium/webkit/browser/fileapi/test_file_set.cc
@@ -43,7 +43,7 @@ void SetUpOneTestCase(const base::FilePath& root_path,
const TestCaseRecord& test_case) {
base::FilePath path = root_path.Append(test_case.path);
if (test_case.is_directory) {
- ASSERT_TRUE(file_util::CreateDirectory(path));
+ ASSERT_TRUE(base::CreateDirectory(path));
return;
}
base::PlatformFileError error_code;
diff --git a/chromium/webkit/browser/fileapi/test_file_set.h b/chromium/webkit/browser/fileapi/test_file_set.h
index 59e90ab6e0a..eb44521357a 100644
--- a/chromium/webkit/browser/fileapi/test_file_set.h
+++ b/chromium/webkit/browser/fileapi/test_file_set.h
@@ -29,7 +29,8 @@ extern const size_t kRegularTestCaseSize;
size_t GetRegularTestCaseSize();
// Creates one file or directory specified by |record|.
-void SetUpOneTestCase(const base::FilePath& root_path, const TestCaseRecord& record);
+void SetUpOneTestCase(const base::FilePath& root_path,
+ const TestCaseRecord& record);
// Creates the files and directories specified in kRegularTestCases.
void SetUpRegularTestCases(const base::FilePath& root_path);
diff --git a/chromium/webkit/browser/fileapi/test_file_system_backend.cc b/chromium/webkit/browser/fileapi/test_file_system_backend.cc
deleted file mode 100644
index 44109cf6148..00000000000
--- a/chromium/webkit/browser/fileapi/test_file_system_backend.cc
+++ /dev/null
@@ -1,247 +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/browser/fileapi/test_file_system_backend.h"
-
-#include <set>
-#include <string>
-#include <vector>
-
-#include "base/file_util.h"
-#include "base/sequenced_task_runner.h"
-#include "webkit/browser/blob/file_stream_reader.h"
-#include "webkit/browser/fileapi/copy_or_move_file_validator.h"
-#include "webkit/browser/fileapi/file_observers.h"
-#include "webkit/browser/fileapi/file_system_operation.h"
-#include "webkit/browser/fileapi/file_system_operation_context.h"
-#include "webkit/browser/fileapi/file_system_quota_util.h"
-#include "webkit/browser/fileapi/local_file_util.h"
-#include "webkit/browser/fileapi/native_file_util.h"
-#include "webkit/browser/fileapi/sandbox_file_stream_writer.h"
-#include "webkit/browser/quota/quota_manager.h"
-#include "webkit/common/fileapi/file_system_util.h"
-
-namespace fileapi {
-
-namespace {
-
-class TestFileUtil : public LocalFileUtil {
- public:
- explicit TestFileUtil(const base::FilePath& base_path)
- : base_path_(base_path) {}
- virtual ~TestFileUtil() {}
-
- // LocalFileUtil overrides.
- virtual base::PlatformFileError GetLocalFilePath(
- FileSystemOperationContext* context,
- const FileSystemURL& file_system_url,
- base::FilePath* local_file_path) OVERRIDE {
- *local_file_path = base_path_.Append(file_system_url.path());
- return base::PLATFORM_FILE_OK;
- }
-
- private:
- base::FilePath base_path_;
-};
-
-} // namespace
-
-// This only supports single origin.
-class TestFileSystemBackend::QuotaUtil
- : public FileSystemQuotaUtil,
- public FileUpdateObserver {
- public:
- QuotaUtil(base::SequencedTaskRunner* task_runner)
- : usage_(0),
- task_runner_(task_runner) {
- update_observers_ = update_observers_.AddObserver(this, task_runner_.get());
- }
- virtual ~QuotaUtil() {}
-
- // FileSystemQuotaUtil overrides.
- virtual base::PlatformFileError DeleteOriginDataOnFileThread(
- FileSystemContext* context,
- quota::QuotaManagerProxy* proxy,
- const GURL& origin_url,
- FileSystemType type) OVERRIDE {
- NOTREACHED();
- return base::PLATFORM_FILE_OK;
- }
-
- virtual void GetOriginsForTypeOnFileThread(
- FileSystemType type,
- std::set<GURL>* origins) OVERRIDE {
- NOTREACHED();
- }
-
- virtual void GetOriginsForHostOnFileThread(
- FileSystemType type,
- const std::string& host,
- std::set<GURL>* origins) OVERRIDE {
- NOTREACHED();
- }
-
- virtual int64 GetOriginUsageOnFileThread(
- FileSystemContext* context,
- const GURL& origin_url,
- FileSystemType type) OVERRIDE {
- return usage_;
- }
-
- virtual void AddFileUpdateObserver(
- FileSystemType type,
- FileUpdateObserver* observer,
- base::SequencedTaskRunner* task_runner) OVERRIDE {
- NOTIMPLEMENTED();
- }
-
- virtual void AddFileChangeObserver(
- FileSystemType type,
- FileChangeObserver* observer,
- base::SequencedTaskRunner* task_runner) OVERRIDE {
- change_observers_ = change_observers_.AddObserver(observer, task_runner);
- }
-
- virtual void AddFileAccessObserver(
- FileSystemType type,
- FileAccessObserver* observer,
- base::SequencedTaskRunner* task_runner) OVERRIDE {
- NOTIMPLEMENTED();
- }
-
- virtual const UpdateObserverList* GetUpdateObservers(
- FileSystemType type) const OVERRIDE {
- return &update_observers_;
- }
-
- virtual const ChangeObserverList* GetChangeObservers(
- FileSystemType type) const OVERRIDE {
- return &change_observers_;
- }
-
- virtual const AccessObserverList* GetAccessObservers(
- FileSystemType type) const OVERRIDE {
- NOTIMPLEMENTED();
- return NULL;
- }
-
- // FileUpdateObserver overrides.
- virtual void OnStartUpdate(const FileSystemURL& url) OVERRIDE {}
- virtual void OnUpdate(const FileSystemURL& url, int64 delta) OVERRIDE {
- usage_ += delta;
- }
- virtual void OnEndUpdate(const FileSystemURL& url) OVERRIDE {}
-
- base::SequencedTaskRunner* task_runner() { return task_runner_.get(); }
-
- private:
- int64 usage_;
-
- scoped_refptr<base::SequencedTaskRunner> task_runner_;
-
- UpdateObserverList update_observers_;
- ChangeObserverList change_observers_;
-};
-
-TestFileSystemBackend::TestFileSystemBackend(
- base::SequencedTaskRunner* task_runner,
- const base::FilePath& base_path)
- : base_path_(base_path),
- file_util_(new AsyncFileUtilAdapter(new TestFileUtil(base_path))),
- quota_util_(new QuotaUtil(task_runner)),
- require_copy_or_move_validator_(false) {
-}
-
-TestFileSystemBackend::~TestFileSystemBackend() {
-}
-
-bool TestFileSystemBackend::CanHandleType(FileSystemType type) const {
- return (type == kFileSystemTypeTest);
-}
-
-void TestFileSystemBackend::Initialize(FileSystemContext* context) {
-}
-
-void TestFileSystemBackend::OpenFileSystem(
- const GURL& origin_url,
- FileSystemType type,
- OpenFileSystemMode mode,
- const OpenFileSystemCallback& callback) {
- callback.Run(GetFileSystemRootURI(origin_url, type),
- GetFileSystemName(origin_url, type),
- base::PLATFORM_FILE_OK);
-}
-
-AsyncFileUtil* TestFileSystemBackend::GetAsyncFileUtil(FileSystemType type) {
- return file_util_.get();
-}
-
-CopyOrMoveFileValidatorFactory*
-TestFileSystemBackend::GetCopyOrMoveFileValidatorFactory(
- FileSystemType type, base::PlatformFileError* error_code) {
- DCHECK(error_code);
- *error_code = base::PLATFORM_FILE_OK;
- if (require_copy_or_move_validator_) {
- if (!copy_or_move_file_validator_factory_)
- *error_code = base::PLATFORM_FILE_ERROR_SECURITY;
- return copy_or_move_file_validator_factory_.get();
- }
- return NULL;
-}
-
-void TestFileSystemBackend::InitializeCopyOrMoveFileValidatorFactory(
- scoped_ptr<CopyOrMoveFileValidatorFactory> factory) {
- if (!copy_or_move_file_validator_factory_)
- copy_or_move_file_validator_factory_ = factory.Pass();
-}
-
-FileSystemOperation* TestFileSystemBackend::CreateFileSystemOperation(
- const FileSystemURL& url,
- FileSystemContext* context,
- base::PlatformFileError* error_code) const {
- scoped_ptr<FileSystemOperationContext> operation_context(
- new FileSystemOperationContext(context));
- operation_context->set_update_observers(*GetUpdateObservers(url.type()));
- operation_context->set_change_observers(
- *quota_util_->GetChangeObservers(url.type()));
- return FileSystemOperation::Create(url, context, operation_context.Pass());
-}
-
-scoped_ptr<webkit_blob::FileStreamReader>
-TestFileSystemBackend::CreateFileStreamReader(
- const FileSystemURL& url,
- int64 offset,
- const base::Time& expected_modification_time,
- FileSystemContext* context) const {
- return scoped_ptr<webkit_blob::FileStreamReader>(
- webkit_blob::FileStreamReader::CreateForFileSystemFile(
- context, url, offset, expected_modification_time));
-}
-
-scoped_ptr<fileapi::FileStreamWriter>
-TestFileSystemBackend::CreateFileStreamWriter(
- const FileSystemURL& url,
- int64 offset,
- FileSystemContext* context) const {
- return scoped_ptr<fileapi::FileStreamWriter>(
- new SandboxFileStreamWriter(context, url, offset,
- *GetUpdateObservers(url.type())));
-}
-
-FileSystemQuotaUtil* TestFileSystemBackend::GetQuotaUtil() {
- return quota_util_.get();
-}
-
-const UpdateObserverList* TestFileSystemBackend::GetUpdateObservers(
- FileSystemType type) const {
- return quota_util_->GetUpdateObservers(type);
-}
-
-void TestFileSystemBackend::AddFileChangeObserver(
- FileChangeObserver* observer) {
- quota_util_->AddFileChangeObserver(
- kFileSystemTypeTest, observer, quota_util_->task_runner());
-}
-
-} // namespace fileapi
diff --git a/chromium/webkit/browser/fileapi/test_file_system_backend.h b/chromium/webkit/browser/fileapi/test_file_system_backend.h
deleted file mode 100644
index dc1cbce2298..00000000000
--- a/chromium/webkit/browser/fileapi/test_file_system_backend.h
+++ /dev/null
@@ -1,95 +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_BROWSER_FILEAPI_TEST_FILE_SYSTEM_BACKEND_H_
-#define WEBKIT_BROWSER_FILEAPI_TEST_FILE_SYSTEM_BACKEND_H_
-
-#include "base/files/file_path.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
-#include "webkit/browser/fileapi/async_file_util_adapter.h"
-#include "webkit/browser/fileapi/file_system_backend.h"
-#include "webkit/browser/fileapi/task_runner_bound_observer_list.h"
-#include "webkit/browser/webkit_storage_browser_export.h"
-
-namespace base {
-class SequencedTaskRunner;
-}
-
-namespace fileapi {
-
-class AsyncFileUtilAdapter;
-class FileSystemQuotaUtil;
-
-// This should be only used for testing.
-// This file system backend uses LocalFileUtil and stores data file
-// under the given directory.
-class WEBKIT_STORAGE_BROWSER_EXPORT_PRIVATE TestFileSystemBackend
- : public FileSystemBackend {
- public:
- TestFileSystemBackend(
- base::SequencedTaskRunner* task_runner,
- const base::FilePath& base_path);
- virtual ~TestFileSystemBackend();
-
- // FileSystemBackend implementation.
- virtual bool CanHandleType(FileSystemType type) const OVERRIDE;
- virtual void Initialize(FileSystemContext* context) OVERRIDE;
- virtual void OpenFileSystem(
- const GURL& origin_url,
- FileSystemType type,
- OpenFileSystemMode mode,
- const OpenFileSystemCallback& callback) OVERRIDE;
- virtual AsyncFileUtil* GetAsyncFileUtil(FileSystemType type) OVERRIDE;
- virtual CopyOrMoveFileValidatorFactory* GetCopyOrMoveFileValidatorFactory(
- FileSystemType type,
- base::PlatformFileError* error_code) OVERRIDE;
- virtual FileSystemOperation* CreateFileSystemOperation(
- const FileSystemURL& url,
- FileSystemContext* context,
- base::PlatformFileError* error_code) const OVERRIDE;
- virtual scoped_ptr<webkit_blob::FileStreamReader> CreateFileStreamReader(
- const FileSystemURL& url,
- int64 offset,
- const base::Time& expected_modification_time,
- FileSystemContext* context) const OVERRIDE;
- virtual scoped_ptr<FileStreamWriter> CreateFileStreamWriter(
- const FileSystemURL& url,
- int64 offset,
- FileSystemContext* context) const OVERRIDE;
- virtual FileSystemQuotaUtil* GetQuotaUtil() OVERRIDE;
-
- // Initialize the CopyOrMoveFileValidatorFactory. Invalid to call more than
- // once.
- void InitializeCopyOrMoveFileValidatorFactory(
- scoped_ptr<CopyOrMoveFileValidatorFactory> factory);
-
- const UpdateObserverList* GetUpdateObservers(FileSystemType type) const;
- void AddFileChangeObserver(FileChangeObserver* observer);
-
- // For CopyOrMoveFileValidatorFactory testing. Once it's set to true
- // GetCopyOrMoveFileValidatorFactory will start returning security
- // error if validator is not initialized.
- void set_require_copy_or_move_validator(bool flag) {
- require_copy_or_move_validator_ = flag;
- }
-
- private:
- class QuotaUtil;
-
- base::FilePath base_path_;
- scoped_refptr<base::SequencedTaskRunner> task_runner_;
- scoped_ptr<AsyncFileUtilAdapter> file_util_;
- scoped_ptr<QuotaUtil> quota_util_;
-
- bool require_copy_or_move_validator_;
- scoped_ptr<CopyOrMoveFileValidatorFactory>
- copy_or_move_file_validator_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(TestFileSystemBackend);
-};
-
-} // namespace fileapi
-
-#endif // WEBKIT_BROWSER_FILEAPI_TEST_FILE_SYSTEM_BACKEND_H_
diff --git a/chromium/webkit/browser/fileapi/transient_file_util_unittest.cc b/chromium/webkit/browser/fileapi/transient_file_util_unittest.cc
deleted file mode 100644
index 3b6e284070d..00000000000
--- a/chromium/webkit/browser/fileapi/transient_file_util_unittest.cc
+++ /dev/null
@@ -1,122 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/basictypes.h"
-#include "base/file_util.h"
-#include "base/files/file_path.h"
-#include "base/files/scoped_temp_dir.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/platform_file.h"
-#include "base/run_loop.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "webkit/browser/fileapi/file_system_context.h"
-#include "webkit/browser/fileapi/file_system_operation_context.h"
-#include "webkit/browser/fileapi/isolated_context.h"
-#include "webkit/browser/fileapi/mock_file_system_context.h"
-#include "webkit/browser/fileapi/transient_file_util.h"
-#include "webkit/common/blob/scoped_file.h"
-
-namespace fileapi {
-
-class TransientFileUtilTest : public testing::Test {
- public:
- TransientFileUtilTest() {}
- virtual ~TransientFileUtilTest() {}
-
- virtual void SetUp() OVERRIDE {
- file_system_context_ = CreateFileSystemContextForTesting(
- NULL, base::FilePath(FILE_PATH_LITERAL("dummy")));
- transient_file_util_.reset(new TransientFileUtil);
-
- ASSERT_TRUE(data_dir_.CreateUniqueTempDir());
- }
-
- virtual void TearDown() OVERRIDE {
- file_system_context_ = NULL;
- base::RunLoop().RunUntilIdle();
- }
-
- void CreateAndRegisterTemporaryFile(
- FileSystemURL* file_url,
- base::FilePath* file_path) {
- EXPECT_TRUE(
- file_util::CreateTemporaryFileInDir(data_dir_.path(), file_path));
- IsolatedContext* isolated_context = IsolatedContext::GetInstance();
- std::string name = "tmp";
- std::string fsid = isolated_context->RegisterFileSystemForPath(
- kFileSystemTypeForTransientFile,
- *file_path,
- &name);
- ASSERT_TRUE(!fsid.empty());
- base::FilePath virtual_path = isolated_context->CreateVirtualRootPath(
- fsid).AppendASCII(name);
- *file_url = file_system_context_->CreateCrackedFileSystemURL(
- GURL("http://foo"),
- kFileSystemTypeIsolated,
- virtual_path);
- }
-
- scoped_ptr<FileSystemOperationContext> NewOperationContext() {
- return make_scoped_ptr(
- new FileSystemOperationContext(file_system_context_.get()));
- }
-
- FileSystemFileUtil* file_util() { return transient_file_util_.get(); }
-
- private:
- base::MessageLoop message_loop_;
- base::ScopedTempDir data_dir_;
- scoped_refptr<FileSystemContext> file_system_context_;
- scoped_ptr<TransientFileUtil> transient_file_util_;
-
- DISALLOW_COPY_AND_ASSIGN(TransientFileUtilTest);
-};
-
-TEST_F(TransientFileUtilTest, TransientFile) {
- FileSystemURL temp_url;
- base::FilePath temp_path;
-
- CreateAndRegisterTemporaryFile(&temp_url, &temp_path);
-
- base::PlatformFileError error;
- base::PlatformFileInfo file_info;
- base::FilePath path;
-
- // Make sure the file is there.
- ASSERT_TRUE(temp_url.is_valid());
- ASSERT_TRUE(base::PathExists(temp_path));
- ASSERT_FALSE(base::DirectoryExists(temp_path));
-
- // Create a snapshot file.
- {
- webkit_blob::ScopedFile scoped_file =
- file_util()->CreateSnapshotFile(NewOperationContext().get(),
- temp_url,
- &error,
- &file_info,
- &path);
- ASSERT_EQ(base::PLATFORM_FILE_OK, error);
- ASSERT_EQ(temp_path, path);
- ASSERT_FALSE(file_info.is_directory);
-
- // The file should be still there.
- ASSERT_TRUE(base::PathExists(temp_path));
- ASSERT_EQ(base::PLATFORM_FILE_OK,
- file_util()->GetFileInfo(NewOperationContext().get(),
- temp_url, &file_info, &path));
- ASSERT_EQ(temp_path, path);
- ASSERT_FALSE(file_info.is_directory);
- }
-
- // The file's now scoped out.
- base::RunLoop().RunUntilIdle();
-
- // Now the temporary file and the transient filesystem must be gone too.
- ASSERT_FALSE(base::PathExists(temp_path));
- ASSERT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND,
- file_util()->GetFileInfo(NewOperationContext().get(),
- temp_url, &file_info, &path));
-}
-
-} // namespace fileapi
diff --git a/chromium/webkit/browser/fileapi/upload_file_system_file_element_reader.cc b/chromium/webkit/browser/fileapi/upload_file_system_file_element_reader.cc
index 3fb5ab4d31e..46a57f0957a 100644
--- a/chromium/webkit/browser/fileapi/upload_file_system_file_element_reader.cc
+++ b/chromium/webkit/browser/fileapi/upload_file_system_file_element_reader.cc
@@ -4,6 +4,8 @@
#include "webkit/browser/fileapi/upload_file_system_file_element_reader.h"
+#include <algorithm>
+
#include "base/bind.h"
#include "net/base/net_errors.h"
#include "webkit/browser/blob/file_stream_reader.h"
diff --git a/chromium/webkit/browser/fileapi/upload_file_system_file_element_reader_unittest.cc b/chromium/webkit/browser/fileapi/upload_file_system_file_element_reader_unittest.cc
deleted file mode 100644
index 429edf2fe05..00000000000
--- a/chromium/webkit/browser/fileapi/upload_file_system_file_element_reader_unittest.cc
+++ /dev/null
@@ -1,278 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "webkit/browser/fileapi/upload_file_system_file_element_reader.h"
-
-#include "base/files/scoped_temp_dir.h"
-#include "base/run_loop.h"
-#include "net/base/io_buffer.h"
-#include "net/base/test_completion_callback.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "webkit/browser/fileapi/async_file_test_helper.h"
-#include "webkit/browser/fileapi/file_system_backend.h"
-#include "webkit/browser/fileapi/file_system_context.h"
-#include "webkit/browser/fileapi/file_system_operation_context.h"
-#include "webkit/browser/fileapi/file_system_url.h"
-#include "webkit/browser/fileapi/mock_file_system_context.h"
-
-namespace fileapi {
-
-namespace {
-
-const char kFileSystemURLOrigin[] = "http://remote";
-const fileapi::FileSystemType kFileSystemType =
- fileapi::kFileSystemTypeTemporary;
-
-} // namespace
-
-class UploadFileSystemFileElementReaderTest : public testing::Test {
- public:
- UploadFileSystemFileElementReaderTest()
- : message_loop_(base::MessageLoop::TYPE_IO) {}
-
- virtual void SetUp() OVERRIDE {
- ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
-
- file_system_context_ = fileapi::CreateFileSystemContextForTesting(
- NULL, temp_dir_.path());
-
- file_system_context_->OpenFileSystem(
- GURL(kFileSystemURLOrigin),
- kFileSystemType,
- OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
- base::Bind(&UploadFileSystemFileElementReaderTest::OnOpenFileSystem,
- base::Unretained(this)));
- base::RunLoop().RunUntilIdle();
- ASSERT_TRUE(file_system_root_url_.is_valid());
-
- // Prepare a file on file system.
- const char kTestData[] = "abcdefghijklmnop0123456789";
- file_data_.assign(kTestData, kTestData + arraysize(kTestData) - 1);
- const char kFilename[] = "File.dat";
- file_url_ = GetFileSystemURL(kFilename);
- WriteFileSystemFile(kFilename, &file_data_[0], file_data_.size(),
- &file_modification_time_);
-
- // Create and initialize a reader.
- reader_.reset(
- new UploadFileSystemFileElementReader(file_system_context_.get(),
- file_url_,
- 0,
- kuint64max,
- file_modification_time_));
- net::TestCompletionCallback callback;
- ASSERT_EQ(net::ERR_IO_PENDING, reader_->Init(callback.callback()));
- EXPECT_EQ(net::OK, callback.WaitForResult());
- EXPECT_EQ(file_data_.size(), reader_->GetContentLength());
- EXPECT_EQ(file_data_.size(), reader_->BytesRemaining());
- EXPECT_FALSE(reader_->IsInMemory());
- }
-
- virtual void TearDown() OVERRIDE {
- reader_.reset();
- base::RunLoop().RunUntilIdle();
- }
-
- protected:
- GURL GetFileSystemURL(const std::string& filename) {
- return GURL(file_system_root_url_.spec() + filename);
- }
-
- void WriteFileSystemFile(const std::string& filename,
- const char* buf,
- int buf_size,
- base::Time* modification_time) {
- fileapi::FileSystemURL url =
- file_system_context_->CreateCrackedFileSystemURL(
- GURL(kFileSystemURLOrigin),
- kFileSystemType,
- base::FilePath().AppendASCII(filename));
-
- ASSERT_EQ(base::PLATFORM_FILE_OK,
- AsyncFileTestHelper::CreateFileWithData(
- file_system_context_, url, buf, buf_size));
-
- base::PlatformFileInfo file_info;
- ASSERT_EQ(base::PLATFORM_FILE_OK,
- AsyncFileTestHelper::GetMetadata(
- file_system_context_, url, &file_info));
- *modification_time = file_info.last_modified;
- }
-
- void OnOpenFileSystem(base::PlatformFileError result,
- const std::string& name,
- const GURL& root) {
- ASSERT_EQ(base::PLATFORM_FILE_OK, result);
- ASSERT_TRUE(root.is_valid());
- file_system_root_url_ = root;
- }
-
- base::MessageLoop message_loop_;
- base::ScopedTempDir temp_dir_;
- scoped_refptr<FileSystemContext> file_system_context_;
- GURL file_system_root_url_;
- std::vector<char> file_data_;
- GURL file_url_;
- base::Time file_modification_time_;
- scoped_ptr<UploadFileSystemFileElementReader> reader_;
-};
-
-TEST_F(UploadFileSystemFileElementReaderTest, ReadAll) {
- scoped_refptr<net::IOBufferWithSize> buf =
- new net::IOBufferWithSize(file_data_.size());
- net::TestCompletionCallback read_callback;
- ASSERT_EQ(net::ERR_IO_PENDING,
- reader_->Read(buf.get(), buf->size(), read_callback.callback()));
- EXPECT_EQ(buf->size(), read_callback.WaitForResult());
- EXPECT_EQ(0U, reader_->BytesRemaining());
- EXPECT_TRUE(std::equal(file_data_.begin(), file_data_.end(), buf->data()));
- // Try to read again.
- EXPECT_EQ(0, reader_->Read(buf.get(), buf->size(), read_callback.callback()));
-}
-
-TEST_F(UploadFileSystemFileElementReaderTest, ReadPartially) {
- const size_t kHalfSize = file_data_.size() / 2;
- ASSERT_EQ(file_data_.size(), kHalfSize * 2);
-
- scoped_refptr<net::IOBufferWithSize> buf =
- new net::IOBufferWithSize(kHalfSize);
-
- net::TestCompletionCallback read_callback1;
- ASSERT_EQ(net::ERR_IO_PENDING,
- reader_->Read(buf.get(), buf->size(), read_callback1.callback()));
- EXPECT_EQ(buf->size(), read_callback1.WaitForResult());
- EXPECT_EQ(file_data_.size() - buf->size(), reader_->BytesRemaining());
- EXPECT_TRUE(std::equal(file_data_.begin(), file_data_.begin() + kHalfSize,
- buf->data()));
-
- net::TestCompletionCallback read_callback2;
- EXPECT_EQ(net::ERR_IO_PENDING,
- reader_->Read(buf.get(), buf->size(), read_callback2.callback()));
- EXPECT_EQ(buf->size(), read_callback2.WaitForResult());
- EXPECT_EQ(0U, reader_->BytesRemaining());
- EXPECT_TRUE(std::equal(file_data_.begin() + kHalfSize, file_data_.end(),
- buf->data()));
-}
-
-TEST_F(UploadFileSystemFileElementReaderTest, ReadTooMuch) {
- const size_t kTooLargeSize = file_data_.size() * 2;
- scoped_refptr<net::IOBufferWithSize> buf =
- new net::IOBufferWithSize(kTooLargeSize);
- net::TestCompletionCallback read_callback;
- ASSERT_EQ(net::ERR_IO_PENDING,
- reader_->Read(buf.get(), buf->size(), read_callback.callback()));
- EXPECT_EQ(static_cast<int>(file_data_.size()), read_callback.WaitForResult());
- EXPECT_EQ(0U, reader_->BytesRemaining());
- EXPECT_TRUE(std::equal(file_data_.begin(), file_data_.end(), buf->data()));
-}
-
-TEST_F(UploadFileSystemFileElementReaderTest, MultipleInit) {
- scoped_refptr<net::IOBufferWithSize> buf =
- new net::IOBufferWithSize(file_data_.size());
-
- // Read all.
- net::TestCompletionCallback read_callback1;
- ASSERT_EQ(net::ERR_IO_PENDING,
- reader_->Read(buf.get(), buf->size(), read_callback1.callback()));
- EXPECT_EQ(buf->size(), read_callback1.WaitForResult());
- EXPECT_EQ(0U, reader_->BytesRemaining());
- EXPECT_TRUE(std::equal(file_data_.begin(), file_data_.end(), buf->data()));
-
- // Call Init() again to reset the state.
- net::TestCompletionCallback init_callback;
- ASSERT_EQ(net::ERR_IO_PENDING, reader_->Init(init_callback.callback()));
- EXPECT_EQ(net::OK, init_callback.WaitForResult());
- EXPECT_EQ(file_data_.size(), reader_->GetContentLength());
- EXPECT_EQ(file_data_.size(), reader_->BytesRemaining());
-
- // Read again.
- net::TestCompletionCallback read_callback2;
- ASSERT_EQ(net::ERR_IO_PENDING,
- reader_->Read(buf.get(), buf->size(), read_callback2.callback()));
- EXPECT_EQ(buf->size(), read_callback2.WaitForResult());
- EXPECT_EQ(0U, reader_->BytesRemaining());
- EXPECT_TRUE(std::equal(file_data_.begin(), file_data_.end(), buf->data()));
-}
-
-TEST_F(UploadFileSystemFileElementReaderTest, InitDuringAsyncOperation) {
- scoped_refptr<net::IOBufferWithSize> buf =
- new net::IOBufferWithSize(file_data_.size());
-
- // Start reading all.
- net::TestCompletionCallback read_callback1;
- EXPECT_EQ(net::ERR_IO_PENDING,
- reader_->Read(buf.get(), buf->size(), read_callback1.callback()));
-
- // Call Init to cancel the previous read.
- net::TestCompletionCallback init_callback1;
- EXPECT_EQ(net::ERR_IO_PENDING, reader_->Init(init_callback1.callback()));
-
- // Call Init again to cancel the previous init.
- net::TestCompletionCallback init_callback2;
- EXPECT_EQ(net::ERR_IO_PENDING, reader_->Init(init_callback2.callback()));
- EXPECT_EQ(net::OK, init_callback2.WaitForResult());
- EXPECT_EQ(file_data_.size(), reader_->GetContentLength());
- EXPECT_EQ(file_data_.size(), reader_->BytesRemaining());
-
- // Read half.
- scoped_refptr<net::IOBufferWithSize> buf2 =
- new net::IOBufferWithSize(file_data_.size() / 2);
- net::TestCompletionCallback read_callback2;
- EXPECT_EQ(net::ERR_IO_PENDING,
- reader_->Read(buf2.get(), buf2->size(), read_callback2.callback()));
- EXPECT_EQ(buf2->size(), read_callback2.WaitForResult());
- EXPECT_EQ(file_data_.size() - buf2->size(), reader_->BytesRemaining());
- EXPECT_TRUE(std::equal(file_data_.begin(), file_data_.begin() + buf2->size(),
- buf2->data()));
-
- // Make sure callbacks are not called for cancelled operations.
- EXPECT_FALSE(read_callback1.have_result());
- EXPECT_FALSE(init_callback1.have_result());
-}
-
-TEST_F(UploadFileSystemFileElementReaderTest, Range) {
- const int kOffset = 2;
- const int kLength = file_data_.size() - kOffset * 3;
- reader_.reset(new UploadFileSystemFileElementReader(
- file_system_context_.get(), file_url_, kOffset, kLength, base::Time()));
- net::TestCompletionCallback init_callback;
- ASSERT_EQ(net::ERR_IO_PENDING, reader_->Init(init_callback.callback()));
- EXPECT_EQ(net::OK, init_callback.WaitForResult());
- EXPECT_EQ(static_cast<uint64>(kLength), reader_->GetContentLength());
- EXPECT_EQ(static_cast<uint64>(kLength), reader_->BytesRemaining());
- scoped_refptr<net::IOBufferWithSize> buf = new net::IOBufferWithSize(kLength);
- net::TestCompletionCallback read_callback;
- ASSERT_EQ(net::ERR_IO_PENDING,
- reader_->Read(buf.get(), buf->size(), read_callback.callback()));
- EXPECT_EQ(kLength, read_callback.WaitForResult());
- EXPECT_TRUE(std::equal(file_data_.begin() + kOffset,
- file_data_.begin() + kOffset + kLength,
- buf->data()));
-}
-
-TEST_F(UploadFileSystemFileElementReaderTest, FileChanged) {
- // Expect one second before the actual modification time to simulate change.
- const base::Time expected_modification_time =
- file_modification_time_ - base::TimeDelta::FromSeconds(1);
- reader_.reset(
- new UploadFileSystemFileElementReader(file_system_context_.get(),
- file_url_,
- 0,
- kuint64max,
- expected_modification_time));
- net::TestCompletionCallback init_callback;
- ASSERT_EQ(net::ERR_IO_PENDING, reader_->Init(init_callback.callback()));
- EXPECT_EQ(net::ERR_UPLOAD_FILE_CHANGED, init_callback.WaitForResult());
-}
-
-TEST_F(UploadFileSystemFileElementReaderTest, WrongURL) {
- const GURL wrong_url = GetFileSystemURL("wrong_file_name.dat");
- reader_.reset(new UploadFileSystemFileElementReader(
- file_system_context_.get(), wrong_url, 0, kuint64max, base::Time()));
- net::TestCompletionCallback init_callback;
- ASSERT_EQ(net::ERR_IO_PENDING, reader_->Init(init_callback.callback()));
- EXPECT_EQ(net::ERR_FILE_NOT_FOUND, init_callback.WaitForResult());
-}
-
-} // namespace fileapi