Commit 821fb4f2 authored by satorux@chromium.org's avatar satorux@chromium.org

gdata: Add GDataFileSystem::GetFileInfoByPathAsync().

In preparation for removing GetFileInfoByPath(), which is a synchronous
function. The new function is not used in production code yet.

BUG=chromium-os:30066
TEST=add unit tests

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

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@134589 0039d316-1c4b-4281-b951-d872f2087c98
parent 73b82025
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include "base/threading/thread_restrictions.h" #include "base/threading/thread_restrictions.h"
#include "base/synchronization/waitable_event.h" #include "base/synchronization/waitable_event.h"
#include "base/values.h" #include "base/values.h"
#include "chrome/browser/chromeos/gdata/gdata.pb.h"
#include "chrome/browser/chromeos/gdata/gdata_documents_service.h" #include "chrome/browser/chromeos/gdata/gdata_documents_service.h"
#include "chrome/browser/chromeos/gdata/gdata_download_observer.h" #include "chrome/browser/chromeos/gdata/gdata_download_observer.h"
#include "chrome/browser/chromeos/gdata/gdata_protocol_handler.h" #include "chrome/browser/chromeos/gdata/gdata_protocol_handler.h"
...@@ -808,6 +809,17 @@ void RelaySetMountedStateCallback( ...@@ -808,6 +809,17 @@ void RelaySetMountedStateCallback(
base::Bind(callback, error, file_path)); base::Bind(callback, error, file_path));
} }
// Ditto for GetFileInfoCallback.
void RelayGetFileInfoCallback(
scoped_refptr<base::MessageLoopProxy> relay_proxy,
const GetFileInfoCallback& callback,
base::PlatformFileError error,
scoped_ptr<GDataFileProto> file_proto) {
relay_proxy->PostTask(
FROM_HERE,
base::Bind(callback, error, base::Passed(&file_proto)));
}
} // namespace } // namespace
// GDataFileProperties struct implementation. // GDataFileProperties struct implementation.
...@@ -2104,6 +2116,66 @@ void GDataFileSystem::ResumeUpload( ...@@ -2104,6 +2116,66 @@ void GDataFileSystem::ResumeUpload(
documents_service_->ResumeUpload(params, callback); documents_service_->ResumeUpload(params, callback);
} }
void GDataFileSystem::GetFileInfoByPathAsync(
const FilePath& file_path,
const GetFileInfoCallback& callback) {
if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
const bool posted = BrowserThread::PostTask(
BrowserThread::UI,
FROM_HERE,
base::Bind(&GDataFileSystem::GetFileInfoByPathAsync,
ui_weak_ptr_,
file_path,
base::Bind(&RelayGetFileInfoCallback,
base::MessageLoopProxy::current(),
callback)));
DCHECK(posted);
return;
}
GetFileInfoByPathAsyncOnUIThread(file_path, callback);
}
void GDataFileSystem::GetFileInfoByPathAsyncOnUIThread(
const FilePath& file_path,
const GetFileInfoCallback& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
FindEntryByPathAsyncOnUIThread(
file_path,
base::Bind(&GDataFileSystem::OnEntryFound,
ui_weak_ptr_,
callback));
}
void GDataFileSystem::OnEntryFound(const GetFileInfoCallback& callback,
base::PlatformFileError error,
const FilePath& directory_path,
GDataEntry* entry) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (error != base::PLATFORM_FILE_OK) {
if (!callback.is_null())
callback.Run(error, scoped_ptr<GDataFileProto>());
return;
}
GDataFile* file = entry->AsGDataFile();
if (!file) {
if (!callback.is_null())
callback.Run(base::PLATFORM_FILE_ERROR_NOT_FOUND,
scoped_ptr<GDataFileProto>());
return;
}
scoped_ptr<GDataFileProto> file_proto(new GDataFileProto);
file->ToProto(file_proto.get());
if (!callback.is_null())
callback.Run(base::PLATFORM_FILE_OK, file_proto.Pass());
}
bool GDataFileSystem::GetFileInfoByPath( bool GDataFileSystem::GetFileInfoByPath(
const FilePath& file_path, GDataFileProperties* properties) { const FilePath& file_path, GDataFileProperties* properties) {
DCHECK(properties); DCHECK(properties);
......
...@@ -39,6 +39,7 @@ class WaitableEvent; ...@@ -39,6 +39,7 @@ class WaitableEvent;
namespace gdata { namespace gdata {
class DocumentsServiceInterface; class DocumentsServiceInterface;
class GDataFileProto;
struct UploadFileInfo; struct UploadFileInfo;
namespace { namespace {
...@@ -68,6 +69,12 @@ typedef base::Callback<void(base::PlatformFileError error, ...@@ -68,6 +69,12 @@ typedef base::Callback<void(base::PlatformFileError error,
GDataFileType file_type)> GDataFileType file_type)>
GetFileCallback; GetFileCallback;
// Used to get file info from the file system.
// If |error| is not PLATFORM_FILE_OK, |file_info| is set to NULL.
typedef base::Callback<void(base::PlatformFileError error,
scoped_ptr<GDataFileProto> file_proto)>
GetFileInfoCallback;
// Callback for SetMountedState. // Callback for SetMountedState.
typedef base::Callback<void(base::PlatformFileError error, typedef base::Callback<void(base::PlatformFileError error,
const FilePath& file_path)> const FilePath& file_path)>
...@@ -99,6 +106,7 @@ typedef base::Callback<void(base::PlatformFileError error, ...@@ -99,6 +106,7 @@ typedef base::Callback<void(base::PlatformFileError error,
int cache_state)> GetCacheStateCallback; int cache_state)> GetCacheStateCallback;
// Helper structure used for extracting key properties from GDataFile object. // Helper structure used for extracting key properties from GDataFile object.
// TODO(satorux): Remove this as part of crosbug.com/30066
struct GDataFileProperties { struct GDataFileProperties {
GDataFileProperties(); GDataFileProperties();
~GDataFileProperties(); ~GDataFileProperties();
...@@ -307,7 +315,13 @@ class GDataFileSystemInterface { ...@@ -307,7 +315,13 @@ class GDataFileSystemInterface {
// Finds a file (not a directory) by |file_path| and returns its key // Finds a file (not a directory) by |file_path| and returns its key
// |properties|. Returns true if file was found. // |properties|. Returns true if file was found.
virtual bool GetFileInfoByPath(const FilePath& gdata_file_path, virtual void GetFileInfoByPathAsync(const FilePath& file_path,
const GetFileInfoCallback& callback) = 0;
// Finds a file (not a directory) by |file_path| and returns its key
// |properties|. Returns true if file was found.
// TODO(satorux): Remove this: crosbug.com/30066.
virtual bool GetFileInfoByPath(const FilePath& file_path,
GDataFileProperties* properties) = 0; GDataFileProperties* properties) = 0;
// Returns true if the given path is under gdata cache directory, i.e. // Returns true if the given path is under gdata cache directory, i.e.
...@@ -396,7 +410,10 @@ class GDataFileSystem : public GDataFileSystemInterface, ...@@ -396,7 +410,10 @@ class GDataFileSystem : public GDataFileSystemInterface,
virtual void GetCacheState(const std::string& resource_id, virtual void GetCacheState(const std::string& resource_id,
const std::string& md5, const std::string& md5,
const GetCacheStateCallback& callback) OVERRIDE; const GetCacheStateCallback& callback) OVERRIDE;
virtual bool GetFileInfoByPath(const FilePath& gdata_file_path, virtual void GetFileInfoByPathAsync(
const FilePath& file_path,
const GetFileInfoCallback& callback) OVERRIDE;
virtual bool GetFileInfoByPath(const FilePath& file_path,
GDataFileProperties* properties) OVERRIDE; GDataFileProperties* properties) OVERRIDE;
virtual bool IsUnderGDataCacheDirectory(const FilePath& path) const OVERRIDE; virtual bool IsUnderGDataCacheDirectory(const FilePath& path) const OVERRIDE;
virtual FilePath GetCacheDirectoryPath( virtual FilePath GetCacheDirectoryPath(
...@@ -1194,6 +1211,12 @@ class GDataFileSystem : public GDataFileSystemInterface, ...@@ -1194,6 +1211,12 @@ class GDataFileSystem : public GDataFileSystemInterface,
// Initializes preference change observer. // Initializes preference change observer.
void InitializePreferenceObserver(); void InitializePreferenceObserver();
// Called when an entry is found for GetFileInfoByPath().
void OnEntryFound(const GetFileInfoCallback& callback,
base::PlatformFileError error,
const FilePath& directory_path,
GDataEntry* entry);
// The following functions are used to forward calls to asynchronous public // The following functions are used to forward calls to asynchronous public
// member functions to UI thread. // member functions to UI thread.
void FindEntryByPathAsyncOnUIThread(const FilePath& search_file_path, void FindEntryByPathAsyncOnUIThread(const FilePath& search_file_path,
...@@ -1219,6 +1242,9 @@ class GDataFileSystem : public GDataFileSystemInterface, ...@@ -1219,6 +1242,9 @@ class GDataFileSystem : public GDataFileSystemInterface,
const std::string& resource_id, const std::string& resource_id,
const GetFileCallback& get_file_callback, const GetFileCallback& get_file_callback,
const GetDownloadDataCallback& get_download_data_callback); const GetDownloadDataCallback& get_download_data_callback);
void GetFileInfoByPathAsyncOnUIThread(
const FilePath& file_path,
const GetFileInfoCallback& callback);
void GetCacheStateOnUIThread(const std::string& resource_id, void GetCacheStateOnUIThread(const std::string& resource_id,
const std::string& md5, const std::string& md5,
const GetCacheStateCallback& callback); const GetCacheStateCallback& callback);
......
...@@ -271,10 +271,30 @@ class GDataFileSystemTest : public testing::Test { ...@@ -271,10 +271,30 @@ class GDataFileSystemTest : public testing::Test {
GDataEntry* FindEntryByResourceId(const std::string& resource_id) { GDataEntry* FindEntryByResourceId(const std::string& resource_id) {
ReadOnlyFindEntryDelegate search_delegate; ReadOnlyFindEntryDelegate search_delegate;
file_system_->FindEntryByResourceIdSync(resource_id, file_system_->FindEntryByResourceIdSync(resource_id,
&search_delegate); &search_delegate);
return search_delegate.entry(); return search_delegate.entry();
} }
// Gets the file info for |file_path| and compares the contents against
// |entry|. Returns true if the file info matches |entry|.
bool GetFileInfoAndCompare(const FilePath& file_path,
GDataEntry* entry) {
file_system_->GetFileInfoByPathAsync(
file_path,
base::Bind(&CallbackHelper::GetFileInfoCallback,
callback_helper_.get()));
message_loop_.RunAllPending();
if (entry == NULL) {
// File info is expected not to be found.
return callback_helper_->file_info_ == NULL;
}
scoped_ptr<GDataFileProto> file_info =
callback_helper_->file_info_.Pass();
return (entry->resource_id() == file_info->gdata_entry().resource_id());
}
FilePath GetCacheFilePath( FilePath GetCacheFilePath(
const std::string& resource_id, const std::string& resource_id,
const std::string& md5, const std::string& md5,
...@@ -950,7 +970,8 @@ class GDataFileSystemTest : public testing::Test { ...@@ -950,7 +970,8 @@ class GDataFileSystemTest : public testing::Test {
CallbackHelper() CallbackHelper()
: last_error_(base::PLATFORM_FILE_OK), : last_error_(base::PLATFORM_FILE_OK),
quota_bytes_total_(0), quota_bytes_total_(0),
quota_bytes_used_(0) {} quota_bytes_used_(0),
file_info_(NULL) {}
virtual ~CallbackHelper() {} virtual ~CallbackHelper() {}
virtual void GetFileCallback(base::PlatformFileError error, virtual void GetFileCallback(base::PlatformFileError error,
const FilePath& file_path, const FilePath& file_path,
...@@ -973,6 +994,12 @@ class GDataFileSystemTest : public testing::Test { ...@@ -973,6 +994,12 @@ class GDataFileSystemTest : public testing::Test {
quota_bytes_total_ = bytes_total; quota_bytes_total_ = bytes_total;
quota_bytes_used_ = bytes_used; quota_bytes_used_ = bytes_used;
} }
virtual void GetFileInfoCallback(
base::PlatformFileError error,
scoped_ptr<GDataFileProto> file_info) {
last_error_ = error;
file_info_ = file_info.Pass();
}
base::PlatformFileError last_error_; base::PlatformFileError last_error_;
FilePath download_path_; FilePath download_path_;
...@@ -980,6 +1007,7 @@ class GDataFileSystemTest : public testing::Test { ...@@ -980,6 +1007,7 @@ class GDataFileSystemTest : public testing::Test {
GDataFileType file_type_; GDataFileType file_type_;
int64 quota_bytes_total_; int64 quota_bytes_total_;
int64 quota_bytes_used_; int64 quota_bytes_used_;
scoped_ptr<GDataFileProto> file_info_;
}; };
MessageLoopForUI message_loop_; MessageLoopForUI message_loop_;
...@@ -1042,77 +1070,139 @@ TEST_F(GDataFileSystemTest, DuplicatedAsyncInitialization) { ...@@ -1042,77 +1070,139 @@ TEST_F(GDataFileSystemTest, DuplicatedAsyncInitialization) {
} }
TEST_F(GDataFileSystemTest, SearchRootDirectory) { TEST_F(GDataFileSystemTest, SearchRootDirectory) {
EXPECT_TRUE(FindEntry(FilePath(FILE_PATH_LITERAL("gdata")))); const FilePath kFilePath = FilePath(FILE_PATH_LITERAL("gdata"));
GDataEntry* entry = FindEntry(FilePath(FILE_PATH_LITERAL(kFilePath)));
ASSERT_TRUE(entry);
EXPECT_EQ(kFilePath, entry->GetFilePath());
} }
TEST_F(GDataFileSystemTest, SearchExistingFile) { TEST_F(GDataFileSystemTest, SearchExistingFile) {
LoadRootFeedDocument("root_feed.json"); LoadRootFeedDocument("root_feed.json");
EXPECT_TRUE(FindEntry(FilePath(FILE_PATH_LITERAL("gdata/File 1.txt"))));
const FilePath kFilePath = FilePath(
FILE_PATH_LITERAL("gdata/File 1.txt"));
GDataEntry* entry = FindEntry(kFilePath);
ASSERT_TRUE(entry);
EXPECT_EQ(kFilePath, entry->GetFilePath());
EXPECT_TRUE(GetFileInfoAndCompare(kFilePath, entry));
} }
TEST_F(GDataFileSystemTest, SearchExistingDocument) { TEST_F(GDataFileSystemTest, SearchExistingDocument) {
LoadRootFeedDocument("root_feed.json"); LoadRootFeedDocument("root_feed.json");
EXPECT_TRUE(FindEntry(FilePath(FILE_PATH_LITERAL("gdata/Document 1.gdoc"))));
const FilePath kFilePath = FilePath(
FILE_PATH_LITERAL("gdata/Document 1.gdoc"));
GDataEntry* entry = FindEntry(kFilePath);
ASSERT_TRUE(entry);
EXPECT_EQ(kFilePath, entry->GetFilePath());
EXPECT_TRUE(GetFileInfoAndCompare(kFilePath, entry));
} }
TEST_F(GDataFileSystemTest, SearchNonExistingFile) { TEST_F(GDataFileSystemTest, SearchNonExistingFile) {
LoadRootFeedDocument("root_feed.json"); LoadRootFeedDocument("root_feed.json");
EXPECT_FALSE(
FindEntry(FilePath(FILE_PATH_LITERAL("gdata/nonexisting.file")))); const FilePath kFilePath = FilePath(
FILE_PATH_LITERAL("gdata/nonexisting.file"));
GDataEntry* entry = FindEntry(kFilePath);
ASSERT_FALSE(entry);
EXPECT_TRUE(GetFileInfoAndCompare(kFilePath, NULL));
} }
TEST_F(GDataFileSystemTest, SearchEncodedFileNames) { TEST_F(GDataFileSystemTest, SearchEncodedFileNames) {
LoadRootFeedDocument("root_feed.json"); LoadRootFeedDocument("root_feed.json");
EXPECT_FALSE(FindEntry(FilePath(FILE_PATH_LITERAL( const FilePath kFilePath1 = FilePath(
"gdata/Slash / in file 1.txt")))); FILE_PATH_LITERAL("gdata/Slash / in file 1.txt"));
GDataEntry* entry = FindEntry(kFilePath1);
EXPECT_TRUE(FindEntry(FilePath::FromUTF8Unsafe( ASSERT_FALSE(entry);
"gdata/Slash \xE2\x88\x95 in file 1.txt")));
const FilePath kFilePath2 = FilePath::FromUTF8Unsafe(
EXPECT_TRUE(FindEntry(FilePath::FromUTF8Unsafe( "gdata/Slash \xE2\x88\x95 in file 1.txt");
"gdata/Slash \xE2\x88\x95 in directory/Slash SubDir File.txt"))); entry = FindEntry(kFilePath2);
ASSERT_TRUE(entry);
EXPECT_EQ(kFilePath2, entry->GetFilePath());
EXPECT_TRUE(GetFileInfoAndCompare(kFilePath2, entry));
const FilePath kFilePath3 = FilePath::FromUTF8Unsafe(
"gdata/Slash \xE2\x88\x95 in directory/Slash SubDir File.txt");
entry = FindEntry(kFilePath3);
ASSERT_TRUE(entry);
EXPECT_EQ(kFilePath3, entry->GetFilePath());
EXPECT_TRUE(GetFileInfoAndCompare(kFilePath3, entry));
} }
TEST_F(GDataFileSystemTest, SearchEncodedFileNamesLoadingRoot) { TEST_F(GDataFileSystemTest, SearchEncodedFileNamesLoadingRoot) {
LoadRootFeedDocument("root_feed.json"); LoadRootFeedDocument("root_feed.json");
EXPECT_FALSE(FindEntry(FilePath(FILE_PATH_LITERAL( const FilePath kFilePath1 = FilePath(
"gdata/Slash / in file 1.txt")))); FILE_PATH_LITERAL("gdata/Slash / in file 1.txt"));
GDataEntry* entry = FindEntry(kFilePath1);
EXPECT_TRUE(FindEntry(FilePath::FromUTF8Unsafe( ASSERT_FALSE(entry);
"gdata/Slash \xE2\x88\x95 in file 1.txt")));
const FilePath kFilePath2 = FilePath::FromUTF8Unsafe(
EXPECT_TRUE(FindEntry(FilePath::FromUTF8Unsafe( "gdata/Slash \xE2\x88\x95 in file 1.txt");
"gdata/Slash \xE2\x88\x95 in directory/Slash SubDir File.txt"))); entry = FindEntry(kFilePath2);
ASSERT_TRUE(entry);
EXPECT_EQ(kFilePath2, entry->GetFilePath());
EXPECT_TRUE(GetFileInfoAndCompare(kFilePath2, entry));
const FilePath kFilePath3 = FilePath::FromUTF8Unsafe(
"gdata/Slash \xE2\x88\x95 in directory/Slash SubDir File.txt");
entry = FindEntry(kFilePath3);
ASSERT_TRUE(entry);
EXPECT_EQ(kFilePath3, entry->GetFilePath());
EXPECT_TRUE(GetFileInfoAndCompare(kFilePath3, entry));
} }
TEST_F(GDataFileSystemTest, SearchDuplicateNames) { TEST_F(GDataFileSystemTest, SearchDuplicateNames) {
LoadRootFeedDocument("root_feed.json"); LoadRootFeedDocument("root_feed.json");
EXPECT_TRUE(FindEntry(FilePath(
FILE_PATH_LITERAL("gdata/Duplicate Name.txt")))); const FilePath kFilePath1 = FilePath(
EXPECT_TRUE(FindEntry(FilePath( FILE_PATH_LITERAL("gdata/Duplicate Name.txt"));
FILE_PATH_LITERAL("gdata/Duplicate Name (2).txt")))); GDataEntry* entry = FindEntry(kFilePath1);
ASSERT_TRUE(entry);
EXPECT_EQ(kFilePath1, entry->GetFilePath());
EXPECT_TRUE(GetFileInfoAndCompare(kFilePath1, entry));
const FilePath kFilePath2 = FilePath(
FILE_PATH_LITERAL("gdata/Duplicate Name (2).txt"));
entry = FindEntry(kFilePath2);
ASSERT_TRUE(entry);
EXPECT_EQ(kFilePath2, entry->GetFilePath());
EXPECT_TRUE(GetFileInfoAndCompare(kFilePath2, entry));
} }
TEST_F(GDataFileSystemTest, SearchExistingDirectory) { TEST_F(GDataFileSystemTest, SearchExistingDirectory) {
LoadRootFeedDocument("root_feed.json"); LoadRootFeedDocument("root_feed.json");
EXPECT_TRUE(FindEntry(FilePath(
FILE_PATH_LITERAL("gdata/Directory 1")))); const FilePath kFilePath = FilePath(
FILE_PATH_LITERAL("gdata/Directory 1"));
GDataEntry* entry = FindEntry(kFilePath);
ASSERT_TRUE(entry);
EXPECT_EQ(kFilePath, entry->GetFilePath());
} }
TEST_F(GDataFileSystemTest, SearchInSubdir) { TEST_F(GDataFileSystemTest, SearchInSubdir) {
LoadRootFeedDocument("root_feed.json"); LoadRootFeedDocument("root_feed.json");
EXPECT_TRUE(FindEntry(FilePath(
FILE_PATH_LITERAL("gdata/Directory 1/SubDirectory File 1.txt")))); const FilePath kFilePath = FilePath(
FILE_PATH_LITERAL("gdata/Directory 1/SubDirectory File 1.txt"));
GDataEntry* entry = FindEntry(kFilePath);
ASSERT_TRUE(entry);
EXPECT_EQ(kFilePath, entry->GetFilePath());
EXPECT_TRUE(GetFileInfoAndCompare(kFilePath, entry));
} }
// Check the reconstruction of the directory structure from only the root feed. // Check the reconstruction of the directory structure from only the root feed.
TEST_F(GDataFileSystemTest, SearchInSubSubdir) { TEST_F(GDataFileSystemTest, SearchInSubSubdir) {
LoadRootFeedDocument("root_feed.json"); LoadRootFeedDocument("root_feed.json");
EXPECT_TRUE(FindEntry(FilePath(
const FilePath kFilePath = FilePath(
FILE_PATH_LITERAL("gdata/Directory 1/Sub Directory Folder/" FILE_PATH_LITERAL("gdata/Directory 1/Sub Directory Folder/"
"Sub Sub Directory Folder")))); "Sub Sub Directory Folder"));
GDataEntry* entry = FindEntry(kFilePath);
ASSERT_TRUE(entry);
EXPECT_EQ(kFilePath, entry->GetFilePath());
} }
TEST_F(GDataFileSystemTest, FilePathTests) { TEST_F(GDataFileSystemTest, FilePathTests) {
......
...@@ -60,7 +60,10 @@ class MockGDataFileSystem : public GDataFileSystemInterface { ...@@ -60,7 +60,10 @@ class MockGDataFileSystem : public GDataFileSystemInterface {
MOCK_METHOD3(GetCacheState, void(const std::string& resource_id, MOCK_METHOD3(GetCacheState, void(const std::string& resource_id,
const std::string& md5, const std::string& md5,
const GetCacheStateCallback& callback)); const GetCacheStateCallback& callback));
MOCK_METHOD2(GetFileInfoByPath, bool(const FilePath& gdata_file_path, MOCK_METHOD2(GetFileInfoByPathAsync,
void(const FilePath& file_path,
const GetFileInfoCallback& callback));
MOCK_METHOD2(GetFileInfoByPath, bool(const FilePath& file_path,
GDataFileProperties* properties)); GDataFileProperties* properties));
MOCK_CONST_METHOD1(IsUnderGDataCacheDirectory, bool(const FilePath& path)); MOCK_CONST_METHOD1(IsUnderGDataCacheDirectory, bool(const FilePath& path));
MOCK_CONST_METHOD1(GetCacheDirectoryPath, FilePath( MOCK_CONST_METHOD1(GetCacheDirectoryPath, FilePath(
......
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