0

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:
kinuko@chromium.org
2012-10-12 11:28:54 +00:00
parent 41efb29da4
commit a8db44ec3a
9 changed files with 490 additions and 0 deletions

@ -433,6 +433,7 @@
'../webkit/fileapi/syncable/canned_syncable_file_system.h',
'../webkit/fileapi/syncable/file_change_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/syncable_file_system_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/sandbox_mount_point_provider.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/test_mount_point_provider.h"
#include "webkit/quota/quota_manager.h"
@ -289,6 +290,11 @@ void FileSystemContext::SetLocalFileChangeTracker(
task_runners_->file_task_runner());
}
void FileSystemContext::set_sync_context(
LocalFileSyncContext* sync_context) {
sync_context_ = sync_context;
}
FileSystemContext::~FileSystemContext() {}
void FileSystemContext::DeleteOnCorrectThread() const {

@ -41,6 +41,7 @@ class FileSystemURL;
class IsolatedMountPointProvider;
class LocalFileChangeTracker;
class SandboxMountPointProvider;
class LocalFileSyncContext;
struct DefaultContextDeleter;
@ -165,6 +166,9 @@ class FILEAPI_EXPORT FileSystemContext
LocalFileChangeTracker* change_tracker() { return change_tracker_.get(); }
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_; }
private:
@ -193,6 +197,7 @@ class FILEAPI_EXPORT FileSystemContext
// For syncable file systems.
scoped_ptr<LocalFileChangeTracker> change_tracker_;
scoped_refptr<LocalFileSyncContext> sync_context_;
DISALLOW_IMPLICIT_CONSTRUCTORS(FileSystemContext);
};

@ -15,6 +15,7 @@
#include "webkit/fileapi/isolated_context.h"
#include "webkit/fileapi/local_file_system_operation.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/quota_manager.h"
@ -29,12 +30,15 @@ CannedSyncableFileSystem::CannedSyncableFileSystem(
test_helper_(origin, kFileSystemTypeSyncable),
result_(base::PLATFORM_FILE_OK),
sync_status_(SYNC_STATUS_OK),
is_filesystem_set_up_(false),
is_filesystem_opened_(false),
weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
}
CannedSyncableFileSystem::~CannedSyncableFileSystem() {}
void CannedSyncableFileSystem::SetUp() {
ASSERT_FALSE(is_filesystem_set_up_);
ASSERT_TRUE(data_dir_.CreateUniqueTempDir());
scoped_refptr<quota::SpecialStoragePolicy> storage_policy =
@ -55,6 +59,7 @@ void CannedSyncableFileSystem::SetUp() {
CreateAllowFileAccessOptions());
test_helper_.SetUp(file_system_context_.get(), NULL);
is_filesystem_set_up_ = true;
}
void CannedSyncableFileSystem::TearDown() {
@ -63,10 +68,14 @@ void CannedSyncableFileSystem::TearDown() {
}
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));
}
PlatformFileError CannedSyncableFileSystem::OpenFileSystem() {
EXPECT_TRUE(is_filesystem_set_up_);
EXPECT_FALSE(is_filesystem_opened_);
file_system_context_->OpenSyncableFileSystem(
service_name_,
test_helper_.origin(), test_helper_.type(),
@ -77,8 +86,22 @@ PlatformFileError CannedSyncableFileSystem::OpenFileSystem() {
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(
const FileSystemURL& url) {
EXPECT_TRUE(is_filesystem_opened_);
result_ = base::PLATFORM_FILE_ERROR_FAILED;
test_helper_.NewOperation()->CreateDirectory(
url, false /* exclusive */, false /* recursive */,
@ -90,6 +113,7 @@ PlatformFileError CannedSyncableFileSystem::CreateDirectory(
PlatformFileError CannedSyncableFileSystem::CreateFile(
const FileSystemURL& url) {
EXPECT_TRUE(is_filesystem_opened_);
result_ = base::PLATFORM_FILE_ERROR_FAILED;
test_helper_.NewOperation()->CreateFile(
url, false /* exclusive */,
@ -123,6 +147,7 @@ PlatformFileError CannedSyncableFileSystem::Move(
PlatformFileError CannedSyncableFileSystem::TruncateFile(
const FileSystemURL& url, int64 size) {
EXPECT_TRUE(is_filesystem_opened_);
result_ = base::PLATFORM_FILE_ERROR_FAILED;
test_helper_.NewOperation()->Truncate(
url, size,
@ -134,6 +159,7 @@ PlatformFileError CannedSyncableFileSystem::TruncateFile(
PlatformFileError CannedSyncableFileSystem::Remove(
const FileSystemURL& url, bool recursive) {
EXPECT_TRUE(is_filesystem_opened_);
result_ = base::PLATFORM_FILE_ERROR_FAILED;
test_helper_.NewOperation()->Remove(
url, recursive,
@ -144,6 +170,7 @@ PlatformFileError CannedSyncableFileSystem::Remove(
}
PlatformFileError CannedSyncableFileSystem::DeleteFileSystem() {
EXPECT_TRUE(is_filesystem_set_up_);
file_system_context_->DeleteFileSystem(
test_helper_.origin(), test_helper_.type(),
base::Bind(&CannedSyncableFileSystem::StatusCallback,
@ -156,6 +183,13 @@ void CannedSyncableFileSystem::DidOpenFileSystem(
PlatformFileError result, const std::string& name, const GURL& root) {
result_ = result;
root_url_ = root;
is_filesystem_opened_ = true;
}
void CannedSyncableFileSystem::DidInitializeFileSystemContext(
SyncStatusCode status) {
sync_status_ = status;
MessageLoop::current()->Quit();
}
void CannedSyncableFileSystem::StatusCallback(PlatformFileError result) {

@ -27,6 +27,7 @@ class QuotaManager;
namespace fileapi {
class FileSystemContext;
class LocalFileSyncContext;
// A canned syncable filesystem for testing.
// This internally creates its own QuotaManager and FileSystemContext
@ -45,6 +46,11 @@ class CannedSyncableFileSystem {
// Creates a FileSystemURL for the given (utf8) path string.
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.
base::PlatformFileError OpenFileSystem();
@ -60,6 +66,7 @@ class CannedSyncableFileSystem {
}
// 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).
base::PlatformFileError CreateDirectory(const FileSystemURL& url);
base::PlatformFileError CreateFile(const FileSystemURL& url);
@ -78,6 +85,7 @@ class CannedSyncableFileSystem {
void DidOpenFileSystem(base::PlatformFileError result,
const std::string& name,
const GURL& root);
void DidInitializeFileSystemContext(SyncStatusCode status);
void StatusCallback(base::PlatformFileError result);
FileSystemOperationContext* NewOperationContext();
@ -92,6 +100,10 @@ class CannedSyncableFileSystem {
base::PlatformFileError result_;
SyncStatusCode sync_status_;
// Boolean flags mainly for helping debug.
bool is_filesystem_set_up_;
bool is_filesystem_opened_;
base::WeakPtrFactory<CannedSyncableFileSystem> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(CannedSyncableFileSystem);

@ -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

@ -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_

@ -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/local_file_change_tracker.cc',
'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.h',
'syncable/sync_status_code.cc',