| // Copyright 2013 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/browser/media_galleries/fileapi/picasa/picasa_file_util.h" |
| |
| #include <string> |
| #include <vector> |
| |
| #include "base/basictypes.h" |
| #include "base/bind_helpers.h" |
| #include "base/strings/string_util.h" |
| #include "base/strings/stringprintf.h" |
| #include "base/strings/sys_string_conversions.h" |
| #include "base/strings/utf_string_conversions.h" |
| #include "chrome/browser/media_galleries/fileapi/media_file_system_backend.h" |
| #include "chrome/browser/media_galleries/fileapi/picasa/picasa_data_provider.h" |
| #include "chrome/browser/media_galleries/imported_media_gallery_registry.h" |
| #include "chrome/common/media_galleries/picasa_types.h" |
| #include "webkit/browser/fileapi/file_system_operation_context.h" |
| #include "webkit/browser/fileapi/file_system_url.h" |
| #include "webkit/common/fileapi/file_system_util.h" |
| |
| using base::FilePath; |
| using fileapi::DirectoryEntry; |
| using fileapi::FileSystemOperationContext; |
| using fileapi::FileSystemURL; |
| |
| namespace picasa { |
| |
| namespace { |
| |
| // |error| is only set when the method fails and the return is NULL. |
| base::PlatformFileError FindAlbumInfo(const std::string& key, |
| const AlbumMap* map, |
| AlbumInfo* album_info) { |
| if (!map) |
| return base::PLATFORM_FILE_ERROR_FAILED; |
| |
| AlbumMap::const_iterator it = map->find(key); |
| |
| if (it == map->end()) |
| return base::PLATFORM_FILE_ERROR_NOT_FOUND; |
| |
| if (album_info != NULL) |
| *album_info = it->second; |
| |
| return base::PLATFORM_FILE_OK; |
| } |
| |
| } // namespace |
| |
| const char kPicasaDirAlbums[] = "albums"; |
| const char kPicasaDirFolders[] = "folders"; |
| |
| PicasaFileUtil::PicasaFileUtil(chrome::MediaPathFilter* media_path_filter) |
| : chrome::NativeMediaFileUtil(media_path_filter), |
| weak_factory_(this) { |
| } |
| |
| PicasaFileUtil::~PicasaFileUtil() {} |
| |
| void PicasaFileUtil::GetFileInfoOnTaskRunnerThread( |
| scoped_ptr<fileapi::FileSystemOperationContext> context, |
| const fileapi::FileSystemURL& url, |
| const GetFileInfoCallback& callback) { |
| GetDataProvider()->RefreshData( |
| base::Bind(&PicasaFileUtil::GetFileInfoWithFreshDataProvider, |
| weak_factory_.GetWeakPtr(), base::Passed(&context), url, |
| callback)); |
| } |
| |
| void PicasaFileUtil::ReadDirectoryOnTaskRunnerThread( |
| scoped_ptr<fileapi::FileSystemOperationContext> context, |
| const fileapi::FileSystemURL& url, |
| const ReadDirectoryCallback& callback) { |
| GetDataProvider()->RefreshData( |
| base::Bind(&PicasaFileUtil::ReadDirectoryWithFreshDataProvider, |
| weak_factory_.GetWeakPtr(), base::Passed(&context), url, |
| callback)); |
| } |
| |
| base::PlatformFileError PicasaFileUtil::GetFileInfoSync( |
| FileSystemOperationContext* context, const FileSystemURL& url, |
| base::PlatformFileInfo* file_info, base::FilePath* platform_path) { |
| DCHECK(context); |
| DCHECK(file_info); |
| DCHECK(platform_path); |
| |
| *platform_path = base::FilePath(); |
| |
| std::vector<std::string> components; |
| fileapi::VirtualPath::GetComponentsUTF8Unsafe(url.path(), &components); |
| |
| switch (components.size()) { |
| case 0: |
| // Root directory. |
| file_info->is_directory = true; |
| return base::PLATFORM_FILE_OK; |
| case 1: |
| if (components[0] == kPicasaDirAlbums || |
| components[0] == kPicasaDirFolders) { |
| file_info->is_directory = true; |
| return base::PLATFORM_FILE_OK; |
| } |
| |
| break; |
| case 2: |
| if (components[0] == kPicasaDirAlbums) { |
| scoped_ptr<AlbumMap> album_map = GetDataProvider()->GetAlbums(); |
| base::PlatformFileError error = |
| FindAlbumInfo(components[1], album_map.get(), NULL); |
| if (error != base::PLATFORM_FILE_OK) |
| return error; |
| |
| file_info->is_directory = true; |
| return base::PLATFORM_FILE_OK; |
| } |
| |
| if (components[0] == kPicasaDirFolders) { |
| return NativeMediaFileUtil::GetFileInfoSync(context, url, file_info, |
| platform_path); |
| } |
| break; |
| case 3: |
| // NativeMediaFileUtil::GetInfo calls into virtual function |
| // PicasaFileUtil::GetLocalFilePath, and that will handle both |
| // album contents and folder contents. |
| base::PlatformFileError result = NativeMediaFileUtil::GetFileInfoSync( |
| context, url, file_info, platform_path); |
| |
| DCHECK(components[0] == kPicasaDirAlbums || |
| components[0] == kPicasaDirFolders || |
| result == base::PLATFORM_FILE_ERROR_NOT_FOUND); |
| |
| return result; |
| } |
| |
| return base::PLATFORM_FILE_ERROR_NOT_FOUND; |
| } |
| |
| base::PlatformFileError PicasaFileUtil::ReadDirectorySync( |
| fileapi::FileSystemOperationContext* context, |
| const fileapi::FileSystemURL& url, |
| EntryList* file_list) { |
| DCHECK(context); |
| DCHECK(file_list); |
| DCHECK(file_list->empty()); |
| |
| base::PlatformFileInfo file_info; |
| base::FilePath platform_directory_path; |
| base::PlatformFileError error = GetFileInfoSync( |
| context, url, &file_info, &platform_directory_path); |
| |
| if (error != base::PLATFORM_FILE_OK) |
| return error; |
| |
| if (!file_info.is_directory) |
| return base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY; |
| |
| std::vector<std::string> components; |
| fileapi::VirtualPath::GetComponentsUTF8Unsafe(url.path(), &components); |
| |
| switch (components.size()) { |
| case 0: { |
| // Root directory. |
| file_list->push_back( |
| DirectoryEntry(kPicasaDirAlbums, DirectoryEntry::DIRECTORY, 0, |
| base::Time())); |
| file_list->push_back( |
| DirectoryEntry(kPicasaDirFolders, DirectoryEntry::DIRECTORY, 0, |
| base::Time())); |
| break; |
| } |
| case 1: |
| if (components[0] == kPicasaDirAlbums) { |
| scoped_ptr<AlbumMap> albums = GetDataProvider()->GetAlbums(); |
| if (!albums) |
| return base::PLATFORM_FILE_ERROR_NOT_FOUND; |
| |
| for (AlbumMap::const_iterator it = albums->begin(); |
| it != albums->end(); ++it) { |
| file_list->push_back( |
| DirectoryEntry(it->first, DirectoryEntry::DIRECTORY, 0, |
| it->second.timestamp)); |
| } |
| } else if (components[0] == kPicasaDirFolders) { |
| scoped_ptr<AlbumMap> folders = GetDataProvider()->GetFolders(); |
| if (!folders) |
| return base::PLATFORM_FILE_ERROR_NOT_FOUND; |
| |
| for (AlbumMap::const_iterator it = folders->begin(); |
| it != folders->end(); ++it) { |
| file_list->push_back( |
| DirectoryEntry(it->first, DirectoryEntry::DIRECTORY, 0, |
| it->second.timestamp)); |
| } |
| } |
| break; |
| case 2: |
| if (components[0] == kPicasaDirAlbums) { |
| // TODO(tommycli): Implement album contents. |
| } |
| |
| if (components[0] == kPicasaDirFolders) { |
| EntryList super_list; |
| base::PlatformFileError error = |
| NativeMediaFileUtil::ReadDirectorySync(context, url, &super_list); |
| if (error != base::PLATFORM_FILE_OK) |
| return error; |
| |
| for (EntryList::const_iterator it = super_list.begin(); |
| it != super_list.end(); ++it) { |
| if (!it->is_directory) |
| file_list->push_back(*it); |
| } |
| } |
| |
| break; |
| } |
| |
| return base::PLATFORM_FILE_OK; |
| } |
| |
| base::PlatformFileError PicasaFileUtil::GetLocalFilePath( |
| FileSystemOperationContext* context, const FileSystemURL& url, |
| base::FilePath* local_file_path) { |
| DCHECK(local_file_path); |
| DCHECK(url.is_valid()); |
| std::vector<std::string> components; |
| fileapi::VirtualPath::GetComponentsUTF8Unsafe(url.path(), &components); |
| |
| switch (components.size()) { |
| case 2: |
| if (components[0] == kPicasaDirFolders) { |
| scoped_ptr<AlbumMap> album_map = GetDataProvider()->GetFolders(); |
| AlbumInfo album_info; |
| base::PlatformFileError error = |
| FindAlbumInfo(components[1], album_map.get(), &album_info); |
| if (error != base::PLATFORM_FILE_OK) |
| return error; |
| |
| *local_file_path = album_info.path; |
| return base::PLATFORM_FILE_OK; |
| } |
| break; |
| case 3: |
| if (components[0] == kPicasaDirAlbums) { |
| scoped_ptr<AlbumMap> album_map = GetDataProvider()->GetAlbums(); |
| base::PlatformFileError error = |
| FindAlbumInfo(components[1], album_map.get(), NULL); |
| if (error != base::PLATFORM_FILE_OK) |
| return error; |
| |
| // TODO(tommycli): Implement album contents. |
| return base::PLATFORM_FILE_ERROR_NOT_FOUND; |
| } |
| |
| if (components[0] == kPicasaDirFolders) { |
| scoped_ptr<AlbumMap> album_map = GetDataProvider()->GetFolders(); |
| AlbumInfo album_info; |
| base::PlatformFileError error = |
| FindAlbumInfo(components[1], album_map.get(), &album_info); |
| if (error != base::PLATFORM_FILE_OK) |
| return error; |
| |
| // Not part of this class's mandate to check that it actually exists. |
| *local_file_path = album_info.path.Append(url.path().BaseName()); |
| return base::PLATFORM_FILE_OK; |
| } |
| |
| return base::PLATFORM_FILE_ERROR_NOT_FOUND; |
| break; |
| } |
| |
| // All other cases don't have a local path. The valid cases should be |
| // intercepted by GetFileInfo()/CreateFileEnumerator(). Invalid cases |
| // return a NOT_FOUND error. |
| return base::PLATFORM_FILE_ERROR_NOT_FOUND; |
| } |
| |
| void PicasaFileUtil::GetFileInfoWithFreshDataProvider( |
| scoped_ptr<fileapi::FileSystemOperationContext> context, |
| const fileapi::FileSystemURL& url, |
| const GetFileInfoCallback& callback) { |
| NativeMediaFileUtil::GetFileInfoOnTaskRunnerThread(context.Pass(), url, |
| callback); |
| } |
| |
| void PicasaFileUtil::ReadDirectoryWithFreshDataProvider( |
| scoped_ptr<fileapi::FileSystemOperationContext> context, |
| const fileapi::FileSystemURL& url, |
| const ReadDirectoryCallback& callback) { |
| NativeMediaFileUtil::ReadDirectoryOnTaskRunnerThread(context.Pass(), url, |
| callback); |
| } |
| |
| PicasaDataProvider* PicasaFileUtil::GetDataProvider() { |
| return chrome::ImportedMediaGalleryRegistry::PicasaDataProvider(); |
| } |
| |
| } // namespace picasa |