Commit 7d2f9f57 authored by kinaba@chromium.org's avatar kinaba@chromium.org

gdata: File info of dirty files should be get from the cached file.

This CL is the part 2 (of 2) for fixing 138512.
In GDataFileSystem::GetEntry*() family of functions, check the
existence of dirty cache and if there exists, use the file
info from the cache file.

BUG=138512
TEST=unit_tests --gtest_filter='*GData*'
TEST=Manual:
- edit a file by photo editor and save as a different file.
- verify the file size and the date is displayed correctly for the edited file even if feed update intervenes.

Review URL: https://chromiumcodereview.appspot.com/10826006

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@148712 0039d316-1c4b-4281-b951-d872f2087c98
parent 80b050cf
...@@ -605,6 +605,17 @@ void PostBlockingPoolSequencedTaskAndReply( ...@@ -605,6 +605,17 @@ void PostBlockingPoolSequencedTaskAndReply(
DCHECK(posted); DCHECK(posted);
} }
// Helper function for binding |path| to GetEntryInfoWithFilePathCallback and
// create GetEntryInfoCallback.
void RunGetEntryInfoWithFilePathCallback(
const GetEntryInfoWithFilePathCallback& callback,
const FilePath& path,
GDataFileError error,
scoped_ptr<GDataEntryProto> entry_proto) {
if (!callback.is_null())
callback.Run(error, path, entry_proto.Pass());
}
} // namespace } // namespace
// GDataFileSystem::GetDocumentsParams struct implementation. // GDataFileSystem::GetDocumentsParams struct implementation.
...@@ -907,7 +918,10 @@ void GDataFileSystem::GetEntryInfoByEntryOnUIThread( ...@@ -907,7 +918,10 @@ void GDataFileSystem::GetEntryInfoByEntryOnUIThread(
if (entry) { if (entry) {
scoped_ptr<GDataEntryProto> entry_proto(new GDataEntryProto); scoped_ptr<GDataEntryProto> entry_proto(new GDataEntryProto);
entry->ToProtoFull(entry_proto.get()); entry->ToProtoFull(entry_proto.get());
callback.Run(GDATA_FILE_OK, entry->GetFilePath(), entry_proto.Pass()); CheckLocalModificationAndRun(
entry_proto.Pass(),
base::Bind(&RunGetEntryInfoWithFilePathCallback,
callback, entry->GetFilePath()));
} else { } else {
callback.Run(GDATA_FILE_ERROR_NOT_FOUND, callback.Run(GDATA_FILE_ERROR_NOT_FOUND,
FilePath(), FilePath(),
...@@ -2261,8 +2275,7 @@ void GDataFileSystem::OnGetEntryInfo(const GetEntryInfoCallback& callback, ...@@ -2261,8 +2275,7 @@ void GDataFileSystem::OnGetEntryInfo(const GetEntryInfoCallback& callback,
scoped_ptr<GDataEntryProto> entry_proto(new GDataEntryProto); scoped_ptr<GDataEntryProto> entry_proto(new GDataEntryProto);
entry->ToProtoFull(entry_proto.get()); entry->ToProtoFull(entry_proto.get());
if (!callback.is_null()) CheckLocalModificationAndRun(entry_proto.Pass(), callback);
callback.Run(GDATA_FILE_OK, entry_proto.Pass());
} }
void GDataFileSystem::ReadDirectoryByPath( void GDataFileSystem::ReadDirectoryByPath(
...@@ -4168,4 +4181,108 @@ void GDataFileSystem::OnCloseFileFinished( ...@@ -4168,4 +4181,108 @@ void GDataFileSystem::OnCloseFileFinished(
callback.Run(result); callback.Run(result);
} }
void GDataFileSystem::CheckLocalModificationAndRun(
scoped_ptr<GDataEntryProto> entry_proto,
const GetEntryInfoCallback& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(entry_proto.get());
// For entries that will never be cached, use the original entry info as is.
if (!entry_proto->has_file_specific_info() ||
entry_proto->file_specific_info().is_hosted_document()) {
if (!callback.is_null())
callback.Run(GDATA_FILE_OK, entry_proto.Pass());
return;
}
// Checks if the file is cached and modified locally.
const std::string resource_id = entry_proto->resource_id();
const std::string md5 = entry_proto->file_specific_info().file_md5();
cache_->GetCacheEntryOnUIThread(
resource_id,
md5,
base::Bind(
&GDataFileSystem::CheckLocalModificationAndRunAfterGetCacheEntry,
ui_weak_ptr_, base::Passed(&entry_proto), callback));
}
void GDataFileSystem::CheckLocalModificationAndRunAfterGetCacheEntry(
scoped_ptr<GDataEntryProto> entry_proto,
const GetEntryInfoCallback& callback,
bool success,
const GDataCacheEntry& cache_entry) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
// When no dirty cache is found, use the original entry info as is.
if (!success || !cache_entry.is_dirty()) {
if (!callback.is_null())
callback.Run(GDATA_FILE_OK, entry_proto.Pass());
return;
}
// Gets the cache file path.
const std::string& resource_id = entry_proto->resource_id();
const std::string& md5 = entry_proto->file_specific_info().file_md5();
cache_->GetFileOnUIThread(
resource_id,
md5,
base::Bind(
&GDataFileSystem::CheckLocalModificationAndRunAfterGetCacheFile,
ui_weak_ptr_, base::Passed(&entry_proto), callback));
}
void GDataFileSystem::CheckLocalModificationAndRunAfterGetCacheFile(
scoped_ptr<GDataEntryProto> entry_proto,
const GetEntryInfoCallback& callback,
GDataFileError error,
const std::string& resource_id,
const std::string& md5,
const FilePath& local_cache_path) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
// When no dirty cache is found, use the original entry info as is.
if (error != GDATA_FILE_OK) {
if (!callback.is_null())
callback.Run(GDATA_FILE_OK, entry_proto.Pass());
return;
}
// If the cache is dirty, obtain the file info from the cache file itself.
base::PlatformFileInfo* file_info = new base::PlatformFileInfo;
bool* get_file_info_result = new bool(false);
PostBlockingPoolSequencedTaskAndReply(
FROM_HERE,
blocking_task_runner_,
base::Bind(&GetFileInfoOnBlockingPool,
local_cache_path,
base::Unretained(file_info),
base::Unretained(get_file_info_result)),
base::Bind(&GDataFileSystem::CheckLocalModificationAndRunAfterGetFileInfo,
ui_weak_ptr_,
base::Passed(&entry_proto),
callback,
base::Owned(file_info),
base::Owned(get_file_info_result)));
}
void GDataFileSystem::CheckLocalModificationAndRunAfterGetFileInfo(
scoped_ptr<GDataEntryProto> entry_proto,
const GetEntryInfoCallback& callback,
base::PlatformFileInfo* file_info,
bool* get_file_info_result) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (!*get_file_info_result) {
if (!callback.is_null())
callback.Run(GDATA_FILE_ERROR_NOT_FOUND, scoped_ptr<GDataEntryProto>());
return;
}
PlatformFileInfoProto entry_file_info;
GDataEntry::ConvertPlatformFileInfoToProto(*file_info, &entry_file_info);
*entry_proto->mutable_file_info() = entry_file_info;
if (!callback.is_null())
callback.Run(GDATA_FILE_OK, entry_proto.Pass());
}
} // namespace gdata } // namespace gdata
...@@ -855,6 +855,29 @@ class GDataFileSystem : public GDataFileSystemInterface, ...@@ -855,6 +855,29 @@ class GDataFileSystem : public GDataFileSystemInterface,
GDataFileError error, GDataFileError error,
scoped_ptr<GDataEntryProto> entry_proto); scoped_ptr<GDataEntryProto> entry_proto);
// Part of GetEntryByResourceId and GetEntryByPath. Checks whether there is a
// local dirty cache for the entry, and if there is, replace the
// PlatformFileInfo part of the |entry_proto| with the locally modified info.
void CheckLocalModificationAndRun(scoped_ptr<GDataEntryProto> entry_proto,
const GetEntryInfoCallback& callback);
void CheckLocalModificationAndRunAfterGetCacheEntry(
scoped_ptr<GDataEntryProto> entry_proto,
const GetEntryInfoCallback& callback,
bool success,
const GDataCacheEntry& cache_entry);
void CheckLocalModificationAndRunAfterGetCacheFile(
scoped_ptr<GDataEntryProto> entry_proto,
const GetEntryInfoCallback& callback,
GDataFileError error,
const std::string& resource_id,
const std::string& md5,
const FilePath& local_cache_path);
void CheckLocalModificationAndRunAfterGetFileInfo(
scoped_ptr<GDataEntryProto> entry_proto,
const GetEntryInfoCallback& callback,
base::PlatformFileInfo* file_info,
bool* get_file_info_result);
// All members should be accessed only on UI thread. Do not post tasks to // All members should be accessed only on UI thread. Do not post tasks to
// other threads with base::Unretained(this). // other threads with base::Unretained(this).
scoped_ptr<GDataDirectoryService> directory_service_; scoped_ptr<GDataDirectoryService> directory_service_;
......
...@@ -355,7 +355,7 @@ class GDataFileSystemTest : public testing::Test { ...@@ -355,7 +355,7 @@ class GDataFileSystemTest : public testing::Test {
file_path, file_path,
base::Bind(&CallbackHelper::GetEntryInfoCallback, base::Bind(&CallbackHelper::GetEntryInfoCallback,
callback_helper_.get())); callback_helper_.get()));
message_loop_.RunAllPending(); test_util::RunBlockingPoolTask();
return callback_helper_->entry_proto_.Pass(); return callback_helper_->entry_proto_.Pass();
} }
...@@ -367,7 +367,7 @@ class GDataFileSystemTest : public testing::Test { ...@@ -367,7 +367,7 @@ class GDataFileSystemTest : public testing::Test {
file_path, file_path,
base::Bind(&CallbackHelper::ReadDirectoryCallback, base::Bind(&CallbackHelper::ReadDirectoryCallback,
callback_helper_.get())); callback_helper_.get()));
message_loop_.RunAllPending(); test_util::RunBlockingPoolTask();
return callback_helper_->directory_entries_.Pass(); return callback_helper_->directory_entries_.Pass();
} }
...@@ -1388,7 +1388,7 @@ TEST_F(GDataFileSystemTest, CopyNotExistingFile) { ...@@ -1388,7 +1388,7 @@ TEST_F(GDataFileSystemTest, CopyNotExistingFile) {
callback_helper_.get()); callback_helper_.get());
file_system_->Copy(src_file_path, dest_file_path, callback); file_system_->Copy(src_file_path, dest_file_path, callback);
message_loop_.RunAllPending(); // Wait to get our result test_util::RunBlockingPoolTask();
EXPECT_EQ(GDATA_FILE_ERROR_NOT_FOUND, callback_helper_->last_error_); EXPECT_EQ(GDATA_FILE_ERROR_NOT_FOUND, callback_helper_->last_error_);
EXPECT_FALSE(EntryExists(src_file_path)); EXPECT_FALSE(EntryExists(src_file_path));
...@@ -1417,7 +1417,7 @@ TEST_F(GDataFileSystemTest, CopyFileToNonExistingDirectory) { ...@@ -1417,7 +1417,7 @@ TEST_F(GDataFileSystemTest, CopyFileToNonExistingDirectory) {
callback_helper_.get()); callback_helper_.get());
file_system_->Move(src_file_path, dest_file_path, callback); file_system_->Move(src_file_path, dest_file_path, callback);
message_loop_.RunAllPending(); test_util::RunBlockingPoolTask();
EXPECT_EQ(GDATA_FILE_ERROR_NOT_FOUND, callback_helper_->last_error_); EXPECT_EQ(GDATA_FILE_ERROR_NOT_FOUND, callback_helper_->last_error_);
EXPECT_TRUE(EntryExists(src_file_path)); EXPECT_TRUE(EntryExists(src_file_path));
...@@ -1453,7 +1453,7 @@ TEST_F(GDataFileSystemTest, CopyFileToInvalidPath) { ...@@ -1453,7 +1453,7 @@ TEST_F(GDataFileSystemTest, CopyFileToInvalidPath) {
callback_helper_.get()); callback_helper_.get());
file_system_->Copy(src_file_path, dest_file_path, callback); file_system_->Copy(src_file_path, dest_file_path, callback);
message_loop_.RunAllPending(); test_util::RunBlockingPoolTask();
EXPECT_EQ(GDATA_FILE_ERROR_NOT_A_DIRECTORY, EXPECT_EQ(GDATA_FILE_ERROR_NOT_A_DIRECTORY,
callback_helper_->last_error_); callback_helper_->last_error_);
...@@ -1492,7 +1492,7 @@ TEST_F(GDataFileSystemTest, RenameFile) { ...@@ -1492,7 +1492,7 @@ TEST_F(GDataFileSystemTest, RenameFile) {
Eq(FilePath(FILE_PATH_LITERAL("drive/Directory 1"))))).Times(1); Eq(FilePath(FILE_PATH_LITERAL("drive/Directory 1"))))).Times(1);
file_system_->Move(src_file_path, dest_file_path, callback); file_system_->Move(src_file_path, dest_file_path, callback);
message_loop_.RunAllPending(); test_util::RunBlockingPoolTask();
EXPECT_EQ(GDATA_FILE_OK, callback_helper_->last_error_); EXPECT_EQ(GDATA_FILE_OK, callback_helper_->last_error_);
EXPECT_FALSE(EntryExists(src_file_path)); EXPECT_FALSE(EntryExists(src_file_path));
...@@ -1541,7 +1541,7 @@ TEST_F(GDataFileSystemTest, MoveFileFromRootToSubDirectory) { ...@@ -1541,7 +1541,7 @@ TEST_F(GDataFileSystemTest, MoveFileFromRootToSubDirectory) {
Eq(FilePath(FILE_PATH_LITERAL("drive/Directory 1"))))).Times(1); Eq(FilePath(FILE_PATH_LITERAL("drive/Directory 1"))))).Times(1);
file_system_->Move(src_file_path, dest_file_path, callback); file_system_->Move(src_file_path, dest_file_path, callback);
message_loop_.RunAllPending(); test_util::RunBlockingPoolTask();
EXPECT_EQ(GDATA_FILE_OK, callback_helper_->last_error_); EXPECT_EQ(GDATA_FILE_OK, callback_helper_->last_error_);
EXPECT_FALSE(EntryExists(src_file_path)); EXPECT_FALSE(EntryExists(src_file_path));
...@@ -1592,7 +1592,7 @@ TEST_F(GDataFileSystemTest, MoveFileFromSubDirectoryToRoot) { ...@@ -1592,7 +1592,7 @@ TEST_F(GDataFileSystemTest, MoveFileFromSubDirectoryToRoot) {
Eq(FilePath(FILE_PATH_LITERAL("drive/Directory 1"))))).Times(1); Eq(FilePath(FILE_PATH_LITERAL("drive/Directory 1"))))).Times(1);
file_system_->Move(src_file_path, dest_file_path, callback); file_system_->Move(src_file_path, dest_file_path, callback);
message_loop_.RunAllPending(); test_util::RunBlockingPoolTask();
EXPECT_EQ(GDATA_FILE_OK, callback_helper_->last_error_); EXPECT_EQ(GDATA_FILE_OK, callback_helper_->last_error_);
EXPECT_FALSE(EntryExists(src_file_path)); EXPECT_FALSE(EntryExists(src_file_path));
...@@ -1667,7 +1667,7 @@ TEST_F(GDataFileSystemTest, MoveFileBetweenSubDirectories) { ...@@ -1667,7 +1667,7 @@ TEST_F(GDataFileSystemTest, MoveFileBetweenSubDirectories) {
Eq(FilePath(FILE_PATH_LITERAL("drive/New Folder 1"))))).Times(1); Eq(FilePath(FILE_PATH_LITERAL("drive/New Folder 1"))))).Times(1);
file_system_->Move(src_file_path, dest_file_path, callback); file_system_->Move(src_file_path, dest_file_path, callback);
message_loop_.RunAllPending(); test_util::RunBlockingPoolTask();
EXPECT_EQ(GDATA_FILE_OK, callback_helper_->last_error_); EXPECT_EQ(GDATA_FILE_OK, callback_helper_->last_error_);
EXPECT_FALSE(EntryExists(src_file_path)); EXPECT_FALSE(EntryExists(src_file_path));
...@@ -1691,7 +1691,7 @@ TEST_F(GDataFileSystemTest, MoveNotExistingFile) { ...@@ -1691,7 +1691,7 @@ TEST_F(GDataFileSystemTest, MoveNotExistingFile) {
callback_helper_.get()); callback_helper_.get());
file_system_->Move(src_file_path, dest_file_path, callback); file_system_->Move(src_file_path, dest_file_path, callback);
message_loop_.RunAllPending(); // Wait to get our result test_util::RunBlockingPoolTask();
EXPECT_EQ(GDATA_FILE_ERROR_NOT_FOUND, callback_helper_->last_error_); EXPECT_EQ(GDATA_FILE_ERROR_NOT_FOUND, callback_helper_->last_error_);
EXPECT_FALSE(EntryExists(src_file_path)); EXPECT_FALSE(EntryExists(src_file_path));
...@@ -1720,7 +1720,7 @@ TEST_F(GDataFileSystemTest, MoveFileToNonExistingDirectory) { ...@@ -1720,7 +1720,7 @@ TEST_F(GDataFileSystemTest, MoveFileToNonExistingDirectory) {
callback_helper_.get()); callback_helper_.get());
file_system_->Move(src_file_path, dest_file_path, callback); file_system_->Move(src_file_path, dest_file_path, callback);
message_loop_.RunAllPending(); test_util::RunBlockingPoolTask();
EXPECT_EQ(GDATA_FILE_ERROR_NOT_FOUND, callback_helper_->last_error_); EXPECT_EQ(GDATA_FILE_ERROR_NOT_FOUND, callback_helper_->last_error_);
...@@ -1756,7 +1756,7 @@ TEST_F(GDataFileSystemTest, MoveFileToInvalidPath) { ...@@ -1756,7 +1756,7 @@ TEST_F(GDataFileSystemTest, MoveFileToInvalidPath) {
callback_helper_.get()); callback_helper_.get());
file_system_->Move(src_file_path, dest_file_path, callback); file_system_->Move(src_file_path, dest_file_path, callback);
message_loop_.RunAllPending(); test_util::RunBlockingPoolTask();
EXPECT_EQ(GDATA_FILE_ERROR_NOT_A_DIRECTORY, EXPECT_EQ(GDATA_FILE_ERROR_NOT_A_DIRECTORY,
callback_helper_->last_error_); callback_helper_->last_error_);
...@@ -1915,7 +1915,7 @@ TEST_F(GDataFileSystemTest, CreateDirectoryWithService) { ...@@ -1915,7 +1915,7 @@ TEST_F(GDataFileSystemTest, CreateDirectoryWithService) {
true, // is_recursive true, // is_recursive
base::Bind(&CallbackHelper::FileOperationCallback, base::Bind(&CallbackHelper::FileOperationCallback,
callback_helper_.get())); callback_helper_.get()));
message_loop_.RunAllPending(); test_util::RunBlockingPoolTask();
// TODO(gspencer): Uncomment this when we get a blob that // TODO(gspencer): Uncomment this when we get a blob that
// works that can be returned from the mock. // works that can be returned from the mock.
// EXPECT_EQ(GDATA_FILE_OK, callback_helper_->last_error_); // EXPECT_EQ(GDATA_FILE_OK, callback_helper_->last_error_);
...@@ -2452,7 +2452,7 @@ TEST_F(GDataFileSystemTest, GetAvailableSpace) { ...@@ -2452,7 +2452,7 @@ TEST_F(GDataFileSystemTest, GetAvailableSpace) {
EXPECT_CALL(*mock_doc_service_, GetAccountMetadata(_)); EXPECT_CALL(*mock_doc_service_, GetAccountMetadata(_));
file_system_->GetAvailableSpace(callback); file_system_->GetAvailableSpace(callback);
message_loop_.RunAllPending(); test_util::RunBlockingPoolTask();
EXPECT_EQ(GG_LONGLONG(6789012345), callback_helper_->quota_bytes_used_); EXPECT_EQ(GG_LONGLONG(6789012345), callback_helper_->quota_bytes_used_);
EXPECT_EQ(GG_LONGLONG(9876543210), callback_helper_->quota_bytes_total_); EXPECT_EQ(GG_LONGLONG(9876543210), callback_helper_->quota_bytes_total_);
} }
...@@ -2469,7 +2469,7 @@ TEST_F(GDataFileSystemTest, RequestDirectoryRefresh) { ...@@ -2469,7 +2469,7 @@ TEST_F(GDataFileSystemTest, RequestDirectoryRefresh) {
OnDirectoryChanged(Eq(FilePath(kGDataRootDirectory)))).Times(1); OnDirectoryChanged(Eq(FilePath(kGDataRootDirectory)))).Times(1);
file_system_->RequestDirectoryRefresh(FilePath(kGDataRootDirectory)); file_system_->RequestDirectoryRefresh(FilePath(kGDataRootDirectory));
message_loop_.RunAllPending(); test_util::RunBlockingPoolTask();
} }
TEST_F(GDataFileSystemTest, OpenAndCloseFile) { TEST_F(GDataFileSystemTest, OpenAndCloseFile) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment