diff options
author | hshi@chromium.org <hshi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-06-08 19:49:52 +0000 |
---|---|---|
committer | hshi@chromium.org <hshi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-06-08 19:49:52 +0000 |
commit | b69d0a4aa6ebdc3eff2522f2a9f3cf23831ca7ff (patch) | |
tree | 4b6e02e1129f682972175a42e8b7a8ecd10afbb8 | |
parent | c82da8c4adce2fcf0fef48442f877f4d5917a6b1 (diff) | |
download | chromium_src-b69d0a4aa6ebdc3eff2522f2a9f3cf23831ca7ff.zip chromium_src-b69d0a4aa6ebdc3eff2522f2a9f3cf23831ca7ff.tar.gz chromium_src-b69d0a4aa6ebdc3eff2522f2a9f3cf23831ca7ff.tar.bz2 |
gdata: Get rid of GDataFileSystem::GetFileInfoByPath()
This is part 1 of converting public synchronous functions in GDataFileSystem to asynchronous.
Eliminate the helper class GDataFileProperties and the public synchronous function GetFileInfoByPath().
BUG=127048
TEST=unit_tests, browser_tests
Review URL: https://chromiumcodereview.appspot.com/10543037
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@141262 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/chromeos/extensions/file_handler_util.cc | 60 | ||||
-rw-r--r-- | chrome/browser/chromeos/extensions/file_handler_util.h | 17 | ||||
-rw-r--r-- | chrome/browser/chromeos/gdata/gdata_file_system.cc | 128 | ||||
-rw-r--r-- | chrome/browser/chromeos/gdata/gdata_file_system.h | 48 | ||||
-rw-r--r-- | chrome/browser/chromeos/gdata/gdata_file_system_proxy.cc | 35 | ||||
-rw-r--r-- | chrome/browser/chromeos/gdata/gdata_file_system_proxy.h | 9 | ||||
-rw-r--r-- | chrome/browser/chromeos/gdata/gdata_util.cc | 118 | ||||
-rw-r--r-- | chrome/browser/chromeos/gdata/gdata_util.h | 12 | ||||
-rw-r--r-- | chrome/browser/chromeos/gdata/mock_gdata_file_system.h | 2 |
9 files changed, 269 insertions, 160 deletions
diff --git a/chrome/browser/chromeos/extensions/file_handler_util.cc b/chrome/browser/chromeos/extensions/file_handler_util.cc index 08db70e..4bbdaa9 100644 --- a/chrome/browser/chromeos/extensions/file_handler_util.cc +++ b/chrome/browser/chromeos/extensions/file_handler_util.cc @@ -547,6 +547,14 @@ void FileTaskExecutor::ExecuteFailedOnUIThread() { Done(false); } +const Extension* FileTaskExecutor::GetExtension() { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + + ExtensionService* service = profile_->GetExtensionService(); + return service ? service->GetExtensionById(extension_id_, false) : + NULL; +} + void FileTaskExecutor::ExecuteFileActionsOnUIThread( const std::string& file_system_name, const GURL& file_system_root, @@ -554,20 +562,37 @@ void FileTaskExecutor::ExecuteFileActionsOnUIThread( int handler_pid) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - ExtensionService* service = profile_->GetExtensionService(); - if (!service) { + const Extension* extension = GetExtension(); + if (!extension) { Done(false); return; } - const Extension* extension = service->GetExtensionById(extension_id_, false); + InitHandlerHostFileAccessPermissions( + file_list, + extension, + action_id_, + base::Bind(&FileTaskExecutor::OnInitAccessForExecuteFileActionsOnUIThread, + this, + file_system_name, + file_system_root, + file_list, + handler_pid)); +} + +void FileTaskExecutor::OnInitAccessForExecuteFileActionsOnUIThread( + const std::string& file_system_name, + const GURL& file_system_root, + const FileDefinitionList& file_list, + int handler_pid) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + + const Extension* extension = GetExtension(); if (!extension) { Done(false); return; } - InitHandlerHostFileAccessPermissions(file_list, extension, action_id_); - if (handler_pid > 0) { SetupPermissionsAndDispatchEvent(file_system_name, file_system_root, file_list, handler_pid, NULL); @@ -649,9 +674,11 @@ void FileTaskExecutor::SetupPermissionsAndDispatchEvent( void FileTaskExecutor::InitHandlerHostFileAccessPermissions( const FileDefinitionList& file_list, const Extension* handler_extension, - const std::string& action_id) { + const std::string& action_id, + const base::Closure& callback) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + scoped_ptr<std::vector<FilePath> > gdata_paths(new std::vector<FilePath>); for (FileDefinitionList::const_iterator iter = file_list.begin(); iter != file_list.end(); ++iter) { @@ -660,15 +687,22 @@ void FileTaskExecutor::InitHandlerHostFileAccessPermissions( iter->absolute_path, GetAccessPermissionsForHandler(handler_extension, action_id))); - if (!gdata::util::IsUnderGDataMountPoint(iter->absolute_path)) - continue; + if (gdata::util::IsUnderGDataMountPoint(iter->absolute_path)) + gdata_paths->push_back(iter->virtual_path); + } - // If the file is on gdata mount point, we'll have to give handler host - // permissions for file's gdata cache paths. - // This has to be called on UI thread. - gdata::util::InsertGDataCachePathsPermissions(profile_, iter->virtual_path, - &handler_host_permissions_); + if (gdata_paths->empty()) { + // Invoke callback if none of the files are on gdata mount point. + callback.Run(); + return; } + + // For files on gdata mount point, we'll have to give handler host permissions + // for their cache paths. This has to be called on UI thread. + gdata::util::InsertGDataCachePathsPermissions(profile_, + gdata_paths.Pass(), + &handler_host_permissions_, + callback); } void FileTaskExecutor::SetupHandlerHostFileAccessPermissions(int handler_pid) { diff --git a/chrome/browser/chromeos/extensions/file_handler_util.h b/chrome/browser/chromeos/extensions/file_handler_util.h index 84b0e2f..144fa94 100644 --- a/chrome/browser/chromeos/extensions/file_handler_util.h +++ b/chrome/browser/chromeos/extensions/file_handler_util.h @@ -109,7 +109,7 @@ class FileTaskExecutor : public base::RefCountedThreadSafe<FileTaskExecutor> { void ExecuteFileActionsOnUIThread(const std::string& file_system_name, const GURL& file_system_root, const FileDefinitionList& file_list, - int handler_id); + int handler_pid); void SetupPermissionsAndDispatchEvent(const std::string& file_system_name, const GURL& file_system_root, const FileDefinitionList& file_list, @@ -121,11 +121,24 @@ class FileTaskExecutor : public base::RefCountedThreadSafe<FileTaskExecutor> { void InitHandlerHostFileAccessPermissions( const FileDefinitionList& file_list, const extensions::Extension* handler_extension, - const std::string& action_id); + const std::string& action_id, + const base::Closure& callback); + + // Invoked upon completion of InitHandlerHostFileAccessPermissions initiated + // by ExecuteFileActionsOnUIThread. + void OnInitAccessForExecuteFileActionsOnUIThread( + const std::string& file_system_name, + const GURL& file_system_root, + const FileDefinitionList& file_list, + int handler_pid); + // Registers file permissions from |handler_host_permissions_| with // ChildProcessSecurityPolicy for process with id |handler_pid|. void SetupHandlerHostFileAccessPermissions(int handler_pid); + // Helper function to get the extension pointer. + const extensions::Extension* GetExtension(); + Profile* profile_; const GURL source_url_; const std::string extension_id_; diff --git a/chrome/browser/chromeos/gdata/gdata_file_system.cc b/chrome/browser/chromeos/gdata/gdata_file_system.cc index bc9de4a..c73dd2e 100644 --- a/chrome/browser/chromeos/gdata/gdata_file_system.cc +++ b/chrome/browser/chromeos/gdata/gdata_file_system.cc @@ -837,14 +837,6 @@ CallbackType CreateRelayCallback(const CallbackType& callback) { } // namespace -// GDataFileProperties struct implementation. - -GDataFileProperties::GDataFileProperties() : is_hosted_document(false) { -} - -GDataFileProperties::~GDataFileProperties() { -} - // GDataFileSystem::GetDocumentsParams struct implementation. GDataFileSystem::GetDocumentsParams::GetDocumentsParams( @@ -1976,8 +1968,40 @@ void GDataFileSystem::GetFileByPathOnUIThread( const GetDownloadDataCallback& get_download_data_callback) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - GDataFileProperties file_properties; - if (!GetFileInfoByPath(file_path, &file_properties)) { + GetFileInfoByPathAsync( + file_path, + base::Bind(&GDataFileSystem::OnGetFileInfoCompleteForGetFileByPath, + ui_weak_ptr_, + file_path, + CreateRelayCallback(get_file_callback), + CreateRelayCallback(get_download_data_callback))); +} + +void GDataFileSystem::OnGetFileInfoCompleteForGetFileByPath( + const FilePath& file_path, + const GetFileCallback& get_file_callback, + const GetDownloadDataCallback& get_download_data_callback, + base::PlatformFileError error, + scoped_ptr<GDataFileProto> file_info) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + + DCHECK(!file_info->gdata_entry().resource_id().empty()); + GetResolvedFileByPath(file_path, + get_file_callback, + get_download_data_callback, + error, + file_info.get()); +} + +void GDataFileSystem::GetResolvedFileByPath( + const FilePath& file_path, + const GetFileCallback& get_file_callback, + const GetDownloadDataCallback& get_download_data_callback, + base::PlatformFileError error, + const GDataFileProto* file_proto) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + + if (error != base::PLATFORM_FILE_OK || !file_proto) { if (!get_file_callback.is_null()) { MessageLoop::current()->PostTask( FROM_HERE, @@ -1994,7 +2018,7 @@ void GDataFileSystem::GetFileByPathOnUIThread( // document instead of fetching the document content in one of the exported // formats. The JSON file contains the edit URL and resource ID of the // document. - if (file_properties.is_hosted_document) { + if (file_proto->is_hosted_document()) { base::PlatformFileError* error = new base::PlatformFileError(base::PLATFORM_FILE_OK); FilePath* temp_file_path = new FilePath; @@ -2005,8 +2029,8 @@ void GDataFileSystem::GetFileByPathOnUIThread( base::Bind(&CreateDocumentJsonFileOnBlockingPool, GetCacheDirectoryPath( GDataCache::CACHE_TYPE_TMP_DOCUMENTS), - file_properties.alternate_url, - file_properties.resource_id, + GURL(file_proto->alternate_url()), + file_proto->gdata_entry().resource_id(), error, temp_file_path, mime_type, @@ -2022,22 +2046,22 @@ void GDataFileSystem::GetFileByPathOnUIThread( // Returns absolute path of the file if it were cached or to be cached. FilePath local_tmp_path = cache_->GetCacheFilePath( - file_properties.resource_id, - file_properties.file_md5, + file_proto->gdata_entry().resource_id(), + file_proto->file_md5(), GDataCache::CACHE_TYPE_TMP, GDataCache::CACHED_FILE_FROM_SERVER); GetFileFromCacheByResourceIdAndMd5( - file_properties.resource_id, - file_properties.file_md5, + file_proto->gdata_entry().resource_id(), + file_proto->file_md5(), base::Bind( &GDataFileSystem::OnGetFileFromCache, ui_weak_ptr_, GetFileFromCacheParams(file_path, local_tmp_path, - file_properties.content_url, - file_properties.resource_id, - file_properties.file_md5, - file_properties.mime_type, + GURL(file_proto->gdata_entry().content_url()), + file_proto->gdata_entry().resource_id(), + file_proto->file_md5(), + file_proto->content_mime_type(), get_file_callback, get_download_data_callback))); } @@ -2483,28 +2507,6 @@ void GDataFileSystem::OnRequestDirectoryRefresh( DVLOG(1) << "Directory refreshed: " << directory_path.value(); } -bool GDataFileSystem::GetFileInfoByPath( - const FilePath& file_path, GDataFileProperties* properties) { - DCHECK(properties); - base::AutoLock lock(lock_); - GDataEntry* entry = GetGDataEntryByPath(file_path); - if (!entry) - return false; - - properties->file_info = entry->file_info(); - properties->resource_id = entry->resource_id(); - - GDataFile* regular_file = entry->AsGDataFile(); - if (regular_file) { - properties->file_md5 = regular_file->file_md5(); - properties->mime_type = regular_file->content_mime_type(); - properties->content_url = regular_file->content_url(); - properties->alternate_url = regular_file->alternate_url(); - properties->is_hosted_document = regular_file->is_hosted_document(); - } - return true; -} - GDataEntry* GDataFileSystem::GetGDataEntryByPath( const FilePath& file_path) { lock_.AssertAcquired(); @@ -5078,21 +5080,15 @@ void GDataFileSystem::OnGetFileInfoCompleteForOpenFile( } DCHECK(!file_info->gdata_entry().resource_id().empty()); - - // TODO(kinaba): once it is cleaned up (crbug/127048), remove the indirection. - // Do not call GetFileByPathOnUIThread() directly for avoiding deadlock. - // The current method is called as a callback from GetFileInfoByPathAsync(), - // which is under the lock taken. - base::MessageLoopProxy::current()->PostTask( - FROM_HERE, - base::Bind(&GDataFileSystem::GetFileByPathOnUIThread, + GetResolvedFileByPath( + file_path, + base::Bind(&GDataFileSystem::OnGetFileCompleteForOpenFile, ui_weak_ptr_, - file_path, - base::Bind(&GDataFileSystem::OnGetFileCompleteForOpenFile, - ui_weak_ptr_, - callback, - base::Passed(&file_info)), - GetDownloadDataCallback())); + callback, + base::Passed(&file_info)), + GetDownloadDataCallback(), + error, + file_info.get()); } void GDataFileSystem::OnGetFileCompleteForOpenFile( @@ -5181,21 +5177,13 @@ void GDataFileSystem::OnGetFileInfoCompleteForCloseFile( // if the file has not been modified. Come up with a way to detect the // intactness effectively, or provide a method for user to declare it when // calling CloseFile(). - - // TODO(kinaba): once it is cleaned up (crbug/127048), remove the indirection. - // Do not call CommitDirtyInCache() directly for avoiding deadlock. - // The current method is called as a callback from GetFileInfoByPathAsync(), - // which is under the lock taken. - base::MessageLoopProxy::current()->PostTask( - FROM_HERE, + CommitDirtyInCache( + file_info->gdata_entry().resource_id(), + file_info->file_md5(), base::Bind( - &GDataFileSystem::CommitDirtyInCache, + &GDataFileSystem::OnCommitDirtyInCacheCompleteForCloseFile, ui_weak_ptr_, - file_info->gdata_entry().resource_id(), - file_info->file_md5(), - base::Bind(&GDataFileSystem::OnCommitDirtyInCacheCompleteForCloseFile, - ui_weak_ptr_, - callback))); + callback)); } void GDataFileSystem::OnCommitDirtyInCacheCompleteForCloseFile( diff --git a/chrome/browser/chromeos/gdata/gdata_file_system.h b/chrome/browser/chromeos/gdata/gdata_file_system.h index f0a6f89..b8daad4 100644 --- a/chrome/browser/chromeos/gdata/gdata_file_system.h +++ b/chrome/browser/chromeos/gdata/gdata_file_system.h @@ -114,21 +114,6 @@ typedef base::Callback<void(const std::string& resource_id)> typedef base::Callback<void(base::PlatformFileError error, int cache_state)> GetCacheStateCallback; -// Helper structure used for extracting key properties from GDataFile object. -// TODO(satorux): Remove this as part of crosbug.com/30066 -struct GDataFileProperties { - GDataFileProperties(); - ~GDataFileProperties(); - - base::PlatformFileInfo file_info; - std::string resource_id; - std::string file_md5; - std::string mime_type; - GURL content_url; - GURL alternate_url; - bool is_hosted_document; -}; - // GData file system abstraction layer. // The interface is defined to make GDataFileSystem mockable. class GDataFileSystemInterface { @@ -392,13 +377,6 @@ class GDataFileSystemInterface { virtual void SearchAsync(const std::string& search_query, const ReadDirectoryCallback& 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; - // Returns true if the given path is under gdata cache directory, i.e. // <user_profile_dir>/GCache/v1 virtual bool IsUnderGDataCacheDirectory(const FilePath& path) const = 0; @@ -508,8 +486,6 @@ class GDataFileSystem : public GDataFileSystemInterface, const ReadDirectoryCallback& callback) OVERRIDE; virtual void RequestDirectoryRefresh( const FilePath& file_path) OVERRIDE; - virtual bool GetFileInfoByPath(const FilePath& file_path, - GDataFileProperties* properties) OVERRIDE; virtual bool IsUnderGDataCacheDirectory(const FilePath& path) const OVERRIDE; virtual FilePath GetCacheDirectoryPath( GDataCache::CacheSubDirectoryType sub_dir_type) const OVERRIDE; @@ -692,16 +668,24 @@ class GDataFileSystem : public GDataFileSystemInterface, const FilePath& remote_dest_file_path, const FileOperationCallback& callback); + // Invoked upon completion of GetFileInfoByPathAsync initiated by + // GetFileByPath. It then continues to invoke GetResolvedFileByPath. + void OnGetFileInfoCompleteForGetFileByPath( + const FilePath& file_path, + const GetFileCallback& get_file_callback, + const GetDownloadDataCallback& get_download_data_callback, + base::PlatformFileError error, + scoped_ptr<GDataFileProto> file_info); // Invoked upon completion of GetFileInfoByPathAsync initiated by OpenFile. - // It then continues to invoke GetFileByPath and processed to + // It then continues to invoke GetResolvedFileByPath and proceeds to // OnGetFileCompleteForOpenFile. void OnGetFileInfoCompleteForOpenFile(const FilePath& file_path, const OpenFileCallback& callback, base::PlatformFileError error, scoped_ptr<GDataFileProto> file_info); // Invoked upon completion of GetFileInfoByPathAsync initiated by CloseFile. - // It then continues to invoke GetFileByPath and processed to - // OnGetFileCompleteForCloseFile. + // It then continues to invoke CommitDirtyInCache and proceeds to + // OnCommitDirtyInCacheCompleteForCloseFile. void OnGetFileInfoCompleteForCloseFile(const FilePath& file_path, const CloseFileCallback& callback, base::PlatformFileError error, @@ -1419,6 +1403,16 @@ class GDataFileSystem : public GDataFileSystemInterface, void FindEntryByPathAsyncOnUIThread(const FilePath& search_file_path, const FindEntryCallback& callback); + // Gets |file_path| from the file system after the file info is already + // resolved with GetFileInfoByPathAsync(). This function is called by + // OnGetFileInfoCompleteForGetFileByPath and OnGetFileInfoCompleteForOpenFile. + void GetResolvedFileByPath( + const FilePath& file_path, + const GetFileCallback& get_file_callback, + const GetDownloadDataCallback& get_download_data_callback, + base::PlatformFileError error, + const GDataFileProto* file_proto); + // The following functions are used to forward calls to asynchronous public // member functions to UI thread. void SearchAsyncOnUIThread(const std::string& search_query, diff --git a/chrome/browser/chromeos/gdata/gdata_file_system_proxy.cc b/chrome/browser/chromeos/gdata/gdata_file_system_proxy.cc index decfef4..ec35486 100644 --- a/chrome/browser/chromeos/gdata/gdata_file_system_proxy.cc +++ b/chrome/browser/chromeos/gdata/gdata_file_system_proxy.cc @@ -215,10 +215,7 @@ void GDataFileSystemProxy::CreateSnapshotFile( const GURL& file_url, const FileSystemOperationInterface::SnapshotFileCallback& callback) { FilePath file_path; - base::PlatformFileInfo file_info; - GDataFileProperties file_properties; - if (!ValidateUrl(file_url, &file_path) || - !file_system_->GetFileInfoByPath(file_path, &file_properties)) { + if (!ValidateUrl(file_url, &file_path)) { MessageLoopProxy::current()->PostTask(FROM_HERE, base::Bind(callback, base::PLATFORM_FILE_ERROR_NOT_FOUND, @@ -228,10 +225,36 @@ void GDataFileSystemProxy::CreateSnapshotFile( return; } - file_system_->GetFileByPath(file_path, + file_system_->GetEntryInfoByPathAsync( + file_path, + base::Bind(&GDataFileSystemProxy::OnGetEntryInfoByPathAsync, + this, callback)); +} + +void GDataFileSystemProxy::OnGetEntryInfoByPathAsync( + const FileSystemOperationInterface::SnapshotFileCallback& callback, + base::PlatformFileError error, + const FilePath& entry_path, + scoped_ptr<GDataEntryProto> entry_proto) { + if (error != base::PLATFORM_FILE_OK || !entry_proto.get()) { + MessageLoopProxy::current()->PostTask(FROM_HERE, + base::Bind(callback, + base::PLATFORM_FILE_ERROR_NOT_FOUND, + base::PlatformFileInfo(), + FilePath(), + scoped_refptr<ShareableFileReference>(NULL))); + return; + } + + base::PlatformFileInfo file_info; + GDataEntry::ConvertProtoToPlatformFileInfo( + entry_proto->file_info(), + &file_info); + + file_system_->GetFileByPath(entry_path, base::Bind(&CallSnapshotFileCallback, callback, - file_properties.file_info), + file_info), GetDownloadDataCallback()); } diff --git a/chrome/browser/chromeos/gdata/gdata_file_system_proxy.h b/chrome/browser/chromeos/gdata/gdata_file_system_proxy.h index d510102..4d5595f 100644 --- a/chrome/browser/chromeos/gdata/gdata_file_system_proxy.h +++ b/chrome/browser/chromeos/gdata/gdata_file_system_proxy.h @@ -69,6 +69,15 @@ class GDataFileSystemProxy : public fileapi::RemoteFileSystemProxyInterface { const FilePath& entry_path, scoped_ptr<gdata::GDataEntryProto> entry_proto); + // Helper callback for relaying reply for GetEntryInfoByPathAsync() to the + // calling thread. + void OnGetEntryInfoByPathAsync( + const fileapi::FileSystemOperationInterface::SnapshotFileCallback& + callback, + base::PlatformFileError error, + const FilePath& entry_path, + scoped_ptr<GDataEntryProto> entry_proto); + // Helper callback for relaying reply for ReadDirectory() to the calling // thread. void OnReadDirectory( diff --git a/chrome/browser/chromeos/gdata/gdata_util.cc b/chrome/browser/chromeos/gdata/gdata_util.cc index a4635ac..722441a 100644 --- a/chrome/browser/chromeos/gdata/gdata_util.cc +++ b/chrome/browser/chromeos/gdata/gdata_util.cc @@ -21,6 +21,7 @@ #include "chrome/common/chrome_version_info.h" #include "chrome/common/pref_names.h" #include "chrome/common/url_constants.h" +#include "chrome/browser/chromeos/gdata/gdata.pb.h" #include "chrome/browser/chromeos/gdata/gdata_file_system.h" #include "chrome/browser/chromeos/gdata/gdata_system_service.h" #include "chrome/browser/chromeos/login/user.h" @@ -93,6 +94,58 @@ void OpenEditURLUIThread(Profile* profile, GURL* edit_url) { } } +// Invoked upon completion of GetFileInfoByPathAsync initiated by +// InsertGDataCachePathPermissions. +void OnGetFileInfoForInsertGDataCachePathsPermissions( + Profile* profile, + std::vector<std::pair<FilePath, int> >* cache_paths, + const base::Closure& callback, + base::PlatformFileError error, + scoped_ptr<GDataFileProto> file_info) { + DCHECK(profile); + DCHECK(cache_paths); + DCHECK(!callback.is_null()); + + GDataFileSystem* file_system = GetGDataFileSystem(profile); + if (!file_system || error != base::PLATFORM_FILE_OK) { + callback.Run(); + return; + } + + DCHECK(file_info.get()); + std::string resource_id = file_info->gdata_entry().resource_id(); + std::string file_md5 = file_info->file_md5(); + + // We check permissions for raw cache file paths only for read-only + // operations (when fileEntry.file() is called), so read only permissions + // should be sufficient for all cache paths. For the rest of supported + // operations the file access check is done for drive/ paths. + cache_paths->push_back(std::make_pair( + file_system->GetCacheFilePath(resource_id, file_md5, + GDataCache::CACHE_TYPE_PERSISTENT, + GDataCache::CACHED_FILE_FROM_SERVER), + kReadOnlyFilePermissions)); + // TODO(tbarzic): When we start supporting openFile operation, we may have to + // change permission for localy modified files to match handler's permissions. + cache_paths->push_back(std::make_pair( + file_system->GetCacheFilePath(resource_id, file_md5, + GDataCache::CACHE_TYPE_PERSISTENT, + GDataCache::CACHED_FILE_LOCALLY_MODIFIED), + kReadOnlyFilePermissions)); + cache_paths->push_back(std::make_pair( + file_system->GetCacheFilePath(resource_id, file_md5, + GDataCache::CACHE_TYPE_PERSISTENT, + GDataCache::CACHED_FILE_MOUNTED), + kReadOnlyFilePermissions)); + cache_paths->push_back(std::make_pair( + file_system->GetCacheFilePath(resource_id, file_md5, + GDataCache::CACHE_TYPE_TMP, + GDataCache::CACHED_FILE_FROM_SERVER), + kReadOnlyFilePermissions)); + + callback.Run(); +} + } // namespace const FilePath& GetGDataMountPointPath() { @@ -231,47 +284,40 @@ FilePath ExtractGDataPath(const FilePath& path) { void InsertGDataCachePathsPermissions( Profile* profile, - const FilePath& gdata_path, - std::vector<std::pair<FilePath, int> >* cache_paths ) { + scoped_ptr<std::vector<FilePath> > gdata_paths, + std::vector<std::pair<FilePath, int> >* cache_paths, + const base::Closure& callback) { + DCHECK(profile); + DCHECK(gdata_paths.get()); DCHECK(cache_paths); + DCHECK(!callback.is_null()); GDataFileSystem* file_system = GetGDataFileSystem(profile); - if (!file_system) + if (!file_system || gdata_paths->empty()) { + callback.Run(); return; + } - GDataFileProperties file_properties; - if (!file_system->GetFileInfoByPath(gdata_path, &file_properties)) - return; - - std::string resource_id = file_properties.resource_id; - std::string file_md5 = file_properties.file_md5; - - // We check permissions for raw cache file paths only for read-only - // operations (when fileEntry.file() is called), so read only permissions - // should be sufficient for all cache paths. For the rest of supported - // operations the file access check is done for drive/ paths. - cache_paths->push_back(std::make_pair( - file_system->GetCacheFilePath(resource_id, file_md5, - GDataCache::CACHE_TYPE_PERSISTENT, - GDataCache::CACHED_FILE_FROM_SERVER), - kReadOnlyFilePermissions)); - // TODO(tbarzic): When we start supporting openFile operation, we may have to - // change permission for localy modified files to match handler's permissions. - cache_paths->push_back(std::make_pair( - file_system->GetCacheFilePath(resource_id, file_md5, - GDataCache::CACHE_TYPE_PERSISTENT, - GDataCache::CACHED_FILE_LOCALLY_MODIFIED), - kReadOnlyFilePermissions)); - cache_paths->push_back(std::make_pair( - file_system->GetCacheFilePath(resource_id, file_md5, - GDataCache::CACHE_TYPE_PERSISTENT, - GDataCache::CACHED_FILE_MOUNTED), - kReadOnlyFilePermissions)); - cache_paths->push_back(std::make_pair( - file_system->GetCacheFilePath(resource_id, file_md5, - GDataCache::CACHE_TYPE_TMP, - GDataCache::CACHED_FILE_FROM_SERVER), - kReadOnlyFilePermissions)); + // Remove one file path entry from the back of the input vector |gdata_paths|. + FilePath gdata_path = gdata_paths->back(); + gdata_paths->pop_back(); + + // Call GetFileInfoByPathAsync() to get file info for |gdata_path| then insert + // all possible cache paths to the output vector |cache_paths|. + // Note that we can only process one file path at a time. Upon completion + // of OnGetFileInfoForInsertGDataCachePathsPermissions(), we recursively call + // InsertGDataCachePathsPermissions() to process the next file path from the + // back of the input vector |gdata_paths| until it is empty. + file_system->GetFileInfoByPathAsync( + gdata_path, + base::Bind(&OnGetFileInfoForInsertGDataCachePathsPermissions, + profile, + cache_paths, + base::Bind(&InsertGDataCachePathsPermissions, + profile, + base::Passed(&gdata_paths), + cache_paths, + callback))); } bool IsGDataAvailable(Profile* profile) { diff --git a/chrome/browser/chromeos/gdata/gdata_util.h b/chrome/browser/chromeos/gdata/gdata_util.h index 87a6c25..7da949e 100644 --- a/chrome/browser/chromeos/gdata/gdata_util.h +++ b/chrome/browser/chromeos/gdata/gdata_util.h @@ -9,6 +9,8 @@ #include <string> #include <vector> +#include "base/bind.h" +#include "base/memory/scoped_ptr.h" #include "googleurl/src/gurl.h" class FilePath; @@ -77,12 +79,14 @@ bool ParseSearchFileName(const std::string& search_file_name, // Examples: ExtractGDatPath("/special/drive/foo.txt") => "drive/foo.txt" FilePath ExtractGDataPath(const FilePath& path); -// Returns vector of all possible cache paths for a given path on gdata mount -// point. +// Inserts all possible cache paths for a given vector of paths on gdata mount +// point into the output vector |cache_paths|, and then invokes callback. +// Caller must ensure that |cache_paths| lives until the callback is invoked. void InsertGDataCachePathsPermissions( Profile* profile_, - const FilePath& gdata_path, - std::vector<std::pair<FilePath, int> >* cache_paths); + scoped_ptr<std::vector<FilePath> > gdata_paths, + std::vector<std::pair<FilePath, int> >* cache_paths, + const base::Closure& callback); // Returns true if gdata is currently active with the specified profile. bool IsGDataAvailable(Profile* profile); diff --git a/chrome/browser/chromeos/gdata/mock_gdata_file_system.h b/chrome/browser/chromeos/gdata/mock_gdata_file_system.h index f0a2a92..20acce3 100644 --- a/chrome/browser/chromeos/gdata/mock_gdata_file_system.h +++ b/chrome/browser/chromeos/gdata/mock_gdata_file_system.h @@ -80,8 +80,6 @@ class MockGDataFileSystem : public GDataFileSystemInterface { const ReadDirectoryCallback& callback)); MOCK_METHOD1(RequestDirectoryRefresh, void(const FilePath& file_path)); - MOCK_METHOD2(GetFileInfoByPath, bool(const FilePath& file_path, - GDataFileProperties* properties)); MOCK_CONST_METHOD1(IsUnderGDataCacheDirectory, bool(const FilePath& path)); MOCK_CONST_METHOD1(GetCacheDirectoryPath, FilePath( GDataCache::CacheSubDirectoryType)); |