Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / media_galleries / fileapi / iphoto_file_util.cc
blob765fba18321ca1347bfc9302cbbb7c929998a037
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/iphoto_file_util.h"
7 #include <set>
8 #include <string>
9 #include <vector>
11 #include "base/bind_helpers.h"
12 #include "base/file_util.h"
13 #include "base/strings/string_number_conversions.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "chrome/browser/media_galleries/fileapi/iphoto_data_provider.h"
16 #include "chrome/browser/media_galleries/fileapi/media_path_filter.h"
17 #include "chrome/browser/media_galleries/imported_media_gallery_registry.h"
18 #include "content/public/browser/browser_thread.h"
19 #include "webkit/browser/fileapi/file_system_operation_context.h"
20 #include "webkit/browser/fileapi/file_system_url.h"
21 #include "webkit/browser/fileapi/native_file_util.h"
22 #include "webkit/common/blob/shareable_file_reference.h"
23 #include "webkit/common/fileapi/directory_entry.h"
24 #include "webkit/common/fileapi/file_system_util.h"
26 using fileapi::DirectoryEntry;
28 namespace iphoto {
30 namespace {
32 base::PlatformFileError MakeDirectoryFileInfo(
33 base::PlatformFileInfo* file_info) {
34 base::PlatformFileInfo result;
35 result.is_directory = true;
36 *file_info = result;
37 return base::PLATFORM_FILE_OK;
40 template <typename T>
41 bool ContainsElement(const std::vector<T>& collection, const T& key) {
42 typename std::vector<T>::const_iterator it = collection.begin();
43 while (it != collection.end()) {
44 if (*it == key)
45 return true;
46 it++;
48 return false;
51 } // namespace
53 const char kIPhotoAlbumsDir[] = "Albums";
54 const char kIPhotoOriginalsDir[] = "Originals";
56 IPhotoFileUtil::IPhotoFileUtil(MediaPathFilter* media_path_filter)
57 : NativeMediaFileUtil(media_path_filter),
58 weak_factory_(this),
59 imported_registry_(NULL) {
62 IPhotoFileUtil::~IPhotoFileUtil() {
65 void IPhotoFileUtil::GetFileInfoOnTaskRunnerThread(
66 scoped_ptr<fileapi::FileSystemOperationContext> context,
67 const fileapi::FileSystemURL& url,
68 const GetFileInfoCallback& callback) {
69 GetDataProvider()->RefreshData(
70 base::Bind(&IPhotoFileUtil::GetFileInfoWithFreshDataProvider,
71 weak_factory_.GetWeakPtr(), base::Passed(&context), url,
72 callback));
75 void IPhotoFileUtil::ReadDirectoryOnTaskRunnerThread(
76 scoped_ptr<fileapi::FileSystemOperationContext> context,
77 const fileapi::FileSystemURL& url,
78 const ReadDirectoryCallback& callback) {
79 GetDataProvider()->RefreshData(
80 base::Bind(&IPhotoFileUtil::ReadDirectoryWithFreshDataProvider,
81 weak_factory_.GetWeakPtr(), base::Passed(&context), url,
82 callback));
85 void IPhotoFileUtil::CreateSnapshotFileOnTaskRunnerThread(
86 scoped_ptr<fileapi::FileSystemOperationContext> context,
87 const fileapi::FileSystemURL& url,
88 const CreateSnapshotFileCallback& callback) {
89 GetDataProvider()->RefreshData(
90 base::Bind(&IPhotoFileUtil::CreateSnapshotFileWithFreshDataProvider,
91 weak_factory_.GetWeakPtr(), base::Passed(&context), url,
92 callback));
95 void IPhotoFileUtil::GetFileInfoWithFreshDataProvider(
96 scoped_ptr<fileapi::FileSystemOperationContext> context,
97 const fileapi::FileSystemURL& url,
98 const GetFileInfoCallback& callback,
99 bool valid_parse) {
100 if (!valid_parse) {
101 if (!callback.is_null()) {
102 content::BrowserThread::PostTask(
103 content::BrowserThread::IO,
104 FROM_HERE,
105 base::Bind(callback, base::PLATFORM_FILE_ERROR_IO,
106 base::PlatformFileInfo()));
108 return;
110 NativeMediaFileUtil::GetFileInfoOnTaskRunnerThread(context.Pass(), url,
111 callback);
114 void IPhotoFileUtil::ReadDirectoryWithFreshDataProvider(
115 scoped_ptr<fileapi::FileSystemOperationContext> context,
116 const fileapi::FileSystemURL& url,
117 const ReadDirectoryCallback& callback,
118 bool valid_parse) {
119 if (!valid_parse) {
120 if (!callback.is_null()) {
121 content::BrowserThread::PostTask(
122 content::BrowserThread::IO,
123 FROM_HERE,
124 base::Bind(callback, base::PLATFORM_FILE_ERROR_IO, EntryList(),
125 false));
127 return;
129 NativeMediaFileUtil::ReadDirectoryOnTaskRunnerThread(context.Pass(), url,
130 callback);
133 void IPhotoFileUtil::CreateSnapshotFileWithFreshDataProvider(
134 scoped_ptr<fileapi::FileSystemOperationContext> context,
135 const fileapi::FileSystemURL& url,
136 const CreateSnapshotFileCallback& callback,
137 bool valid_parse) {
138 if (!valid_parse) {
139 if (!callback.is_null()) {
140 base::PlatformFileInfo file_info;
141 base::FilePath platform_path;
142 scoped_refptr<webkit_blob::ShareableFileReference> file_ref;
143 content::BrowserThread::PostTask(
144 content::BrowserThread::IO,
145 FROM_HERE,
146 base::Bind(callback, base::PLATFORM_FILE_ERROR_IO, file_info,
147 platform_path, file_ref));
149 return;
151 NativeMediaFileUtil::CreateSnapshotFileOnTaskRunnerThread(context.Pass(), url,
152 callback);
155 // Begin actual implementation.
157 base::PlatformFileError IPhotoFileUtil::GetFileInfoSync(
158 fileapi::FileSystemOperationContext* context,
159 const fileapi::FileSystemURL& url,
160 base::PlatformFileInfo* file_info,
161 base::FilePath* platform_path) {
162 std::vector<std::string> components;
163 fileapi::VirtualPath::GetComponentsUTF8Unsafe(url.path(), &components);
165 if (components.size() == 0) {
166 return MakeDirectoryFileInfo(file_info);
169 // The 'Albums' directory.
170 if (components[0] == kIPhotoAlbumsDir) {
171 if (components.size() == 1) {
172 return MakeDirectoryFileInfo(file_info);
173 } else if (components.size() == 2) {
174 std::vector<std::string> albums =
175 GetDataProvider()->GetAlbumNames();
176 if (ContainsElement(albums, components[1]))
177 return MakeDirectoryFileInfo(file_info);
178 } else if (components.size() == 3) {
179 if (components[2] == kIPhotoOriginalsDir) {
180 if (GetDataProvider()->HasOriginals(components[1]))
181 return MakeDirectoryFileInfo(file_info);
182 else
183 return base::PLATFORM_FILE_ERROR_NOT_FOUND;
186 base::FilePath location = GetDataProvider()->GetPhotoLocationInAlbum(
187 components[1], components[2]);
188 if (!location.empty()) {
189 return NativeMediaFileUtil::GetFileInfoSync(
190 context, url, file_info, platform_path);
192 } else if (components.size() == 4 &&
193 GetDataProvider()->HasOriginals(components[1]) &&
194 components[2] == kIPhotoOriginalsDir) {
195 base::FilePath location = GetDataProvider()->GetOriginalPhotoLocation(
196 components[1], components[3]);
197 if (!location.empty()) {
198 return NativeMediaFileUtil::GetFileInfoSync(
199 context, url, file_info, platform_path);
204 return base::PLATFORM_FILE_ERROR_NOT_FOUND;
207 base::PlatformFileError IPhotoFileUtil::ReadDirectorySync(
208 fileapi::FileSystemOperationContext* context,
209 const fileapi::FileSystemURL& url,
210 EntryList* file_list) {
211 DCHECK(file_list->empty());
212 std::vector<std::string> components;
213 fileapi::VirtualPath::GetComponentsUTF8Unsafe(url.path(), &components);
215 // Root directory. Child is the /Albums dir.
216 if (components.size() == 0) {
217 file_list->push_back(DirectoryEntry(kIPhotoAlbumsDir,
218 DirectoryEntry::DIRECTORY,
219 0, base::Time()));
220 return base::PLATFORM_FILE_OK;
223 if (components[0] == kIPhotoAlbumsDir) {
224 if (components.size() == 1) {
225 // Albums dir contains all album names.
226 std::vector<std::string> albums =
227 GetDataProvider()->GetAlbumNames();
228 for (std::vector<std::string>::const_iterator it = albums.begin();
229 it != albums.end(); it++) {
230 file_list->push_back(DirectoryEntry(*it, DirectoryEntry::DIRECTORY,
231 0, base::Time()));
233 return base::PLATFORM_FILE_OK;
234 } else if (components.size() == 2) {
235 std::vector<std::string> albums =
236 GetDataProvider()->GetAlbumNames();
237 if (!ContainsElement(albums, components[1]))
238 return base::PLATFORM_FILE_ERROR_NOT_FOUND;
240 // Album dirs contain all photos in them.
241 if (GetDataProvider()->HasOriginals(components[1])) {
242 file_list->push_back(DirectoryEntry(kIPhotoOriginalsDir,
243 DirectoryEntry::DIRECTORY,
244 0, base::Time()));
246 std::map<std::string, base::FilePath> locations =
247 GetDataProvider()->GetAlbumContents(components[1]);
248 for (std::map<std::string, base::FilePath>::const_iterator it =
249 locations.begin();
250 it != locations.end(); it++) {
251 base::File::Info info;
252 if (!base::GetFileInfo(it->second, &info))
253 return base::PLATFORM_FILE_ERROR_IO;
254 file_list->push_back(DirectoryEntry(it->first, DirectoryEntry::FILE,
255 info.size, info.last_modified));
257 return base::PLATFORM_FILE_OK;
258 } else if (components.size() == 3 &&
259 components[2] == kIPhotoOriginalsDir &&
260 GetDataProvider()->HasOriginals(components[1])) {
261 std::map<std::string, base::FilePath> originals =
262 GetDataProvider()->GetOriginals(components[1]);
263 for (std::map<std::string, base::FilePath>::const_iterator it =
264 originals.begin();
265 it != originals.end(); it++) {
266 base::File::Info info;
267 if (!base::GetFileInfo(it->second, &info))
268 return base::PLATFORM_FILE_ERROR_IO;
269 file_list->push_back(DirectoryEntry(it->first, DirectoryEntry::FILE,
270 info.size, info.last_modified));
272 return base::PLATFORM_FILE_OK;
276 return base::PLATFORM_FILE_ERROR_NOT_FOUND;
279 base::PlatformFileError IPhotoFileUtil::DeleteDirectorySync(
280 fileapi::FileSystemOperationContext* context,
281 const fileapi::FileSystemURL& url) {
282 return base::PLATFORM_FILE_ERROR_SECURITY;
285 base::PlatformFileError IPhotoFileUtil::DeleteFileSync(
286 fileapi::FileSystemOperationContext* context,
287 const fileapi::FileSystemURL& url) {
288 return base::PLATFORM_FILE_ERROR_SECURITY;
292 base::PlatformFileError IPhotoFileUtil::GetLocalFilePath(
293 fileapi::FileSystemOperationContext* context,
294 const fileapi::FileSystemURL& url,
295 base::FilePath* local_file_path) {
296 std::vector<std::string> components;
297 fileapi::VirtualPath::GetComponentsUTF8Unsafe(url.path(), &components);
299 if (components.size() == 3 && components[0] == kIPhotoAlbumsDir) {
300 base::FilePath location = GetDataProvider()->GetPhotoLocationInAlbum(
301 components[1], components[2]);
302 if (!location.empty()) {
303 *local_file_path = location;
304 return base::PLATFORM_FILE_OK;
308 if (components.size() == 4 && components[0] == kIPhotoAlbumsDir &&
309 GetDataProvider()->HasOriginals(components[1]) &&
310 components[2] == kIPhotoOriginalsDir) {
311 base::FilePath location = GetDataProvider()->GetOriginalPhotoLocation(
312 components[1], components[3]);
313 if (!location.empty()) {
314 *local_file_path = location;
315 return base::PLATFORM_FILE_OK;
319 return base::PLATFORM_FILE_ERROR_NOT_FOUND;
322 IPhotoDataProvider* IPhotoFileUtil::GetDataProvider() {
323 if (!imported_registry_)
324 imported_registry_ = ImportedMediaGalleryRegistry::GetInstance();
325 return imported_registry_->IPhotoDataProvider();
328 } // namespace iphoto