| OLD | NEW |
| (Empty) |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "chrome/browser/media_galleries/fileapi/picasa/picasa_file_util.h" | |
| 6 | |
| 7 #include <string> | |
| 8 #include <vector> | |
| 9 | |
| 10 #include "base/basictypes.h" | |
| 11 #include "base/bind_helpers.h" | |
| 12 #include "base/strings/string_util.h" | |
| 13 #include "base/strings/stringprintf.h" | |
| 14 #include "base/strings/sys_string_conversions.h" | |
| 15 #include "base/strings/utf_string_conversions.h" | |
| 16 #include "chrome/browser/media_galleries/fileapi/media_file_system_backend.h" | |
| 17 #include "chrome/browser/media_galleries/fileapi/picasa/picasa_data_provider.h" | |
| 18 #include "chrome/browser/media_galleries/imported_media_gallery_registry.h" | |
| 19 #include "chrome/common/media_galleries/picasa_types.h" | |
| 20 #include "content/public/browser/browser_thread.h" | |
| 21 #include "webkit/browser/fileapi/file_system_operation_context.h" | |
| 22 #include "webkit/browser/fileapi/file_system_url.h" | |
| 23 #include "webkit/browser/fileapi/native_file_util.h" | |
| 24 #include "webkit/common/fileapi/file_system_util.h" | |
| 25 | |
| 26 using base::FilePath; | |
| 27 using fileapi::DirectoryEntry; | |
| 28 using fileapi::FileSystemOperationContext; | |
| 29 using fileapi::FileSystemURL; | |
| 30 | |
| 31 namespace picasa { | |
| 32 | |
| 33 namespace { | |
| 34 | |
| 35 base::PlatformFileError FindAlbumInfo(const std::string& key, | |
| 36 const AlbumMap* map, | |
| 37 AlbumInfo* album_info) { | |
| 38 if (!map) | |
| 39 return base::PLATFORM_FILE_ERROR_FAILED; | |
| 40 | |
| 41 AlbumMap::const_iterator it = map->find(key); | |
| 42 | |
| 43 if (it == map->end()) | |
| 44 return base::PLATFORM_FILE_ERROR_NOT_FOUND; | |
| 45 | |
| 46 if (album_info != NULL) | |
| 47 *album_info = it->second; | |
| 48 | |
| 49 return base::PLATFORM_FILE_OK; | |
| 50 } | |
| 51 | |
| 52 PicasaDataProvider::DataType GetDataTypeForURL( | |
| 53 const fileapi::FileSystemURL& url) { | |
| 54 std::vector<std::string> components; | |
| 55 fileapi::VirtualPath::GetComponentsUTF8Unsafe(url.path(), &components); | |
| 56 | |
| 57 if (components.size() >= 2 && components[0] == kPicasaDirAlbums) | |
| 58 return PicasaDataProvider::ALBUMS_IMAGES_DATA; | |
| 59 | |
| 60 return PicasaDataProvider::LIST_OF_ALBUMS_AND_FOLDERS_DATA; | |
| 61 } | |
| 62 | |
| 63 } // namespace | |
| 64 | |
| 65 const char kPicasaDirAlbums[] = "albums"; | |
| 66 const char kPicasaDirFolders[] = "folders"; | |
| 67 | |
| 68 PicasaFileUtil::PicasaFileUtil(chrome::MediaPathFilter* media_path_filter) | |
| 69 : chrome::NativeMediaFileUtil(media_path_filter), | |
| 70 weak_factory_(this) { | |
| 71 } | |
| 72 | |
| 73 PicasaFileUtil::~PicasaFileUtil() {} | |
| 74 | |
| 75 void PicasaFileUtil::GetFileInfoOnTaskRunnerThread( | |
| 76 scoped_ptr<fileapi::FileSystemOperationContext> context, | |
| 77 const fileapi::FileSystemURL& url, | |
| 78 const GetFileInfoCallback& callback) { | |
| 79 GetDataProvider()->RefreshData( | |
| 80 GetDataTypeForURL(url), | |
| 81 base::Bind(&PicasaFileUtil::GetFileInfoWithFreshDataProvider, | |
| 82 weak_factory_.GetWeakPtr(), | |
| 83 base::Passed(&context), | |
| 84 url, | |
| 85 callback)); | |
| 86 } | |
| 87 | |
| 88 void PicasaFileUtil::ReadDirectoryOnTaskRunnerThread( | |
| 89 scoped_ptr<fileapi::FileSystemOperationContext> context, | |
| 90 const fileapi::FileSystemURL& url, | |
| 91 const ReadDirectoryCallback& callback) { | |
| 92 GetDataProvider()->RefreshData( | |
| 93 GetDataTypeForURL(url), | |
| 94 base::Bind(&PicasaFileUtil::ReadDirectoryWithFreshDataProvider, | |
| 95 weak_factory_.GetWeakPtr(), | |
| 96 base::Passed(&context), | |
| 97 url, | |
| 98 callback)); | |
| 99 } | |
| 100 | |
| 101 base::PlatformFileError PicasaFileUtil::GetFileInfoSync( | |
| 102 FileSystemOperationContext* context, const FileSystemURL& url, | |
| 103 base::PlatformFileInfo* file_info, base::FilePath* platform_path) { | |
| 104 DCHECK(context); | |
| 105 DCHECK(file_info); | |
| 106 DCHECK(platform_path); | |
| 107 | |
| 108 *platform_path = base::FilePath(); | |
| 109 | |
| 110 std::vector<std::string> components; | |
| 111 fileapi::VirtualPath::GetComponentsUTF8Unsafe(url.path(), &components); | |
| 112 | |
| 113 switch (components.size()) { | |
| 114 case 0: | |
| 115 // Root directory. | |
| 116 file_info->is_directory = true; | |
| 117 return base::PLATFORM_FILE_OK; | |
| 118 case 1: | |
| 119 if (components[0] == kPicasaDirAlbums || | |
| 120 components[0] == kPicasaDirFolders) { | |
| 121 file_info->is_directory = true; | |
| 122 return base::PLATFORM_FILE_OK; | |
| 123 } | |
| 124 | |
| 125 break; | |
| 126 case 2: | |
| 127 if (components[0] == kPicasaDirAlbums) { | |
| 128 scoped_ptr<AlbumMap> album_map = GetDataProvider()->GetAlbums(); | |
| 129 base::PlatformFileError error = | |
| 130 FindAlbumInfo(components[1], album_map.get(), NULL); | |
| 131 if (error != base::PLATFORM_FILE_OK) | |
| 132 return error; | |
| 133 | |
| 134 file_info->is_directory = true; | |
| 135 return base::PLATFORM_FILE_OK; | |
| 136 } | |
| 137 | |
| 138 if (components[0] == kPicasaDirFolders) { | |
| 139 return NativeMediaFileUtil::GetFileInfoSync(context, url, file_info, | |
| 140 platform_path); | |
| 141 } | |
| 142 break; | |
| 143 case 3: | |
| 144 // NativeMediaFileUtil::GetInfo calls into virtual function | |
| 145 // PicasaFileUtil::GetLocalFilePath, and that will handle both | |
| 146 // album contents and folder contents. | |
| 147 base::PlatformFileError result = NativeMediaFileUtil::GetFileInfoSync( | |
| 148 context, url, file_info, platform_path); | |
| 149 | |
| 150 DCHECK(components[0] == kPicasaDirAlbums || | |
| 151 components[0] == kPicasaDirFolders || | |
| 152 result == base::PLATFORM_FILE_ERROR_NOT_FOUND); | |
| 153 | |
| 154 return result; | |
| 155 } | |
| 156 | |
| 157 return base::PLATFORM_FILE_ERROR_NOT_FOUND; | |
| 158 } | |
| 159 | |
| 160 base::PlatformFileError PicasaFileUtil::ReadDirectorySync( | |
| 161 fileapi::FileSystemOperationContext* context, | |
| 162 const fileapi::FileSystemURL& url, | |
| 163 EntryList* file_list) { | |
| 164 DCHECK(context); | |
| 165 DCHECK(file_list); | |
| 166 DCHECK(file_list->empty()); | |
| 167 | |
| 168 base::PlatformFileInfo file_info; | |
| 169 base::FilePath platform_directory_path; | |
| 170 base::PlatformFileError error = GetFileInfoSync( | |
| 171 context, url, &file_info, &platform_directory_path); | |
| 172 | |
| 173 if (error != base::PLATFORM_FILE_OK) | |
| 174 return error; | |
| 175 | |
| 176 if (!file_info.is_directory) | |
| 177 return base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY; | |
| 178 | |
| 179 std::vector<std::string> components; | |
| 180 fileapi::VirtualPath::GetComponentsUTF8Unsafe(url.path(), &components); | |
| 181 | |
| 182 switch (components.size()) { | |
| 183 case 0: { | |
| 184 // Root directory. | |
| 185 file_list->push_back( | |
| 186 DirectoryEntry(kPicasaDirAlbums, DirectoryEntry::DIRECTORY, 0, | |
| 187 base::Time())); | |
| 188 file_list->push_back( | |
| 189 DirectoryEntry(kPicasaDirFolders, DirectoryEntry::DIRECTORY, 0, | |
| 190 base::Time())); | |
| 191 break; | |
| 192 } | |
| 193 case 1: | |
| 194 if (components[0] == kPicasaDirAlbums) { | |
| 195 scoped_ptr<AlbumMap> albums = GetDataProvider()->GetAlbums(); | |
| 196 if (!albums) | |
| 197 return base::PLATFORM_FILE_ERROR_NOT_FOUND; | |
| 198 | |
| 199 for (AlbumMap::const_iterator it = albums->begin(); | |
| 200 it != albums->end(); ++it) { | |
| 201 file_list->push_back( | |
| 202 DirectoryEntry(it->first, DirectoryEntry::DIRECTORY, 0, | |
| 203 it->second.timestamp)); | |
| 204 } | |
| 205 } else if (components[0] == kPicasaDirFolders) { | |
| 206 scoped_ptr<AlbumMap> folders = GetDataProvider()->GetFolders(); | |
| 207 if (!folders) | |
| 208 return base::PLATFORM_FILE_ERROR_NOT_FOUND; | |
| 209 | |
| 210 for (AlbumMap::const_iterator it = folders->begin(); | |
| 211 it != folders->end(); ++it) { | |
| 212 file_list->push_back( | |
| 213 DirectoryEntry(it->first, DirectoryEntry::DIRECTORY, 0, | |
| 214 it->second.timestamp)); | |
| 215 } | |
| 216 } | |
| 217 break; | |
| 218 case 2: | |
| 219 if (components[0] == kPicasaDirAlbums) { | |
| 220 scoped_ptr<AlbumMap> album_map = GetDataProvider()->GetAlbums(); | |
| 221 AlbumInfo album_info; | |
| 222 base::PlatformFileError error = | |
| 223 FindAlbumInfo(components[1], album_map.get(), &album_info); | |
| 224 if (error != base::PLATFORM_FILE_OK) | |
| 225 return error; | |
| 226 | |
| 227 scoped_ptr<AlbumImages> album_images = | |
| 228 GetDataProvider()->FindAlbumImages(album_info.uid, &error); | |
| 229 if (error != base::PLATFORM_FILE_OK) | |
| 230 return error; | |
| 231 | |
| 232 for (AlbumImages::const_iterator it = album_images->begin(); | |
| 233 it != album_images->end(); | |
| 234 ++it) { | |
| 235 fileapi::DirectoryEntry entry; | |
| 236 base::PlatformFileInfo info; | |
| 237 | |
| 238 // Simply skip files that we can't get info on. | |
| 239 if (fileapi::NativeFileUtil::GetFileInfo(it->second, &info) != | |
| 240 base::PLATFORM_FILE_OK) { | |
| 241 continue; | |
| 242 } | |
| 243 | |
| 244 file_list->push_back(DirectoryEntry( | |
| 245 it->first, DirectoryEntry::FILE, info.size, info.last_modified)); | |
| 246 } | |
| 247 } | |
| 248 | |
| 249 if (components[0] == kPicasaDirFolders) { | |
| 250 EntryList super_list; | |
| 251 base::PlatformFileError error = | |
| 252 NativeMediaFileUtil::ReadDirectorySync(context, url, &super_list); | |
| 253 if (error != base::PLATFORM_FILE_OK) | |
| 254 return error; | |
| 255 | |
| 256 for (EntryList::const_iterator it = super_list.begin(); | |
| 257 it != super_list.end(); ++it) { | |
| 258 if (!it->is_directory) | |
| 259 file_list->push_back(*it); | |
| 260 } | |
| 261 } | |
| 262 | |
| 263 break; | |
| 264 } | |
| 265 | |
| 266 return base::PLATFORM_FILE_OK; | |
| 267 } | |
| 268 | |
| 269 base::PlatformFileError PicasaFileUtil::GetLocalFilePath( | |
| 270 FileSystemOperationContext* context, const FileSystemURL& url, | |
| 271 base::FilePath* local_file_path) { | |
| 272 DCHECK(local_file_path); | |
| 273 DCHECK(url.is_valid()); | |
| 274 std::vector<std::string> components; | |
| 275 fileapi::VirtualPath::GetComponentsUTF8Unsafe(url.path(), &components); | |
| 276 | |
| 277 switch (components.size()) { | |
| 278 case 2: | |
| 279 if (components[0] == kPicasaDirFolders) { | |
| 280 scoped_ptr<AlbumMap> album_map = GetDataProvider()->GetFolders(); | |
| 281 AlbumInfo album_info; | |
| 282 base::PlatformFileError error = | |
| 283 FindAlbumInfo(components[1], album_map.get(), &album_info); | |
| 284 if (error != base::PLATFORM_FILE_OK) | |
| 285 return error; | |
| 286 | |
| 287 *local_file_path = album_info.path; | |
| 288 return base::PLATFORM_FILE_OK; | |
| 289 } | |
| 290 break; | |
| 291 case 3: | |
| 292 if (components[0] == kPicasaDirAlbums) { | |
| 293 scoped_ptr<AlbumMap> album_map = GetDataProvider()->GetAlbums(); | |
| 294 AlbumInfo album_info; | |
| 295 base::PlatformFileError error = | |
| 296 FindAlbumInfo(components[1], album_map.get(), &album_info); | |
| 297 if (error != base::PLATFORM_FILE_OK) | |
| 298 return error; | |
| 299 | |
| 300 scoped_ptr<AlbumImages> album_images = | |
| 301 GetDataProvider()->FindAlbumImages(album_info.uid, &error); | |
| 302 if (error != base::PLATFORM_FILE_OK) | |
| 303 return error; | |
| 304 | |
| 305 AlbumImages::const_iterator it = album_images->find(components[2]); | |
| 306 if (it == album_images->end()) | |
| 307 return base::PLATFORM_FILE_ERROR_NOT_FOUND; | |
| 308 | |
| 309 *local_file_path = it->second; | |
| 310 return base::PLATFORM_FILE_OK; | |
| 311 } | |
| 312 | |
| 313 if (components[0] == kPicasaDirFolders) { | |
| 314 scoped_ptr<AlbumMap> album_map = GetDataProvider()->GetFolders(); | |
| 315 AlbumInfo album_info; | |
| 316 base::PlatformFileError error = | |
| 317 FindAlbumInfo(components[1], album_map.get(), &album_info); | |
| 318 if (error != base::PLATFORM_FILE_OK) | |
| 319 return error; | |
| 320 | |
| 321 // Not part of this class's mandate to check that it actually exists. | |
| 322 *local_file_path = album_info.path.Append(url.path().BaseName()); | |
| 323 return base::PLATFORM_FILE_OK; | |
| 324 } | |
| 325 | |
| 326 return base::PLATFORM_FILE_ERROR_NOT_FOUND; | |
| 327 break; | |
| 328 } | |
| 329 | |
| 330 // All other cases don't have a local path. The valid cases should be | |
| 331 // intercepted by GetFileInfo()/CreateFileEnumerator(). Invalid cases | |
| 332 // return a NOT_FOUND error. | |
| 333 return base::PLATFORM_FILE_ERROR_NOT_FOUND; | |
| 334 } | |
| 335 | |
| 336 void PicasaFileUtil::GetFileInfoWithFreshDataProvider( | |
| 337 scoped_ptr<fileapi::FileSystemOperationContext> context, | |
| 338 const fileapi::FileSystemURL& url, | |
| 339 const GetFileInfoCallback& callback, | |
| 340 bool success) { | |
| 341 if (!success) { | |
| 342 content::BrowserThread::PostTask( | |
| 343 content::BrowserThread::IO, | |
| 344 FROM_HERE, | |
| 345 base::Bind( | |
| 346 callback, base::PLATFORM_FILE_ERROR_IO, base::PlatformFileInfo())); | |
| 347 return; | |
| 348 } | |
| 349 NativeMediaFileUtil::GetFileInfoOnTaskRunnerThread( | |
| 350 context.Pass(), url, callback); | |
| 351 } | |
| 352 | |
| 353 void PicasaFileUtil::ReadDirectoryWithFreshDataProvider( | |
| 354 scoped_ptr<fileapi::FileSystemOperationContext> context, | |
| 355 const fileapi::FileSystemURL& url, | |
| 356 const ReadDirectoryCallback& callback, | |
| 357 bool success) { | |
| 358 if (!success) { | |
| 359 content::BrowserThread::PostTask( | |
| 360 content::BrowserThread::IO, | |
| 361 FROM_HERE, | |
| 362 base::Bind(callback, base::PLATFORM_FILE_ERROR_IO, EntryList(), false)); | |
| 363 return; | |
| 364 } | |
| 365 NativeMediaFileUtil::ReadDirectoryOnTaskRunnerThread( | |
| 366 context.Pass(), url, callback); | |
| 367 } | |
| 368 | |
| 369 PicasaDataProvider* PicasaFileUtil::GetDataProvider() { | |
| 370 return chrome::ImportedMediaGalleryRegistry::PicasaDataProvider(); | |
| 371 } | |
| 372 | |
| 373 } // namespace picasa | |
| OLD | NEW |