summaryrefslogtreecommitdiffstats
path: root/webkit/fileapi
diff options
context:
space:
mode:
authorkinuko@chromium.org <kinuko@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-10-26 10:56:06 +0000
committerkinuko@chromium.org <kinuko@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-10-26 10:56:06 +0000
commit5e4b00e733b9cd37c035ad336f541aae7548efa5 (patch)
tree65bd5be28a06b22e16fd547f33cff6ad91f35352 /webkit/fileapi
parent7362421eb71391bd7078fe618f4baa4df5c57c99 (diff)
downloadchromium_src-5e4b00e733b9cd37c035ad336f541aae7548efa5.zip
chromium_src-5e4b00e733b9cd37c035ad336f541aae7548efa5.tar.gz
chromium_src-5e4b00e733b9cd37c035ad336f541aae7548efa5.tar.bz2
Implement ApplyRemoteChange for Add/Update changes
BUG=156599 TEST=LocalFileSyncContext.ApplyRemoteChangeForAddOrUpdate Review URL: https://codereview.chromium.org/11264038 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@164314 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit/fileapi')
-rw-r--r--webkit/fileapi/syncable/canned_syncable_file_system.cc41
-rw-r--r--webkit/fileapi/syncable/canned_syncable_file_system.h4
-rw-r--r--webkit/fileapi/syncable/local_file_sync_context.cc17
-rw-r--r--webkit/fileapi/syncable/local_file_sync_context_unittest.cc176
4 files changed, 217 insertions, 21 deletions
diff --git a/webkit/fileapi/syncable/canned_syncable_file_system.cc b/webkit/fileapi/syncable/canned_syncable_file_system.cc
index 2f8a584..e5f49cd 100644
--- a/webkit/fileapi/syncable/canned_syncable_file_system.cc
+++ b/webkit/fileapi/syncable/canned_syncable_file_system.cc
@@ -10,6 +10,7 @@
#include "base/single_thread_task_runner.h"
#include "base/task_runner_util.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "webkit/blob/mock_blob_url_request_context.h"
#include "webkit/fileapi/file_system_context.h"
#include "webkit/fileapi/file_system_operation_context.h"
#include "webkit/fileapi/file_system_task_runners.h"
@@ -23,6 +24,8 @@
using base::PlatformFileError;
using quota::QuotaManager;
+using webkit_blob::MockBlobURLRequestContext;
+using webkit_blob::ScopedTextBlob;
namespace fileapi {
@@ -72,7 +75,17 @@ void VerifySameTaskRunner(
class WriteHelper {
public:
WriteHelper() : bytes_written_(0) {}
- ~WriteHelper() {}
+ WriteHelper(MockBlobURLRequestContext* request_context,
+ const GURL& blob_url,
+ const std::string& blob_data)
+ : bytes_written_(0),
+ request_context_(request_context),
+ blob_data_(new ScopedTextBlob(*request_context, blob_url, blob_data)) {}
+
+ ~WriteHelper() {
+ if (request_context_)
+ MessageLoop::current()->DeleteSoon(FROM_HERE, request_context_.release());
+ }
void DidWrite(const base::Callback<void(int64)>& completion_callback,
PlatformFileError error, int64 bytes, bool complete) {
@@ -87,6 +100,10 @@ class WriteHelper {
private:
int64 bytes_written_;
+ scoped_ptr<MockBlobURLRequestContext> request_context_;
+ scoped_ptr<ScopedTextBlob> blob_data_;
+
+ DISALLOW_COPY_AND_ASSIGN(WriteHelper);
};
void DidGetUsageAndQuota(const quota::StatusCallback& callback,
@@ -263,6 +280,15 @@ int64 CannedSyncableFileSystem::Write(
base::Unretained(this), url_request_context, url, blob_url));
}
+int64 CannedSyncableFileSystem::WriteString(
+ const FileSystemURL& url, const std::string& data) {
+ return RunOnThread<int64>(
+ io_task_runner_,
+ FROM_HERE,
+ base::Bind(&CannedSyncableFileSystem::DoWriteString,
+ base::Unretained(this), url, data));
+}
+
PlatformFileError CannedSyncableFileSystem::DeleteFileSystem() {
EXPECT_TRUE(is_filesystem_set_up_);
return RunOnThread<PlatformFileError>(
@@ -355,6 +381,19 @@ void CannedSyncableFileSystem::DoWrite(
base::Owned(helper), callback));
}
+void CannedSyncableFileSystem::DoWriteString(
+ const FileSystemURL& url,
+ const std::string& data,
+ const WriteCallback& callback) {
+ MockBlobURLRequestContext* url_request_context(
+ new MockBlobURLRequestContext(file_system_context_));
+ const GURL blob_url(std::string("blob:") + data);
+ WriteHelper* helper = new WriteHelper(url_request_context, blob_url, data);
+ NewOperation()->Write(url_request_context, url, blob_url, 0,
+ base::Bind(&WriteHelper::DidWrite,
+ base::Owned(helper), callback));
+}
+
void CannedSyncableFileSystem::DoGetUsageAndQuota(
int64* usage,
int64* quota,
diff --git a/webkit/fileapi/syncable/canned_syncable_file_system.h b/webkit/fileapi/syncable/canned_syncable_file_system.h
index 3a69328..b443853 100644
--- a/webkit/fileapi/syncable/canned_syncable_file_system.h
+++ b/webkit/fileapi/syncable/canned_syncable_file_system.h
@@ -94,6 +94,7 @@ class CannedSyncableFileSystem {
// Returns the # of bytes written (>=0) or an error code (<0).
int64 Write(net::URLRequestContext* url_request_context,
const FileSystemURL& url, const GURL& blob_url);
+ int64 WriteString(const FileSystemURL& url, const std::string& data);
// Purges the file system local storage.
base::PlatformFileError DeleteFileSystem();
@@ -130,6 +131,9 @@ class CannedSyncableFileSystem {
const FileSystemURL& url,
const GURL& blob_url,
const WriteCallback& callback);
+ void DoWriteString(const FileSystemURL& url,
+ const std::string& data,
+ const WriteCallback& callback);
void DoGetUsageAndQuota(int64* usage,
int64* quota,
const quota::StatusCallback& callback);
diff --git a/webkit/fileapi/syncable/local_file_sync_context.cc b/webkit/fileapi/syncable/local_file_sync_context.cc
index ea12d42..9194eaa 100644
--- a/webkit/fileapi/syncable/local_file_sync_context.cc
+++ b/webkit/fileapi/syncable/local_file_sync_context.cc
@@ -130,6 +130,8 @@ void LocalFileSyncContext::ApplyRemoteChange(
return;
}
DCHECK(io_task_runner_->RunsTasksOnCurrentThread());
+ DCHECK(!sync_status()->IsWritable(url));
+ DCHECK(!sync_status()->IsWriting(url));
LocalFileSystemOperation* operation = CreateFileSystemOperationForSync(
file_system_context);
DCHECK(operation);
@@ -138,8 +140,19 @@ void LocalFileSyncContext::ApplyRemoteChange(
this, callback);
switch (change.change()) {
case FileChange::FILE_CHANGE_ADD_OR_UPDATE:
- // TODO(kinuko): implement. (crbug.com/156599)
- NOTIMPLEMENTED();
+ switch (change.file_type()) {
+ case FileChange::FILE_TYPE_FILE:
+ DCHECK(!local_path.empty());
+ operation->CopyInForeignFile(local_path, url, operation_callback);
+ break;
+ case FileChange::FILE_TYPE_DIRECTORY:
+ operation->CreateDirectory(
+ url, false /* exclusive */, true /* recursive */,
+ operation_callback);
+ break;
+ case FileChange::FILE_TYPE_UNDETERMINED:
+ NOTREACHED() << "File type undetermined for ADD_OR_UPDATE change";
+ }
break;
case FileChange::FILE_CHANGE_DELETE:
operation->Remove(url, true /* recursive */, operation_callback);
diff --git a/webkit/fileapi/syncable/local_file_sync_context_unittest.cc b/webkit/fileapi/syncable/local_file_sync_context_unittest.cc
index 46e8437..0b61fd9 100644
--- a/webkit/fileapi/syncable/local_file_sync_context_unittest.cc
+++ b/webkit/fileapi/syncable/local_file_sync_context_unittest.cc
@@ -8,11 +8,13 @@
#include "base/bind.h"
#include "base/file_path.h"
+#include "base/file_util.h"
#include "base/message_loop.h"
#include "base/platform_file.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "webkit/blob/mock_blob_url_request_context.h"
#include "webkit/fileapi/file_system_context.h"
#include "webkit/fileapi/file_system_operation.h"
#include "webkit/fileapi/isolated_context.h"
@@ -21,6 +23,8 @@
#include "webkit/fileapi/syncable/sync_status_code.h"
#include "webkit/fileapi/syncable/syncable_file_system_util.h"
+#define FPL FILE_PATH_LITERAL
+
// This tests LocalFileSyncContext behavior in multi-thread /
// multi-file-system-context environment.
// Basic combined tests (single-thread / single-file-system-context)
@@ -59,24 +63,6 @@ class LocalFileSyncContextTest : public testing::Test {
io_thread_->Stop();
}
- SyncStatusCode ApplyRemoteChange(FileSystemContext* file_system_context,
- const FileChange& change,
- const FilePath& local_path,
- const FileSystemURL& url) {
- status_ = SYNC_STATUS_UNKNOWN;
- sync_context_->ApplyRemoteChange(
- file_system_context, change, local_path, url,
- base::Bind(&LocalFileSyncContextTest::DidApplyRemoteChange,
- base::Unretained(this)));
- MessageLoop::current()->Run();
- return status_;
- }
-
- void DidApplyRemoteChange(SyncStatusCode status) {
- MessageLoop::current()->Quit();
- status_ = status;
- }
-
void StartPrepareForSync(LocalFileSyncContext* sync_context,
FileSystemContext* file_system_context,
const FileSystemURL& url,
@@ -121,6 +107,31 @@ class LocalFileSyncContextTest : public testing::Test {
MessageLoop::current()->Quit();
}
+ SyncStatusCode ApplyRemoteChange(FileSystemContext* file_system_context,
+ const FileChange& change,
+ const FilePath& local_path,
+ const FileSystemURL& url) {
+ status_ = SYNC_STATUS_UNKNOWN;
+
+ // First we should call PrepareForSync to disable writing.
+ FileChangeList changes;
+ StartPrepareForSync(sync_context_, file_system_context, url, &changes);
+ MessageLoop::current()->Run();
+ EXPECT_EQ(SYNC_STATUS_OK, status_);
+
+ sync_context_->ApplyRemoteChange(
+ file_system_context, change, local_path, url,
+ base::Bind(&LocalFileSyncContextTest::DidApplyRemoteChange,
+ base::Unretained(this)));
+ MessageLoop::current()->Run();
+ return status_;
+ }
+
+ void DidApplyRemoteChange(SyncStatusCode status) {
+ MessageLoop::current()->Quit();
+ status_ = status;
+ }
+
void StartModifyFileOnIOThread(CannedSyncableFileSystem* file_system,
const FileSystemURL& url) {
async_modify_finished_ = false;
@@ -428,4 +439,133 @@ TEST_F(LocalFileSyncContextTest, ApplyRemoteChangeForDeletion) {
file_system.TearDown();
}
+TEST_F(LocalFileSyncContextTest, ApplyRemoteChangeForAddOrUpdate) {
+ ScopedTempDir temp_dir;
+ ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+
+ CannedSyncableFileSystem file_system(GURL(kOrigin1), kServiceName,
+ io_task_runner_);
+ file_system.SetUp();
+
+ sync_context_ = new LocalFileSyncContext(ui_task_runner_, io_task_runner_);
+ ASSERT_EQ(SYNC_STATUS_OK,
+ file_system.MaybeInitializeFileSystemContext(sync_context_));
+ ASSERT_EQ(base::PLATFORM_FILE_OK, file_system.OpenFileSystem());
+
+ const FileSystemURL kFile1(file_system.URL("file1"));
+ const FileSystemURL kFile2(file_system.URL("file2"));
+ const FileSystemURL kDir(file_system.URL("dir"));
+
+ const char kTestFileData0[] = "0123456789";
+ const char kTestFileData1[] = "Lorem ipsum!";
+ const char kTestFileData2[] = "This is sample test data.";
+
+ // Create kFile1 and populate it with kTestFileData0.
+ EXPECT_EQ(base::PLATFORM_FILE_OK, file_system.CreateFile(kFile1));
+ EXPECT_EQ(static_cast<int64>(arraysize(kTestFileData0) - 1),
+ file_system.WriteString(kFile1, kTestFileData0));
+
+ // kFile2 and kDir are not there yet.
+ EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND,
+ file_system.FileExists(kFile2));
+ EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND,
+ file_system.DirectoryExists(kDir));
+
+ // file_system's change tracker must have recorded the creation.
+ std::vector<FileSystemURL> urls;
+ file_system.file_system_context()->change_tracker()->GetChangedURLs(&urls);
+ ASSERT_EQ(1U, urls.size());
+ EXPECT_EQ(kFile1, urls[0]);
+ file_system.file_system_context()->change_tracker()->FinalizeSyncForURL(
+ urls[0]);
+
+ // Prepare temporary files which represent the remote file data.
+ const FilePath kFilePath1(temp_dir.path().Append(FPL("file1")));
+ const FilePath kFilePath2(temp_dir.path().Append(FPL("file2")));
+
+ ASSERT_EQ(static_cast<int>(arraysize(kTestFileData1) - 1),
+ file_util::WriteFile(kFilePath1, kTestFileData1,
+ arraysize(kTestFileData1) - 1));
+ ASSERT_EQ(static_cast<int>(arraysize(kTestFileData2) - 1),
+ file_util::WriteFile(kFilePath2, kTestFileData2,
+ arraysize(kTestFileData2) - 1));
+
+ // Record the usage.
+ int64 usage = -1, new_usage = -1;
+ int64 quota = -1;
+ EXPECT_EQ(quota::kQuotaStatusOk,
+ file_system.GetUsageAndQuota(&usage, &quota));
+
+ // Here in the local filesystem we have:
+ // * kFile1 with kTestFileData0
+ //
+ // In the remote side let's assume we have:
+ // * kFile1 with kTestFileData1
+ // * kFile2 with kTestFileData2
+ // * kDir
+ //
+ // By calling ApplyChange's:
+ // * kFile1 will be updated to have kTestFileData1
+ // * kFile2 will be created
+ // * kDir will be created
+
+ // Apply the remote change to kFile1 (which will update the file).
+ FileChange change(FileChange::FILE_CHANGE_ADD_OR_UPDATE,
+ FileChange::FILE_TYPE_FILE);
+ EXPECT_EQ(SYNC_STATUS_OK,
+ ApplyRemoteChange(file_system.file_system_context(),
+ change, kFilePath1, kFile1));
+
+ // Check if the usage has been increased by (kTestFileData1 - kTestFileData0).
+ const int updated_size =
+ arraysize(kTestFileData1) - arraysize(kTestFileData0);
+ EXPECT_EQ(quota::kQuotaStatusOk,
+ file_system.GetUsageAndQuota(&new_usage, &quota));
+ EXPECT_EQ(updated_size, new_usage - usage);
+
+ // Apply remote changes to kFile2 and kDir (should create a file and
+ // directory respectively).
+ change = FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE,
+ FileChange::FILE_TYPE_FILE);
+ EXPECT_EQ(SYNC_STATUS_OK,
+ ApplyRemoteChange(file_system.file_system_context(),
+ change, kFilePath2, kFile2));
+
+ change = FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE,
+ FileChange::FILE_TYPE_DIRECTORY);
+ EXPECT_EQ(SYNC_STATUS_OK,
+ ApplyRemoteChange(file_system.file_system_context(),
+ change, FilePath(), kDir));
+
+ // This should not happen, but calling ApplyRemoteChange
+ // with wrong file type will result in error.
+ change = FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE,
+ FileChange::FILE_TYPE_FILE);
+ EXPECT_EQ(SYNC_FILE_ERROR_FAILED,
+ ApplyRemoteChange(file_system.file_system_context(),
+ change, kFilePath1, kDir));
+
+ // Creating a file/directory must have increased the usage more than
+ // the size of kTestFileData2.
+ new_usage = usage;
+ EXPECT_EQ(quota::kQuotaStatusOk,
+ file_system.GetUsageAndQuota(&new_usage, &quota));
+ EXPECT_GT(new_usage,
+ static_cast<int64>(usage + arraysize(kTestFileData2) - 1));
+
+ // The changes applied by ApplyRemoteChange should not be recorded in
+ // the change tracker.
+ urls.clear();
+ file_system.file_system_context()->change_tracker()->GetChangedURLs(&urls);
+ EXPECT_TRUE(urls.empty());
+
+ // Make sure all three files/directory exist.
+ EXPECT_EQ(base::PLATFORM_FILE_OK, file_system.FileExists(kFile1));
+ EXPECT_EQ(base::PLATFORM_FILE_OK, file_system.FileExists(kFile2));
+ EXPECT_EQ(base::PLATFORM_FILE_OK, file_system.DirectoryExists(kDir));
+
+ sync_context_->ShutdownOnUIThread();
+ file_system.TearDown();
+}
+
} // namespace fileapi