Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/chromeos/gdata/gdata_file_system.h" | 5 #include "chrome/browser/chromeos/gdata/gdata_file_system.h" |
| 6 | 6 |
| 7 #include <errno.h> | 7 #include <errno.h> |
| 8 #include <sys/stat.h> | 8 #include <sys/stat.h> |
| 9 | 9 |
| 10 #include <set> | 10 #include <set> |
| (...skipping 875 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 886 // Returns callback which runs the given |callback| on the current thread. | 886 // Returns callback which runs the given |callback| on the current thread. |
| 887 template<typename CallbackType> | 887 template<typename CallbackType> |
| 888 CallbackType CreateRelayCallback(const CallbackType& callback) { | 888 CallbackType CreateRelayCallback(const CallbackType& callback) { |
| 889 return base::Bind(&RelayCallback<CallbackType>::Run, | 889 return base::Bind(&RelayCallback<CallbackType>::Run, |
| 890 base::MessageLoopProxy::current(), | 890 base::MessageLoopProxy::current(), |
| 891 callback); | 891 callback); |
| 892 } | 892 } |
| 893 | 893 |
| 894 } // namespace | 894 } // namespace |
| 895 | 895 |
| 896 // GDataFileProperties struct implementation. | |
| 897 | |
| 898 GDataFileProperties::GDataFileProperties() : is_hosted_document(false) { | |
| 899 } | |
| 900 | |
| 901 GDataFileProperties::~GDataFileProperties() { | |
| 902 } | |
| 903 | |
| 904 // GDataFileSystem::GetDocumentsParams struct implementation. | 896 // GDataFileSystem::GetDocumentsParams struct implementation. |
| 905 | 897 |
| 906 GDataFileSystem::GetDocumentsParams::GetDocumentsParams( | 898 GDataFileSystem::GetDocumentsParams::GetDocumentsParams( |
| 907 int start_changestamp, | 899 int start_changestamp, |
| 908 int root_feed_changestamp, | 900 int root_feed_changestamp, |
| 909 std::vector<DocumentFeed*>* feed_list, | 901 std::vector<DocumentFeed*>* feed_list, |
| 910 bool should_fetch_multiple_feeds, | 902 bool should_fetch_multiple_feeds, |
| 911 const FilePath& search_file_path, | 903 const FilePath& search_file_path, |
| 912 const std::string& search_query, | 904 const std::string& search_query, |
| 913 const std::string& directory_resource_id, | 905 const std::string& directory_resource_id, |
| (...skipping 1114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2028 CreateRelayCallback(get_file_callback), | 2020 CreateRelayCallback(get_file_callback), |
| 2029 CreateRelayCallback(get_download_data_callback))); | 2021 CreateRelayCallback(get_download_data_callback))); |
| 2030 } | 2022 } |
| 2031 | 2023 |
| 2032 void GDataFileSystem::GetFileByPathOnUIThread( | 2024 void GDataFileSystem::GetFileByPathOnUIThread( |
| 2033 const FilePath& file_path, | 2025 const FilePath& file_path, |
| 2034 const GetFileCallback& get_file_callback, | 2026 const GetFileCallback& get_file_callback, |
| 2035 const GetDownloadDataCallback& get_download_data_callback) { | 2027 const GetDownloadDataCallback& get_download_data_callback) { |
| 2036 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 2028 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 2037 | 2029 |
| 2038 GDataFileProperties file_properties; | 2030 GetFileInfoByPathAsync( |
| 2039 if (!GetFileInfoByPath(file_path, &file_properties)) { | 2031 file_path, |
| 2032 base::Bind(&GDataFileSystem::OnGetFileInfoCompleteForGetFileByPath, | |
| 2033 ui_weak_ptr_, | |
| 2034 file_path, | |
| 2035 CreateRelayCallback(get_file_callback), | |
| 2036 CreateRelayCallback(get_download_data_callback))); | |
| 2037 } | |
| 2038 | |
| 2039 void GDataFileSystem::OnGetFileInfoCompleteForGetFileByPath( | |
| 2040 const FilePath& file_path, | |
| 2041 const GetFileCallback& get_file_callback, | |
| 2042 const GetDownloadDataCallback& get_download_data_callback, | |
| 2043 base::PlatformFileError error, | |
| 2044 scoped_ptr<GDataFileProto> file_info) { | |
| 2045 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 2046 | |
| 2047 DCHECK(!file_info->gdata_entry().resource_id().empty()); | |
| 2048 GetResolvedFileByPath(file_path, | |
| 2049 get_file_callback, | |
|
tbarzic
2012/06/08 17:59:13
indent
hshi1
2012/06/08 18:21:41
Done.
| |
| 2050 get_download_data_callback, | |
| 2051 error, | |
| 2052 file_info.get()); | |
| 2053 } | |
| 2054 | |
| 2055 void GDataFileSystem::GetResolvedFileByPath( | |
| 2056 const FilePath& file_path, | |
| 2057 const GetFileCallback& get_file_callback, | |
| 2058 const GetDownloadDataCallback& get_download_data_callback, | |
| 2059 base::PlatformFileError error, | |
| 2060 const GDataFileProto* file_proto) { | |
| 2061 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 2062 | |
| 2063 if (error != base::PLATFORM_FILE_OK || !file_proto) { | |
| 2040 if (!get_file_callback.is_null()) { | 2064 if (!get_file_callback.is_null()) { |
| 2041 MessageLoop::current()->PostTask( | 2065 MessageLoop::current()->PostTask( |
| 2042 FROM_HERE, | 2066 FROM_HERE, |
| 2043 base::Bind(get_file_callback, | 2067 base::Bind(get_file_callback, |
| 2044 base::PLATFORM_FILE_ERROR_NOT_FOUND, | 2068 base::PLATFORM_FILE_ERROR_NOT_FOUND, |
| 2045 FilePath(), | 2069 FilePath(), |
| 2046 std::string(), | 2070 std::string(), |
| 2047 REGULAR_FILE)); | 2071 REGULAR_FILE)); |
| 2048 } | 2072 } |
| 2049 return; | 2073 return; |
| 2050 } | 2074 } |
| 2051 | 2075 |
| 2052 // For a hosted document, we create a special JSON file to represent the | 2076 // For a hosted document, we create a special JSON file to represent the |
| 2053 // document instead of fetching the document content in one of the exported | 2077 // document instead of fetching the document content in one of the exported |
| 2054 // formats. The JSON file contains the edit URL and resource ID of the | 2078 // formats. The JSON file contains the edit URL and resource ID of the |
| 2055 // document. | 2079 // document. |
| 2056 if (file_properties.is_hosted_document) { | 2080 if (file_proto->is_hosted_document()) { |
| 2057 base::PlatformFileError* error = | 2081 base::PlatformFileError* error = |
| 2058 new base::PlatformFileError(base::PLATFORM_FILE_OK); | 2082 new base::PlatformFileError(base::PLATFORM_FILE_OK); |
| 2059 FilePath* temp_file_path = new FilePath; | 2083 FilePath* temp_file_path = new FilePath; |
| 2060 std::string* mime_type = new std::string; | 2084 std::string* mime_type = new std::string; |
| 2061 GDataFileType* file_type = new GDataFileType(REGULAR_FILE); | 2085 GDataFileType* file_type = new GDataFileType(REGULAR_FILE); |
| 2062 PostBlockingPoolSequencedTaskAndReply( | 2086 PostBlockingPoolSequencedTaskAndReply( |
| 2063 FROM_HERE, | 2087 FROM_HERE, |
| 2064 base::Bind(&CreateDocumentJsonFileOnIOThreadPool, | 2088 base::Bind(&CreateDocumentJsonFileOnIOThreadPool, |
| 2065 GetCacheDirectoryPath( | 2089 GetCacheDirectoryPath( |
| 2066 GDataCache::CACHE_TYPE_TMP_DOCUMENTS), | 2090 GDataCache::CACHE_TYPE_TMP_DOCUMENTS), |
| 2067 file_properties.alternate_url, | 2091 GURL(file_proto->alternate_url()), |
| 2068 file_properties.resource_id, | 2092 file_proto->gdata_entry().resource_id(), |
| 2069 error, | 2093 error, |
| 2070 temp_file_path, | 2094 temp_file_path, |
| 2071 mime_type, | 2095 mime_type, |
| 2072 file_type), | 2096 file_type), |
| 2073 base::Bind(&RunGetFileCallbackHelper, | 2097 base::Bind(&RunGetFileCallbackHelper, |
| 2074 get_file_callback, | 2098 get_file_callback, |
| 2075 base::Owned(error), | 2099 base::Owned(error), |
| 2076 base::Owned(temp_file_path), | 2100 base::Owned(temp_file_path), |
| 2077 base::Owned(mime_type), | 2101 base::Owned(mime_type), |
| 2078 base::Owned(file_type))); | 2102 base::Owned(file_type))); |
| 2079 return; | 2103 return; |
| 2080 } | 2104 } |
| 2081 | 2105 |
| 2082 // Returns absolute path of the file if it were cached or to be cached. | 2106 // Returns absolute path of the file if it were cached or to be cached. |
| 2083 FilePath local_tmp_path = GetCacheFilePath(file_properties.resource_id, | 2107 FilePath local_tmp_path = GetCacheFilePath( |
| 2084 file_properties.file_md5, | 2108 file_proto->gdata_entry().resource_id(), |
| 2085 GDataCache::CACHE_TYPE_TMP, | 2109 file_proto->file_md5(), |
| 2086 CACHED_FILE_FROM_SERVER); | 2110 GDataCache::CACHE_TYPE_TMP, |
| 2111 CACHED_FILE_FROM_SERVER); | |
| 2087 GetFileFromCacheByResourceIdAndMd5( | 2112 GetFileFromCacheByResourceIdAndMd5( |
| 2088 file_properties.resource_id, | 2113 file_proto->gdata_entry().resource_id(), |
| 2089 file_properties.file_md5, | 2114 file_proto->file_md5(), |
| 2090 base::Bind( | 2115 base::Bind( |
| 2091 &GDataFileSystem::OnGetFileFromCache, | 2116 &GDataFileSystem::OnGetFileFromCache, |
| 2092 ui_weak_ptr_, | 2117 ui_weak_ptr_, |
| 2093 GetFileFromCacheParams(file_path, | 2118 GetFileFromCacheParams(file_path, |
| 2094 local_tmp_path, | 2119 local_tmp_path, |
| 2095 file_properties.content_url, | 2120 GURL(file_proto->gdata_entry().content_url()), |
| 2096 file_properties.resource_id, | 2121 file_proto->gdata_entry().resource_id(), |
| 2097 file_properties.file_md5, | 2122 file_proto->file_md5(), |
| 2098 file_properties.mime_type, | 2123 file_proto->content_mime_type(), |
| 2099 get_file_callback, | 2124 get_file_callback, |
| 2100 get_download_data_callback))); | 2125 get_download_data_callback))); |
| 2101 } | 2126 } |
| 2102 | 2127 |
| 2103 void GDataFileSystem::GetFileByResourceId( | 2128 void GDataFileSystem::GetFileByResourceId( |
| 2104 const std::string& resource_id, | 2129 const std::string& resource_id, |
| 2105 const GetFileCallback& get_file_callback, | 2130 const GetFileCallback& get_file_callback, |
| 2106 const GetDownloadDataCallback& get_download_data_callback) { | 2131 const GetDownloadDataCallback& get_download_data_callback) { |
| 2107 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) || | 2132 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) || |
| 2108 BrowserThread::CurrentlyOn(BrowserThread::IO)); | 2133 BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| (...skipping 438 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2547 directory->AddEntry(entry.release()); | 2572 directory->AddEntry(entry.release()); |
| 2548 } | 2573 } |
| 2549 | 2574 |
| 2550 // Note that there may be no change in the directory, but it's expensive to | 2575 // Note that there may be no change in the directory, but it's expensive to |
| 2551 // check if the new metadata matches the existing one, so we just always | 2576 // check if the new metadata matches the existing one, so we just always |
| 2552 // notify that the directory is changed. | 2577 // notify that the directory is changed. |
| 2553 NotifyDirectoryChanged(directory_path); | 2578 NotifyDirectoryChanged(directory_path); |
| 2554 DVLOG(1) << "Directory refreshed: " << directory_path.value(); | 2579 DVLOG(1) << "Directory refreshed: " << directory_path.value(); |
| 2555 } | 2580 } |
| 2556 | 2581 |
| 2557 bool GDataFileSystem::GetFileInfoByPath( | |
| 2558 const FilePath& file_path, GDataFileProperties* properties) { | |
| 2559 DCHECK(properties); | |
| 2560 base::AutoLock lock(lock_); | |
| 2561 GDataEntry* entry = GetGDataEntryByPath(file_path); | |
| 2562 if (!entry) | |
| 2563 return false; | |
| 2564 | |
| 2565 properties->file_info = entry->file_info(); | |
| 2566 properties->resource_id = entry->resource_id(); | |
| 2567 | |
| 2568 GDataFile* regular_file = entry->AsGDataFile(); | |
| 2569 if (regular_file) { | |
| 2570 properties->file_md5 = regular_file->file_md5(); | |
| 2571 properties->mime_type = regular_file->content_mime_type(); | |
| 2572 properties->content_url = regular_file->content_url(); | |
| 2573 properties->alternate_url = regular_file->alternate_url(); | |
| 2574 properties->is_hosted_document = regular_file->is_hosted_document(); | |
| 2575 } | |
| 2576 return true; | |
| 2577 } | |
| 2578 | |
| 2579 GDataEntry* GDataFileSystem::GetGDataEntryByPath( | 2582 GDataEntry* GDataFileSystem::GetGDataEntryByPath( |
| 2580 const FilePath& file_path) { | 2583 const FilePath& file_path) { |
| 2581 lock_.AssertAcquired(); | 2584 lock_.AssertAcquired(); |
| 2582 // Find directory element within the cached file system snapshot. | 2585 // Find directory element within the cached file system snapshot. |
| 2583 GDataEntry* entry = NULL; | 2586 GDataEntry* entry = NULL; |
| 2584 root_->FindEntryByPath(file_path, base::Bind(&ReadOnlyFindEntryCallback, | 2587 root_->FindEntryByPath(file_path, base::Bind(&ReadOnlyFindEntryCallback, |
| 2585 &entry)); | 2588 &entry)); |
| 2586 return entry; | 2589 return entry; |
| 2587 } | 2590 } |
| 2588 | 2591 |
| (...skipping 2551 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5140 } | 5143 } |
| 5141 } | 5144 } |
| 5142 | 5145 |
| 5143 if (error != base::PLATFORM_FILE_OK) { | 5146 if (error != base::PLATFORM_FILE_OK) { |
| 5144 if (!callback.is_null()) | 5147 if (!callback.is_null()) |
| 5145 callback.Run(error, FilePath()); | 5148 callback.Run(error, FilePath()); |
| 5146 return; | 5149 return; |
| 5147 } | 5150 } |
| 5148 | 5151 |
| 5149 DCHECK(!file_info->gdata_entry().resource_id().empty()); | 5152 DCHECK(!file_info->gdata_entry().resource_id().empty()); |
| 5150 | 5153 GetResolvedFileByPath( |
|
tbarzic
2012/06/08 17:59:13
I guess we are safe against deadlock now (kinaba's
hshi1
2012/06/08 18:21:41
Yes because this is called from the GetFileInfoByP
| |
| 5151 // TODO(kinaba): once it is cleaned up (crbug/127048), remove the indirection. | 5154 file_path, |
| 5152 // Do not call GetFileByPathOnUIThread() directly for avoiding deadlock. | 5155 base::Bind(&GDataFileSystem::OnGetFileCompleteForOpenFile, |
| 5153 // The current method is called as a callback from GetFileInfoByPathAsync(), | |
| 5154 // which is under the lock taken. | |
| 5155 base::MessageLoopProxy::current()->PostTask( | |
| 5156 FROM_HERE, | |
| 5157 base::Bind(&GDataFileSystem::GetFileByPathOnUIThread, | |
| 5158 ui_weak_ptr_, | 5156 ui_weak_ptr_, |
| 5159 file_path, | 5157 callback, |
| 5160 base::Bind(&GDataFileSystem::OnGetFileCompleteForOpenFile, | 5158 base::Passed(&file_info)), |
| 5161 ui_weak_ptr_, | 5159 GetDownloadDataCallback(), |
| 5162 callback, | 5160 error, |
| 5163 base::Passed(&file_info)), | 5161 file_info.get()); |
| 5164 GetDownloadDataCallback())); | |
| 5165 } | 5162 } |
| 5166 | 5163 |
| 5167 void GDataFileSystem::OnGetFileCompleteForOpenFile( | 5164 void GDataFileSystem::OnGetFileCompleteForOpenFile( |
| 5168 const OpenFileCallback& callback, | 5165 const OpenFileCallback& callback, |
| 5169 scoped_ptr<GDataFileProto> file_info, | 5166 scoped_ptr<GDataFileProto> file_info, |
| 5170 base::PlatformFileError error, | 5167 base::PlatformFileError error, |
| 5171 const FilePath& file_path, | 5168 const FilePath& file_path, |
| 5172 const std::string& mime_type, | 5169 const std::string& mime_type, |
| 5173 GDataFileType file_type) { | 5170 GDataFileType file_type) { |
| 5174 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 5171 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5243 callback.Run(error); | 5240 callback.Run(error); |
| 5244 return; | 5241 return; |
| 5245 } | 5242 } |
| 5246 | 5243 |
| 5247 DCHECK(!file_info->gdata_entry().resource_id().empty()); | 5244 DCHECK(!file_info->gdata_entry().resource_id().empty()); |
| 5248 | 5245 |
| 5249 // TODO(benchan,kinaba): Call ClearDirtyInCache instead of CommitDirtyInCache | 5246 // TODO(benchan,kinaba): Call ClearDirtyInCache instead of CommitDirtyInCache |
| 5250 // if the file has not been modified. Come up with a way to detect the | 5247 // if the file has not been modified. Come up with a way to detect the |
| 5251 // intactness effectively, or provide a method for user to declare it when | 5248 // intactness effectively, or provide a method for user to declare it when |
| 5252 // calling CloseFile(). | 5249 // calling CloseFile(). |
| 5253 | 5250 CommitDirtyInCache( |
| 5254 // TODO(kinaba): once it is cleaned up (crbug/127048), remove the indirection. | 5251 file_info->gdata_entry().resource_id(), |
| 5255 // Do not call CommitDirtyInCache() directly for avoiding deadlock. | 5252 file_info->file_md5(), |
| 5256 // The current method is called as a callback from GetFileInfoByPathAsync(), | |
| 5257 // which is under the lock taken. | |
| 5258 base::MessageLoopProxy::current()->PostTask( | |
| 5259 FROM_HERE, | |
| 5260 base::Bind( | 5253 base::Bind( |
| 5261 &GDataFileSystem::CommitDirtyInCache, | 5254 &GDataFileSystem::OnCommitDirtyInCacheCompleteForCloseFile, |
| 5262 ui_weak_ptr_, | 5255 ui_weak_ptr_, |
| 5263 file_info->gdata_entry().resource_id(), | 5256 callback)); |
| 5264 file_info->file_md5(), | |
| 5265 base::Bind(&GDataFileSystem::OnCommitDirtyInCacheCompleteForCloseFile, | |
| 5266 ui_weak_ptr_, | |
| 5267 callback))); | |
| 5268 } | 5257 } |
| 5269 | 5258 |
| 5270 void GDataFileSystem::OnCommitDirtyInCacheCompleteForCloseFile( | 5259 void GDataFileSystem::OnCommitDirtyInCacheCompleteForCloseFile( |
| 5271 const CloseFileCallback& callback, | 5260 const CloseFileCallback& callback, |
| 5272 base::PlatformFileError error, | 5261 base::PlatformFileError error, |
| 5273 const std::string& resource_id, | 5262 const std::string& resource_id, |
| 5274 const std::string& md5) { | 5263 const std::string& md5) { |
| 5275 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 5264 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 5276 | 5265 |
| 5277 if (!callback.is_null()) | 5266 if (!callback.is_null()) |
| 5278 callback.Run(error); | 5267 callback.Run(error); |
| 5279 } | 5268 } |
| 5280 | 5269 |
| 5281 } // namespace gdata | 5270 } // namespace gdata |
| OLD | NEW |