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.
5 #include "chrome/browser/media_galleries/fileapi/picasa_file_util.h"
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_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"
27 using fileapi::DirectoryEntry
;
28 using fileapi::FileSystemOperationContext
;
29 using fileapi::FileSystemURL
;
35 base::PlatformFileError
FindAlbumInfo(const std::string
& key
,
37 AlbumInfo
* album_info
) {
39 return base::PLATFORM_FILE_ERROR_FAILED
;
41 AlbumMap::const_iterator it
= map
->find(key
);
44 return base::PLATFORM_FILE_ERROR_NOT_FOUND
;
46 if (album_info
!= NULL
)
47 *album_info
= it
->second
;
49 return base::PLATFORM_FILE_OK
;
52 PicasaDataProvider::DataType
GetDataTypeForURL(
53 const fileapi::FileSystemURL
& url
) {
54 std::vector
<std::string
> components
;
55 fileapi::VirtualPath::GetComponentsUTF8Unsafe(url
.path(), &components
);
57 if (components
.size() >= 2 && components
[0] == kPicasaDirAlbums
)
58 return PicasaDataProvider::ALBUMS_IMAGES_DATA
;
60 return PicasaDataProvider::LIST_OF_ALBUMS_AND_FOLDERS_DATA
;
65 const char kPicasaDirAlbums
[] = "albums";
66 const char kPicasaDirFolders
[] = "folders";
68 PicasaFileUtil::PicasaFileUtil(MediaPathFilter
* media_path_filter
)
69 : NativeMediaFileUtil(media_path_filter
),
73 PicasaFileUtil::~PicasaFileUtil() {}
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
),
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
),
101 base::PlatformFileError
PicasaFileUtil::GetFileInfoSync(
102 FileSystemOperationContext
* context
, const FileSystemURL
& url
,
103 base::PlatformFileInfo
* file_info
, base::FilePath
* platform_path
) {
108 *platform_path
= base::FilePath();
110 std::vector
<std::string
> components
;
111 fileapi::VirtualPath::GetComponentsUTF8Unsafe(url
.path(), &components
);
113 switch (components
.size()) {
116 file_info
->is_directory
= true;
117 return base::PLATFORM_FILE_OK
;
119 if (components
[0] == kPicasaDirAlbums
||
120 components
[0] == kPicasaDirFolders
) {
121 file_info
->is_directory
= true;
122 return base::PLATFORM_FILE_OK
;
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
)
134 file_info
->is_directory
= true;
135 return base::PLATFORM_FILE_OK
;
138 if (components
[0] == kPicasaDirFolders
) {
139 return NativeMediaFileUtil::GetFileInfoSync(context
, url
, file_info
,
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
);
150 DCHECK(components
[0] == kPicasaDirAlbums
||
151 components
[0] == kPicasaDirFolders
||
152 result
== base::PLATFORM_FILE_ERROR_NOT_FOUND
);
157 return base::PLATFORM_FILE_ERROR_NOT_FOUND
;
160 base::PlatformFileError
PicasaFileUtil::ReadDirectorySync(
161 fileapi::FileSystemOperationContext
* context
,
162 const fileapi::FileSystemURL
& url
,
163 EntryList
* file_list
) {
166 DCHECK(file_list
->empty());
168 base::PlatformFileInfo file_info
;
169 base::FilePath platform_directory_path
;
170 base::PlatformFileError error
= GetFileInfoSync(
171 context
, url
, &file_info
, &platform_directory_path
);
173 if (error
!= base::PLATFORM_FILE_OK
)
176 if (!file_info
.is_directory
)
177 return base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY
;
179 std::vector
<std::string
> components
;
180 fileapi::VirtualPath::GetComponentsUTF8Unsafe(url
.path(), &components
);
182 switch (components
.size()) {
185 file_list
->push_back(
186 DirectoryEntry(kPicasaDirAlbums
, DirectoryEntry::DIRECTORY
, 0,
188 file_list
->push_back(
189 DirectoryEntry(kPicasaDirFolders
, DirectoryEntry::DIRECTORY
, 0,
194 if (components
[0] == kPicasaDirAlbums
) {
195 scoped_ptr
<AlbumMap
> albums
= GetDataProvider()->GetAlbums();
197 return base::PLATFORM_FILE_ERROR_NOT_FOUND
;
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
));
205 } else if (components
[0] == kPicasaDirFolders
) {
206 scoped_ptr
<AlbumMap
> folders
= GetDataProvider()->GetFolders();
208 return base::PLATFORM_FILE_ERROR_NOT_FOUND
;
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
));
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
)
227 scoped_ptr
<AlbumImages
> album_images
=
228 GetDataProvider()->FindAlbumImages(album_info
.uid
, &error
);
229 if (error
!= base::PLATFORM_FILE_OK
)
232 for (AlbumImages::const_iterator it
= album_images
->begin();
233 it
!= album_images
->end();
235 fileapi::DirectoryEntry entry
;
236 base::PlatformFileInfo info
;
238 // Simply skip files that we can't get info on.
239 if (fileapi::NativeFileUtil::GetFileInfo(it
->second
, &info
) !=
240 base::PLATFORM_FILE_OK
) {
244 file_list
->push_back(DirectoryEntry(
245 it
->first
, DirectoryEntry::FILE, info
.size
, info
.last_modified
));
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
)
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
);
266 return base::PLATFORM_FILE_OK
;
269 base::PlatformFileError
PicasaFileUtil::DeleteDirectorySync(
270 fileapi::FileSystemOperationContext
* context
,
271 const fileapi::FileSystemURL
& url
) {
272 return base::PLATFORM_FILE_ERROR_SECURITY
;
275 base::PlatformFileError
PicasaFileUtil::DeleteFileSync(
276 fileapi::FileSystemOperationContext
* context
,
277 const fileapi::FileSystemURL
& url
) {
278 return base::PLATFORM_FILE_ERROR_SECURITY
;
281 base::PlatformFileError
PicasaFileUtil::GetLocalFilePath(
282 FileSystemOperationContext
* context
, const FileSystemURL
& url
,
283 base::FilePath
* local_file_path
) {
284 DCHECK(local_file_path
);
285 DCHECK(url
.is_valid());
286 std::vector
<std::string
> components
;
287 fileapi::VirtualPath::GetComponentsUTF8Unsafe(url
.path(), &components
);
289 switch (components
.size()) {
291 if (components
[0] == kPicasaDirFolders
) {
292 scoped_ptr
<AlbumMap
> album_map
= GetDataProvider()->GetFolders();
293 AlbumInfo album_info
;
294 base::PlatformFileError error
=
295 FindAlbumInfo(components
[1], album_map
.get(), &album_info
);
296 if (error
!= base::PLATFORM_FILE_OK
)
299 *local_file_path
= album_info
.path
;
300 return base::PLATFORM_FILE_OK
;
304 if (components
[0] == kPicasaDirAlbums
) {
305 scoped_ptr
<AlbumMap
> album_map
= GetDataProvider()->GetAlbums();
306 AlbumInfo album_info
;
307 base::PlatformFileError error
=
308 FindAlbumInfo(components
[1], album_map
.get(), &album_info
);
309 if (error
!= base::PLATFORM_FILE_OK
)
312 scoped_ptr
<AlbumImages
> album_images
=
313 GetDataProvider()->FindAlbumImages(album_info
.uid
, &error
);
314 if (error
!= base::PLATFORM_FILE_OK
)
317 AlbumImages::const_iterator it
= album_images
->find(components
[2]);
318 if (it
== album_images
->end())
319 return base::PLATFORM_FILE_ERROR_NOT_FOUND
;
321 *local_file_path
= it
->second
;
322 return base::PLATFORM_FILE_OK
;
325 if (components
[0] == kPicasaDirFolders
) {
326 scoped_ptr
<AlbumMap
> album_map
= GetDataProvider()->GetFolders();
327 AlbumInfo album_info
;
328 base::PlatformFileError error
=
329 FindAlbumInfo(components
[1], album_map
.get(), &album_info
);
330 if (error
!= base::PLATFORM_FILE_OK
)
333 // Not part of this class's mandate to check that it actually exists.
334 *local_file_path
= album_info
.path
.Append(url
.path().BaseName());
335 return base::PLATFORM_FILE_OK
;
338 return base::PLATFORM_FILE_ERROR_NOT_FOUND
;
342 // All other cases don't have a local path. The valid cases should be
343 // intercepted by GetFileInfo()/CreateFileEnumerator(). Invalid cases
344 // return a NOT_FOUND error.
345 return base::PLATFORM_FILE_ERROR_NOT_FOUND
;
348 void PicasaFileUtil::GetFileInfoWithFreshDataProvider(
349 scoped_ptr
<fileapi::FileSystemOperationContext
> context
,
350 const fileapi::FileSystemURL
& url
,
351 const GetFileInfoCallback
& callback
,
354 content::BrowserThread::PostTask(
355 content::BrowserThread::IO
,
358 callback
, base::PLATFORM_FILE_ERROR_IO
, base::PlatformFileInfo()));
361 NativeMediaFileUtil::GetFileInfoOnTaskRunnerThread(
362 context
.Pass(), url
, callback
);
365 void PicasaFileUtil::ReadDirectoryWithFreshDataProvider(
366 scoped_ptr
<fileapi::FileSystemOperationContext
> context
,
367 const fileapi::FileSystemURL
& url
,
368 const ReadDirectoryCallback
& callback
,
371 content::BrowserThread::PostTask(
372 content::BrowserThread::IO
,
374 base::Bind(callback
, base::PLATFORM_FILE_ERROR_IO
, EntryList(), false));
377 NativeMediaFileUtil::ReadDirectoryOnTaskRunnerThread(
378 context
.Pass(), url
, callback
);
381 PicasaDataProvider
* PicasaFileUtil::GetDataProvider() {
382 return ImportedMediaGalleryRegistry::PicasaDataProvider();
385 } // namespace picasa