Add LocalFileSyncContext class which is a glue class between profile-owned service and FileSystemContext(s)
BUG=154234 TEST=LocalFileSyncContextTest.* TBR=jam@chromium.org Review URL: https://codereview.chromium.org/11090019 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@161556 0039d316-1c4b-4281-b951-d872f2087c98
This commit is contained in:
@ -433,6 +433,7 @@
|
|||||||
'../webkit/fileapi/syncable/canned_syncable_file_system.h',
|
'../webkit/fileapi/syncable/canned_syncable_file_system.h',
|
||||||
'../webkit/fileapi/syncable/file_change_unittest.cc',
|
'../webkit/fileapi/syncable/file_change_unittest.cc',
|
||||||
'../webkit/fileapi/syncable/local_file_change_tracker_unittest.cc',
|
'../webkit/fileapi/syncable/local_file_change_tracker_unittest.cc',
|
||||||
|
'../webkit/fileapi/syncable/local_file_sync_context_unittest.cc',
|
||||||
'../webkit/fileapi/syncable/local_file_sync_status_unittest.cc',
|
'../webkit/fileapi/syncable/local_file_sync_status_unittest.cc',
|
||||||
'../webkit/fileapi/syncable/syncable_file_system_unittest.cc',
|
'../webkit/fileapi/syncable/syncable_file_system_unittest.cc',
|
||||||
'../webkit/fileapi/syncable/syncable_file_system_util_unittest.cc',
|
'../webkit/fileapi/syncable/syncable_file_system_util_unittest.cc',
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#include "webkit/fileapi/isolated_mount_point_provider.h"
|
#include "webkit/fileapi/isolated_mount_point_provider.h"
|
||||||
#include "webkit/fileapi/sandbox_mount_point_provider.h"
|
#include "webkit/fileapi/sandbox_mount_point_provider.h"
|
||||||
#include "webkit/fileapi/syncable/local_file_change_tracker.h"
|
#include "webkit/fileapi/syncable/local_file_change_tracker.h"
|
||||||
|
#include "webkit/fileapi/syncable/local_file_sync_context.h"
|
||||||
#include "webkit/fileapi/syncable/syncable_file_system_util.h"
|
#include "webkit/fileapi/syncable/syncable_file_system_util.h"
|
||||||
#include "webkit/fileapi/test_mount_point_provider.h"
|
#include "webkit/fileapi/test_mount_point_provider.h"
|
||||||
#include "webkit/quota/quota_manager.h"
|
#include "webkit/quota/quota_manager.h"
|
||||||
@ -289,6 +290,11 @@ void FileSystemContext::SetLocalFileChangeTracker(
|
|||||||
task_runners_->file_task_runner());
|
task_runners_->file_task_runner());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FileSystemContext::set_sync_context(
|
||||||
|
LocalFileSyncContext* sync_context) {
|
||||||
|
sync_context_ = sync_context;
|
||||||
|
}
|
||||||
|
|
||||||
FileSystemContext::~FileSystemContext() {}
|
FileSystemContext::~FileSystemContext() {}
|
||||||
|
|
||||||
void FileSystemContext::DeleteOnCorrectThread() const {
|
void FileSystemContext::DeleteOnCorrectThread() const {
|
||||||
|
@ -41,6 +41,7 @@ class FileSystemURL;
|
|||||||
class IsolatedMountPointProvider;
|
class IsolatedMountPointProvider;
|
||||||
class LocalFileChangeTracker;
|
class LocalFileChangeTracker;
|
||||||
class SandboxMountPointProvider;
|
class SandboxMountPointProvider;
|
||||||
|
class LocalFileSyncContext;
|
||||||
|
|
||||||
struct DefaultContextDeleter;
|
struct DefaultContextDeleter;
|
||||||
|
|
||||||
@ -165,6 +166,9 @@ class FILEAPI_EXPORT FileSystemContext
|
|||||||
LocalFileChangeTracker* change_tracker() { return change_tracker_.get(); }
|
LocalFileChangeTracker* change_tracker() { return change_tracker_.get(); }
|
||||||
void SetLocalFileChangeTracker(scoped_ptr<LocalFileChangeTracker> tracker);
|
void SetLocalFileChangeTracker(scoped_ptr<LocalFileChangeTracker> tracker);
|
||||||
|
|
||||||
|
LocalFileSyncContext* sync_context() { return sync_context_.get(); }
|
||||||
|
void set_sync_context(LocalFileSyncContext* sync_context);
|
||||||
|
|
||||||
const FilePath& partition_path() const { return partition_path_; }
|
const FilePath& partition_path() const { return partition_path_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -193,6 +197,7 @@ class FILEAPI_EXPORT FileSystemContext
|
|||||||
|
|
||||||
// For syncable file systems.
|
// For syncable file systems.
|
||||||
scoped_ptr<LocalFileChangeTracker> change_tracker_;
|
scoped_ptr<LocalFileChangeTracker> change_tracker_;
|
||||||
|
scoped_refptr<LocalFileSyncContext> sync_context_;
|
||||||
|
|
||||||
DISALLOW_IMPLICIT_CONSTRUCTORS(FileSystemContext);
|
DISALLOW_IMPLICIT_CONSTRUCTORS(FileSystemContext);
|
||||||
};
|
};
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#include "webkit/fileapi/isolated_context.h"
|
#include "webkit/fileapi/isolated_context.h"
|
||||||
#include "webkit/fileapi/local_file_system_operation.h"
|
#include "webkit/fileapi/local_file_system_operation.h"
|
||||||
#include "webkit/fileapi/mock_file_system_options.h"
|
#include "webkit/fileapi/mock_file_system_options.h"
|
||||||
|
#include "webkit/fileapi/syncable/local_file_sync_context.h"
|
||||||
#include "webkit/quota/mock_special_storage_policy.h"
|
#include "webkit/quota/mock_special_storage_policy.h"
|
||||||
#include "webkit/quota/quota_manager.h"
|
#include "webkit/quota/quota_manager.h"
|
||||||
|
|
||||||
@ -29,12 +30,15 @@ CannedSyncableFileSystem::CannedSyncableFileSystem(
|
|||||||
test_helper_(origin, kFileSystemTypeSyncable),
|
test_helper_(origin, kFileSystemTypeSyncable),
|
||||||
result_(base::PLATFORM_FILE_OK),
|
result_(base::PLATFORM_FILE_OK),
|
||||||
sync_status_(SYNC_STATUS_OK),
|
sync_status_(SYNC_STATUS_OK),
|
||||||
|
is_filesystem_set_up_(false),
|
||||||
|
is_filesystem_opened_(false),
|
||||||
weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
|
weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
CannedSyncableFileSystem::~CannedSyncableFileSystem() {}
|
CannedSyncableFileSystem::~CannedSyncableFileSystem() {}
|
||||||
|
|
||||||
void CannedSyncableFileSystem::SetUp() {
|
void CannedSyncableFileSystem::SetUp() {
|
||||||
|
ASSERT_FALSE(is_filesystem_set_up_);
|
||||||
ASSERT_TRUE(data_dir_.CreateUniqueTempDir());
|
ASSERT_TRUE(data_dir_.CreateUniqueTempDir());
|
||||||
|
|
||||||
scoped_refptr<quota::SpecialStoragePolicy> storage_policy =
|
scoped_refptr<quota::SpecialStoragePolicy> storage_policy =
|
||||||
@ -55,6 +59,7 @@ void CannedSyncableFileSystem::SetUp() {
|
|||||||
CreateAllowFileAccessOptions());
|
CreateAllowFileAccessOptions());
|
||||||
|
|
||||||
test_helper_.SetUp(file_system_context_.get(), NULL);
|
test_helper_.SetUp(file_system_context_.get(), NULL);
|
||||||
|
is_filesystem_set_up_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CannedSyncableFileSystem::TearDown() {
|
void CannedSyncableFileSystem::TearDown() {
|
||||||
@ -63,10 +68,14 @@ void CannedSyncableFileSystem::TearDown() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
FileSystemURL CannedSyncableFileSystem::URL(const std::string& path) const {
|
FileSystemURL CannedSyncableFileSystem::URL(const std::string& path) const {
|
||||||
|
EXPECT_TRUE(is_filesystem_set_up_);
|
||||||
|
EXPECT_TRUE(is_filesystem_opened_);
|
||||||
return FileSystemURL(GURL(root_url_.spec() + path));
|
return FileSystemURL(GURL(root_url_.spec() + path));
|
||||||
}
|
}
|
||||||
|
|
||||||
PlatformFileError CannedSyncableFileSystem::OpenFileSystem() {
|
PlatformFileError CannedSyncableFileSystem::OpenFileSystem() {
|
||||||
|
EXPECT_TRUE(is_filesystem_set_up_);
|
||||||
|
EXPECT_FALSE(is_filesystem_opened_);
|
||||||
file_system_context_->OpenSyncableFileSystem(
|
file_system_context_->OpenSyncableFileSystem(
|
||||||
service_name_,
|
service_name_,
|
||||||
test_helper_.origin(), test_helper_.type(),
|
test_helper_.origin(), test_helper_.type(),
|
||||||
@ -77,8 +86,22 @@ PlatformFileError CannedSyncableFileSystem::OpenFileSystem() {
|
|||||||
return result_;
|
return result_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SyncStatusCode CannedSyncableFileSystem::MaybeInitializeFileSystemContext(
|
||||||
|
LocalFileSyncContext* sync_context) {
|
||||||
|
DCHECK(sync_context);
|
||||||
|
sync_status_ = SYNC_STATUS_UNKNOWN;
|
||||||
|
sync_context->MaybeInitializeFileSystemContext(
|
||||||
|
test_helper_.origin(),
|
||||||
|
file_system_context_,
|
||||||
|
base::Bind(&CannedSyncableFileSystem::DidInitializeFileSystemContext,
|
||||||
|
base::Unretained(this)));
|
||||||
|
MessageLoop::current()->Run();
|
||||||
|
return sync_status_;
|
||||||
|
}
|
||||||
|
|
||||||
PlatformFileError CannedSyncableFileSystem::CreateDirectory(
|
PlatformFileError CannedSyncableFileSystem::CreateDirectory(
|
||||||
const FileSystemURL& url) {
|
const FileSystemURL& url) {
|
||||||
|
EXPECT_TRUE(is_filesystem_opened_);
|
||||||
result_ = base::PLATFORM_FILE_ERROR_FAILED;
|
result_ = base::PLATFORM_FILE_ERROR_FAILED;
|
||||||
test_helper_.NewOperation()->CreateDirectory(
|
test_helper_.NewOperation()->CreateDirectory(
|
||||||
url, false /* exclusive */, false /* recursive */,
|
url, false /* exclusive */, false /* recursive */,
|
||||||
@ -90,6 +113,7 @@ PlatformFileError CannedSyncableFileSystem::CreateDirectory(
|
|||||||
|
|
||||||
PlatformFileError CannedSyncableFileSystem::CreateFile(
|
PlatformFileError CannedSyncableFileSystem::CreateFile(
|
||||||
const FileSystemURL& url) {
|
const FileSystemURL& url) {
|
||||||
|
EXPECT_TRUE(is_filesystem_opened_);
|
||||||
result_ = base::PLATFORM_FILE_ERROR_FAILED;
|
result_ = base::PLATFORM_FILE_ERROR_FAILED;
|
||||||
test_helper_.NewOperation()->CreateFile(
|
test_helper_.NewOperation()->CreateFile(
|
||||||
url, false /* exclusive */,
|
url, false /* exclusive */,
|
||||||
@ -123,6 +147,7 @@ PlatformFileError CannedSyncableFileSystem::Move(
|
|||||||
|
|
||||||
PlatformFileError CannedSyncableFileSystem::TruncateFile(
|
PlatformFileError CannedSyncableFileSystem::TruncateFile(
|
||||||
const FileSystemURL& url, int64 size) {
|
const FileSystemURL& url, int64 size) {
|
||||||
|
EXPECT_TRUE(is_filesystem_opened_);
|
||||||
result_ = base::PLATFORM_FILE_ERROR_FAILED;
|
result_ = base::PLATFORM_FILE_ERROR_FAILED;
|
||||||
test_helper_.NewOperation()->Truncate(
|
test_helper_.NewOperation()->Truncate(
|
||||||
url, size,
|
url, size,
|
||||||
@ -134,6 +159,7 @@ PlatformFileError CannedSyncableFileSystem::TruncateFile(
|
|||||||
|
|
||||||
PlatformFileError CannedSyncableFileSystem::Remove(
|
PlatformFileError CannedSyncableFileSystem::Remove(
|
||||||
const FileSystemURL& url, bool recursive) {
|
const FileSystemURL& url, bool recursive) {
|
||||||
|
EXPECT_TRUE(is_filesystem_opened_);
|
||||||
result_ = base::PLATFORM_FILE_ERROR_FAILED;
|
result_ = base::PLATFORM_FILE_ERROR_FAILED;
|
||||||
test_helper_.NewOperation()->Remove(
|
test_helper_.NewOperation()->Remove(
|
||||||
url, recursive,
|
url, recursive,
|
||||||
@ -144,6 +170,7 @@ PlatformFileError CannedSyncableFileSystem::Remove(
|
|||||||
}
|
}
|
||||||
|
|
||||||
PlatformFileError CannedSyncableFileSystem::DeleteFileSystem() {
|
PlatformFileError CannedSyncableFileSystem::DeleteFileSystem() {
|
||||||
|
EXPECT_TRUE(is_filesystem_set_up_);
|
||||||
file_system_context_->DeleteFileSystem(
|
file_system_context_->DeleteFileSystem(
|
||||||
test_helper_.origin(), test_helper_.type(),
|
test_helper_.origin(), test_helper_.type(),
|
||||||
base::Bind(&CannedSyncableFileSystem::StatusCallback,
|
base::Bind(&CannedSyncableFileSystem::StatusCallback,
|
||||||
@ -156,6 +183,13 @@ void CannedSyncableFileSystem::DidOpenFileSystem(
|
|||||||
PlatformFileError result, const std::string& name, const GURL& root) {
|
PlatformFileError result, const std::string& name, const GURL& root) {
|
||||||
result_ = result;
|
result_ = result;
|
||||||
root_url_ = root;
|
root_url_ = root;
|
||||||
|
is_filesystem_opened_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CannedSyncableFileSystem::DidInitializeFileSystemContext(
|
||||||
|
SyncStatusCode status) {
|
||||||
|
sync_status_ = status;
|
||||||
|
MessageLoop::current()->Quit();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CannedSyncableFileSystem::StatusCallback(PlatformFileError result) {
|
void CannedSyncableFileSystem::StatusCallback(PlatformFileError result) {
|
||||||
|
@ -27,6 +27,7 @@ class QuotaManager;
|
|||||||
namespace fileapi {
|
namespace fileapi {
|
||||||
|
|
||||||
class FileSystemContext;
|
class FileSystemContext;
|
||||||
|
class LocalFileSyncContext;
|
||||||
|
|
||||||
// A canned syncable filesystem for testing.
|
// A canned syncable filesystem for testing.
|
||||||
// This internally creates its own QuotaManager and FileSystemContext
|
// This internally creates its own QuotaManager and FileSystemContext
|
||||||
@ -45,6 +46,11 @@ class CannedSyncableFileSystem {
|
|||||||
// Creates a FileSystemURL for the given (utf8) path string.
|
// Creates a FileSystemURL for the given (utf8) path string.
|
||||||
FileSystemURL URL(const std::string& path) const;
|
FileSystemURL URL(const std::string& path) const;
|
||||||
|
|
||||||
|
// Initialize this with given |sync_context| if it hasn't
|
||||||
|
// been initialized.
|
||||||
|
SyncStatusCode MaybeInitializeFileSystemContext(
|
||||||
|
LocalFileSyncContext* sync_context);
|
||||||
|
|
||||||
// Opens a new syncable file system.
|
// Opens a new syncable file system.
|
||||||
base::PlatformFileError OpenFileSystem();
|
base::PlatformFileError OpenFileSystem();
|
||||||
|
|
||||||
@ -60,6 +66,7 @@ class CannedSyncableFileSystem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Helper routines to perform file system operations.
|
// Helper routines to perform file system operations.
|
||||||
|
// OpenFileSystem() must have been called before calling any of them.
|
||||||
// (They run on the current thread and returns synchronously).
|
// (They run on the current thread and returns synchronously).
|
||||||
base::PlatformFileError CreateDirectory(const FileSystemURL& url);
|
base::PlatformFileError CreateDirectory(const FileSystemURL& url);
|
||||||
base::PlatformFileError CreateFile(const FileSystemURL& url);
|
base::PlatformFileError CreateFile(const FileSystemURL& url);
|
||||||
@ -78,6 +85,7 @@ class CannedSyncableFileSystem {
|
|||||||
void DidOpenFileSystem(base::PlatformFileError result,
|
void DidOpenFileSystem(base::PlatformFileError result,
|
||||||
const std::string& name,
|
const std::string& name,
|
||||||
const GURL& root);
|
const GURL& root);
|
||||||
|
void DidInitializeFileSystemContext(SyncStatusCode status);
|
||||||
void StatusCallback(base::PlatformFileError result);
|
void StatusCallback(base::PlatformFileError result);
|
||||||
|
|
||||||
FileSystemOperationContext* NewOperationContext();
|
FileSystemOperationContext* NewOperationContext();
|
||||||
@ -92,6 +100,10 @@ class CannedSyncableFileSystem {
|
|||||||
base::PlatformFileError result_;
|
base::PlatformFileError result_;
|
||||||
SyncStatusCode sync_status_;
|
SyncStatusCode sync_status_;
|
||||||
|
|
||||||
|
// Boolean flags mainly for helping debug.
|
||||||
|
bool is_filesystem_set_up_;
|
||||||
|
bool is_filesystem_opened_;
|
||||||
|
|
||||||
base::WeakPtrFactory<CannedSyncableFileSystem> weak_factory_;
|
base::WeakPtrFactory<CannedSyncableFileSystem> weak_factory_;
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(CannedSyncableFileSystem);
|
DISALLOW_COPY_AND_ASSIGN(CannedSyncableFileSystem);
|
||||||
|
157
webkit/fileapi/syncable/local_file_sync_context.cc
Normal file
157
webkit/fileapi/syncable/local_file_sync_context.cc
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
#include "webkit/fileapi/syncable/local_file_sync_context.h"
|
||||||
|
|
||||||
|
#include "base/bind.h"
|
||||||
|
#include "base/callback.h"
|
||||||
|
#include "base/location.h"
|
||||||
|
#include "base/single_thread_task_runner.h"
|
||||||
|
#include "base/stl_util.h"
|
||||||
|
#include "base/task_runner_util.h"
|
||||||
|
#include "webkit/fileapi/file_system_context.h"
|
||||||
|
#include "webkit/fileapi/file_system_task_runners.h"
|
||||||
|
#include "webkit/fileapi/syncable/local_file_change_tracker.h"
|
||||||
|
|
||||||
|
namespace fileapi {
|
||||||
|
|
||||||
|
LocalFileSyncContext::LocalFileSyncContext(
|
||||||
|
base::SingleThreadTaskRunner* ui_task_runner,
|
||||||
|
base::SingleThreadTaskRunner* io_task_runner)
|
||||||
|
: ui_task_runner_(ui_task_runner),
|
||||||
|
io_task_runner_(io_task_runner),
|
||||||
|
shutdown_(false) {
|
||||||
|
DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
|
||||||
|
}
|
||||||
|
|
||||||
|
void LocalFileSyncContext::MaybeInitializeFileSystemContext(
|
||||||
|
const GURL& source_url,
|
||||||
|
FileSystemContext* file_system_context,
|
||||||
|
const StatusCallback& callback) {
|
||||||
|
DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
|
||||||
|
if (ContainsKey(file_system_contexts_, file_system_context)) {
|
||||||
|
DCHECK(!ContainsKey(origin_to_contexts_, source_url) ||
|
||||||
|
origin_to_contexts_[source_url] == file_system_context);
|
||||||
|
origin_to_contexts_[source_url] = file_system_context;
|
||||||
|
// The context has been already initialized. Just dispatch the callback
|
||||||
|
// with SYNC_STATUS_OK.
|
||||||
|
ui_task_runner_->PostTask(FROM_HERE, base::Bind(callback, SYNC_STATUS_OK));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
StatusCallbackQueue& callback_queue =
|
||||||
|
pending_initialize_callbacks_[file_system_context];
|
||||||
|
callback_queue.push_back(callback);
|
||||||
|
if (callback_queue.size() > 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
io_task_runner_->PostTask(
|
||||||
|
FROM_HERE,
|
||||||
|
base::Bind(&LocalFileSyncContext::InitializeFileSystemContextOnIOThread,
|
||||||
|
this, source_url, make_scoped_refptr(file_system_context)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void LocalFileSyncContext::ShutdownOnUIThread() {
|
||||||
|
DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
|
||||||
|
shutdown_ = true;
|
||||||
|
io_task_runner_->PostTask(
|
||||||
|
FROM_HERE,
|
||||||
|
base::Bind(&LocalFileSyncContext::ShutdownOnIOThread,
|
||||||
|
this));
|
||||||
|
}
|
||||||
|
|
||||||
|
LocalFileSyncContext::~LocalFileSyncContext() {
|
||||||
|
DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
|
||||||
|
DCHECK(shutdown_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LocalFileSyncContext::ShutdownOnIOThread() {
|
||||||
|
DCHECK(io_task_runner_->RunsTasksOnCurrentThread());
|
||||||
|
}
|
||||||
|
|
||||||
|
void LocalFileSyncContext::InitializeFileSystemContextOnIOThread(
|
||||||
|
const GURL& source_url,
|
||||||
|
FileSystemContext* file_system_context) {
|
||||||
|
DCHECK(io_task_runner_->RunsTasksOnCurrentThread());
|
||||||
|
DCHECK(file_system_context);
|
||||||
|
if (!file_system_context->change_tracker()) {
|
||||||
|
// Create and initialize LocalFileChangeTracker and call back this method
|
||||||
|
// later again.
|
||||||
|
scoped_ptr<LocalFileChangeTracker>* tracker_ptr(
|
||||||
|
new scoped_ptr<LocalFileChangeTracker>);
|
||||||
|
base::PostTaskAndReplyWithResult(
|
||||||
|
file_system_context->task_runners()->file_task_runner(),
|
||||||
|
FROM_HERE,
|
||||||
|
base::Bind(&LocalFileSyncContext::InitializeChangeTrackerOnFileThread,
|
||||||
|
this, tracker_ptr,
|
||||||
|
make_scoped_refptr(file_system_context)),
|
||||||
|
base::Bind(&LocalFileSyncContext::DidInitializeChangeTracker, this,
|
||||||
|
base::Owned(tracker_ptr),
|
||||||
|
source_url,
|
||||||
|
make_scoped_refptr(file_system_context)));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
file_system_context->set_sync_context(this);
|
||||||
|
DidInitialize(source_url, file_system_context, SYNC_STATUS_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
SyncStatusCode LocalFileSyncContext::InitializeChangeTrackerOnFileThread(
|
||||||
|
scoped_ptr<LocalFileChangeTracker>* tracker_ptr,
|
||||||
|
FileSystemContext* file_system_context) {
|
||||||
|
DCHECK(file_system_context);
|
||||||
|
DCHECK(tracker_ptr);
|
||||||
|
tracker_ptr->reset(new LocalFileChangeTracker(
|
||||||
|
file_system_context->partition_path(),
|
||||||
|
file_system_context->task_runners()->file_task_runner()));
|
||||||
|
// TODO(kinuko,nhiroki): Uncomment this once http://crbug.com/154028 is fixed.
|
||||||
|
// return change_tracker->Initialize(file_system_context);
|
||||||
|
return SYNC_STATUS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LocalFileSyncContext::DidInitializeChangeTracker(
|
||||||
|
scoped_ptr<LocalFileChangeTracker>* tracker_ptr,
|
||||||
|
const GURL& source_url,
|
||||||
|
FileSystemContext* file_system_context,
|
||||||
|
SyncStatusCode status) {
|
||||||
|
DCHECK(file_system_context);
|
||||||
|
if (status != SYNC_STATUS_OK) {
|
||||||
|
DidInitialize(source_url, file_system_context, status);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
file_system_context->SetLocalFileChangeTracker(tracker_ptr->Pass());
|
||||||
|
InitializeFileSystemContextOnIOThread(source_url, file_system_context);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LocalFileSyncContext::DidInitialize(
|
||||||
|
const GURL& source_url,
|
||||||
|
FileSystemContext* file_system_context,
|
||||||
|
SyncStatusCode status) {
|
||||||
|
if (!ui_task_runner_->RunsTasksOnCurrentThread()) {
|
||||||
|
ui_task_runner_->PostTask(
|
||||||
|
FROM_HERE,
|
||||||
|
base::Bind(&LocalFileSyncContext::DidInitialize,
|
||||||
|
this, source_url,
|
||||||
|
make_scoped_refptr(file_system_context), status));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
|
||||||
|
DCHECK(!ContainsKey(file_system_contexts_, file_system_context));
|
||||||
|
DCHECK(ContainsKey(pending_initialize_callbacks_, file_system_context));
|
||||||
|
DCHECK(file_system_context->change_tracker());
|
||||||
|
|
||||||
|
file_system_contexts_.insert(file_system_context);
|
||||||
|
|
||||||
|
DCHECK(!ContainsKey(origin_to_contexts_, source_url));
|
||||||
|
origin_to_contexts_[source_url] = file_system_context;
|
||||||
|
|
||||||
|
StatusCallbackQueue& callback_queue =
|
||||||
|
pending_initialize_callbacks_[file_system_context];
|
||||||
|
for (StatusCallbackQueue::iterator iter = callback_queue.begin();
|
||||||
|
iter != callback_queue.end(); ++iter) {
|
||||||
|
ui_task_runner_->PostTask(FROM_HERE, base::Bind(*iter, status));
|
||||||
|
}
|
||||||
|
pending_initialize_callbacks_.erase(file_system_context);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace fileapi
|
105
webkit/fileapi/syncable/local_file_sync_context.h
Normal file
105
webkit/fileapi/syncable/local_file_sync_context.h
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
#ifndef WEBKIT_FILEAPI_SYNCABLE_LOCAL_FILE_SYNC_CONTEXT_H_
|
||||||
|
#define WEBKIT_FILEAPI_SYNCABLE_LOCAL_FILE_SYNC_CONTEXT_H_
|
||||||
|
|
||||||
|
#include <deque>
|
||||||
|
#include <map>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
|
#include "base/basictypes.h"
|
||||||
|
#include "base/callback_forward.h"
|
||||||
|
#include "base/file_path.h"
|
||||||
|
#include "base/logging.h"
|
||||||
|
#include "base/memory/ref_counted.h"
|
||||||
|
#include "base/memory/scoped_ptr.h"
|
||||||
|
#include "googleurl/src/gurl.h"
|
||||||
|
#include "webkit/fileapi/fileapi_export.h"
|
||||||
|
#include "webkit/fileapi/syncable/file_change.h"
|
||||||
|
#include "webkit/fileapi/syncable/sync_status_code.h"
|
||||||
|
|
||||||
|
namespace base {
|
||||||
|
class SingleThreadTaskRunner;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace fileapi {
|
||||||
|
|
||||||
|
class FileSystemContext;
|
||||||
|
class LocalFileChangeTracker;
|
||||||
|
|
||||||
|
// This class works as a bridge between LocalFileSyncService (which is a
|
||||||
|
// per-profile object) and FileSystemContext's (which is a per-storage-partition
|
||||||
|
// object and may exist multiple in a profile).
|
||||||
|
// An instance of this class is shared by FileSystemContexts and outlives
|
||||||
|
// LocalFileSyncService.
|
||||||
|
class FILEAPI_EXPORT LocalFileSyncContext
|
||||||
|
: public base::RefCountedThreadSafe<LocalFileSyncContext> {
|
||||||
|
public:
|
||||||
|
typedef base::Callback<void(SyncStatusCode status)> StatusCallback;
|
||||||
|
|
||||||
|
LocalFileSyncContext(base::SingleThreadTaskRunner* ui_task_runner,
|
||||||
|
base::SingleThreadTaskRunner* io_task_runner);
|
||||||
|
|
||||||
|
// Initializes |file_system_context| for syncable file operations and
|
||||||
|
// registers the it into the internal map.
|
||||||
|
// Calling this multiple times for the same file_system_context is valid.
|
||||||
|
// This method must be called on UI thread.
|
||||||
|
void MaybeInitializeFileSystemContext(const GURL& source_url,
|
||||||
|
FileSystemContext* file_system_context,
|
||||||
|
const StatusCallback& callback);
|
||||||
|
|
||||||
|
// Called when the corresponding LocalFileSyncService exits.
|
||||||
|
// This method must be called on UI thread.
|
||||||
|
void ShutdownOnUIThread();
|
||||||
|
|
||||||
|
private:
|
||||||
|
typedef std::deque<StatusCallback> StatusCallbackQueue;
|
||||||
|
friend class base::RefCountedThreadSafe<LocalFileSyncContext>;
|
||||||
|
|
||||||
|
~LocalFileSyncContext();
|
||||||
|
|
||||||
|
void ShutdownOnIOThread();
|
||||||
|
|
||||||
|
// Helper routines for MaybeInitializeFileSystemContext.
|
||||||
|
void InitializeFileSystemContextOnIOThread(
|
||||||
|
const GURL& source_url,
|
||||||
|
FileSystemContext* file_system_context);
|
||||||
|
SyncStatusCode InitializeChangeTrackerOnFileThread(
|
||||||
|
scoped_ptr<LocalFileChangeTracker>* tracker_ptr,
|
||||||
|
FileSystemContext* file_system_context);
|
||||||
|
void DidInitializeChangeTracker(
|
||||||
|
scoped_ptr<LocalFileChangeTracker>* tracker_ptr,
|
||||||
|
const GURL& source_url,
|
||||||
|
FileSystemContext* file_system_context,
|
||||||
|
SyncStatusCode status);
|
||||||
|
void DidInitialize(
|
||||||
|
const GURL& source_url,
|
||||||
|
FileSystemContext* file_system_context,
|
||||||
|
SyncStatusCode status);
|
||||||
|
|
||||||
|
scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_;
|
||||||
|
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
|
||||||
|
|
||||||
|
// This must be accessed only on UI thread.
|
||||||
|
bool shutdown_;
|
||||||
|
|
||||||
|
// Pointers to file system contexts that have been initialized for
|
||||||
|
// synchronization (i.e. that own this instance).
|
||||||
|
// This must be accessed only on UI thread.
|
||||||
|
std::set<FileSystemContext*> file_system_contexts_;
|
||||||
|
|
||||||
|
std::map<FileSystemContext*, StatusCallbackQueue>
|
||||||
|
pending_initialize_callbacks_;
|
||||||
|
|
||||||
|
// Origin to context map. (Assuming that as far as we're in the same
|
||||||
|
// profile single origin wouldn't belong to multiple FileSystemContexts.)
|
||||||
|
std::map<GURL, FileSystemContext*> origin_to_contexts_;
|
||||||
|
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(LocalFileSyncContext);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace fileapi
|
||||||
|
|
||||||
|
#endif // WEBKIT_FILEAPI_SYNCABLE_LOCAL_FILE_SYNC_CONTEXT_H_
|
168
webkit/fileapi/syncable/local_file_sync_context_unittest.cc
Normal file
168
webkit/fileapi/syncable/local_file_sync_context_unittest.cc
Normal file
@ -0,0 +1,168 @@
|
|||||||
|
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
#include "webkit/fileapi/syncable/local_file_sync_context.h"
|
||||||
|
|
||||||
|
#include "base/bind.h"
|
||||||
|
#include "base/file_path.h"
|
||||||
|
#include "base/message_loop.h"
|
||||||
|
#include "base/single_thread_task_runner.h"
|
||||||
|
#include "base/threading/thread.h"
|
||||||
|
#include "testing/gtest/include/gtest/gtest.h"
|
||||||
|
#include "webkit/fileapi/file_system_context.h"
|
||||||
|
#include "webkit/fileapi/isolated_context.h"
|
||||||
|
#include "webkit/fileapi/syncable/canned_syncable_file_system.h"
|
||||||
|
#include "webkit/fileapi/syncable/local_file_change_tracker.h"
|
||||||
|
#include "webkit/fileapi/syncable/sync_status_code.h"
|
||||||
|
#include "webkit/fileapi/syncable/syncable_file_system_util.h"
|
||||||
|
|
||||||
|
namespace fileapi {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
const char kOrigin1[] = "http://example.com";
|
||||||
|
const char kOrigin2[] = "http://chromium.org";
|
||||||
|
const char kServiceName[] = "test";
|
||||||
|
const FileSystemType kSyncableType = kFileSystemTypeSyncable;
|
||||||
|
}
|
||||||
|
|
||||||
|
class LocalFileSyncContextTest : public testing::Test {
|
||||||
|
protected:
|
||||||
|
LocalFileSyncContextTest()
|
||||||
|
: status_(SYNC_FILE_ERROR_FAILED) {}
|
||||||
|
|
||||||
|
virtual void SetUp() OVERRIDE {
|
||||||
|
EXPECT_TRUE(fileapi::RegisterSyncableFileSystem(kServiceName));
|
||||||
|
|
||||||
|
io_thread_.reset(new base::Thread("Thread_IO"));
|
||||||
|
file_thread_.reset(new base::Thread("Thread_File"));
|
||||||
|
io_thread_->Start();
|
||||||
|
file_thread_->Start();
|
||||||
|
|
||||||
|
ui_task_runner_ = MessageLoop::current()->message_loop_proxy();
|
||||||
|
io_task_runner_ = io_thread_->message_loop_proxy();
|
||||||
|
file_task_runner_ = file_thread_->message_loop_proxy();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void TearDown() OVERRIDE {
|
||||||
|
EXPECT_TRUE(fileapi::RevokeSyncableFileSystem(kServiceName));
|
||||||
|
io_thread_->Stop();
|
||||||
|
file_thread_->Stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
// These need to remain until the very end.
|
||||||
|
scoped_ptr<base::Thread> io_thread_;
|
||||||
|
scoped_ptr<base::Thread> file_thread_;
|
||||||
|
MessageLoop loop_;
|
||||||
|
|
||||||
|
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
|
||||||
|
scoped_refptr<base::SingleThreadTaskRunner> file_task_runner_;
|
||||||
|
scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_;
|
||||||
|
|
||||||
|
scoped_refptr<LocalFileSyncContext> sync_context_;
|
||||||
|
|
||||||
|
SyncStatusCode status_;
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_F(LocalFileSyncContextTest, ConstructAndDestruct) {
|
||||||
|
sync_context_ = new LocalFileSyncContext(
|
||||||
|
ui_task_runner_, io_task_runner_);
|
||||||
|
sync_context_->ShutdownOnUIThread();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(LocalFileSyncContextTest, InitializeFileSystemContext) {
|
||||||
|
CannedSyncableFileSystem file_system(GURL(kOrigin1), kServiceName);
|
||||||
|
file_system.SetUp();
|
||||||
|
|
||||||
|
sync_context_ = new LocalFileSyncContext(ui_task_runner_, io_task_runner_);
|
||||||
|
|
||||||
|
// Initializes file_system using |sync_context_|.
|
||||||
|
EXPECT_EQ(SYNC_STATUS_OK,
|
||||||
|
file_system.MaybeInitializeFileSystemContext(sync_context_));
|
||||||
|
|
||||||
|
// Make sure everything's set up for file_system to be able to handle
|
||||||
|
// syncable file system operations.
|
||||||
|
EXPECT_TRUE(file_system.file_system_context()->sync_context() != NULL);
|
||||||
|
EXPECT_TRUE(file_system.file_system_context()->change_tracker() != NULL);
|
||||||
|
EXPECT_EQ(sync_context_.get(),
|
||||||
|
file_system.file_system_context()->sync_context());
|
||||||
|
|
||||||
|
// Calling MaybeInitialize for the same context multiple times must be ok.
|
||||||
|
EXPECT_EQ(SYNC_STATUS_OK,
|
||||||
|
file_system.MaybeInitializeFileSystemContext(sync_context_));
|
||||||
|
EXPECT_EQ(sync_context_.get(),
|
||||||
|
file_system.file_system_context()->sync_context());
|
||||||
|
|
||||||
|
// Opens the file_system, perform some operation and see if the change tracker
|
||||||
|
// correctly captures the change.
|
||||||
|
EXPECT_EQ(base::PLATFORM_FILE_OK, file_system.OpenFileSystem());
|
||||||
|
|
||||||
|
const FileSystemURL kURL(file_system.URL("foo"));
|
||||||
|
EXPECT_EQ(base::PLATFORM_FILE_OK, file_system.CreateFile(kURL));
|
||||||
|
|
||||||
|
std::vector<FileSystemURL> urls;
|
||||||
|
file_system.file_system_context()->change_tracker()->GetChangedURLs(&urls);
|
||||||
|
ASSERT_EQ(1U, urls.size());
|
||||||
|
EXPECT_EQ(kURL, urls[0]);
|
||||||
|
|
||||||
|
// Finishing the test.
|
||||||
|
sync_context_->ShutdownOnUIThread();
|
||||||
|
file_system.TearDown();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(LocalFileSyncContextTest, MultipleFileSystemContexts) {
|
||||||
|
CannedSyncableFileSystem file_system1(GURL(kOrigin1), kServiceName);
|
||||||
|
CannedSyncableFileSystem file_system2(GURL(kOrigin2), kServiceName);
|
||||||
|
file_system1.SetUp();
|
||||||
|
file_system2.SetUp();
|
||||||
|
|
||||||
|
sync_context_ = new LocalFileSyncContext(ui_task_runner_, io_task_runner_);
|
||||||
|
|
||||||
|
// Initializes file_system1 and file_system2.
|
||||||
|
EXPECT_EQ(SYNC_STATUS_OK,
|
||||||
|
file_system1.MaybeInitializeFileSystemContext(sync_context_));
|
||||||
|
EXPECT_EQ(SYNC_STATUS_OK,
|
||||||
|
file_system2.MaybeInitializeFileSystemContext(sync_context_));
|
||||||
|
|
||||||
|
EXPECT_EQ(base::PLATFORM_FILE_OK, file_system1.OpenFileSystem());
|
||||||
|
EXPECT_EQ(base::PLATFORM_FILE_OK, file_system2.OpenFileSystem());
|
||||||
|
|
||||||
|
const FileSystemURL kURL1(file_system1.URL("foo"));
|
||||||
|
const FileSystemURL kURL2(file_system2.URL("bar"));
|
||||||
|
|
||||||
|
// Creates a file in file_system1.
|
||||||
|
EXPECT_EQ(base::PLATFORM_FILE_OK, file_system1.CreateFile(kURL1));
|
||||||
|
|
||||||
|
// file_system1's tracker must have recorded the change.
|
||||||
|
std::vector<FileSystemURL> urls;
|
||||||
|
file_system1.file_system_context()->change_tracker()->GetChangedURLs(&urls);
|
||||||
|
ASSERT_EQ(1U, urls.size());
|
||||||
|
EXPECT_EQ(kURL1, urls[0]);
|
||||||
|
|
||||||
|
// file_system1's tracker must have no change.
|
||||||
|
urls.clear();
|
||||||
|
file_system2.file_system_context()->change_tracker()->GetChangedURLs(&urls);
|
||||||
|
ASSERT_TRUE(urls.empty());
|
||||||
|
|
||||||
|
// Creates a directory in file_system2.
|
||||||
|
EXPECT_EQ(base::PLATFORM_FILE_OK, file_system2.CreateDirectory(kURL2));
|
||||||
|
|
||||||
|
// file_system1's tracker must have the change for kURL1 as before.
|
||||||
|
urls.clear();
|
||||||
|
file_system1.file_system_context()->change_tracker()->GetChangedURLs(&urls);
|
||||||
|
ASSERT_EQ(1U, urls.size());
|
||||||
|
EXPECT_EQ(kURL1, urls[0]);
|
||||||
|
|
||||||
|
// file_system2's tracker now must have the change for kURL2.
|
||||||
|
urls.clear();
|
||||||
|
file_system2.file_system_context()->change_tracker()->GetChangedURLs(&urls);
|
||||||
|
ASSERT_EQ(1U, urls.size());
|
||||||
|
EXPECT_EQ(kURL2, urls[0]);
|
||||||
|
|
||||||
|
sync_context_->ShutdownOnUIThread();
|
||||||
|
|
||||||
|
file_system1.TearDown();
|
||||||
|
file_system2.TearDown();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace fileapi
|
@ -96,6 +96,8 @@
|
|||||||
'syncable/file_change.h',
|
'syncable/file_change.h',
|
||||||
'syncable/local_file_change_tracker.cc',
|
'syncable/local_file_change_tracker.cc',
|
||||||
'syncable/local_file_change_tracker.h',
|
'syncable/local_file_change_tracker.h',
|
||||||
|
'syncable/local_file_sync_context.cc',
|
||||||
|
'syncable/local_file_sync_context.h',
|
||||||
'syncable/local_file_sync_status.cc',
|
'syncable/local_file_sync_status.cc',
|
||||||
'syncable/local_file_sync_status.h',
|
'syncable/local_file_sync_status.h',
|
||||||
'syncable/sync_status_code.cc',
|
'syncable/sync_status_code.cc',
|
||||||
|
Reference in New Issue
Block a user