blob: fa7bb7a22799545535239f682a88c7c4e9dcaf02 [file] [log] [blame]
// 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