NaCl: Update revision in DEPS, r12770 -> r12773
[chromium-blink-merge.git] / chrome / browser / media_galleries / fileapi / iphoto_file_util.cc
blobf35595720bd872d3cacf83abd4a41e353d5fc614
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::File::Error MakeDirectoryFileInfo(base::File::Info* file_info) {
33 base::File::Info result;
34 result.is_directory = true;
35 *file_info = result;
36 return base::File::FILE_OK;
39 template <typename T>
40 bool ContainsElement(const std::vector<T>& collection, const T& key) {
41 typename std::vector<T>::const_iterator it = collection.begin();
42 while (it != collection.end()) {
43 if (*it == key)
44 return true;
45 it++;
47 return false;
50 } // namespace
52 const char kIPhotoAlbumsDir[] = "Albums";
53 const char kIPhotoOriginalsDir[] = "Originals";
55 IPhotoFileUtil::IPhotoFileUtil(MediaPathFilter* media_path_filter)
56 : NativeMediaFileUtil(media_path_filter),
57 weak_factory_(this),
58 imported_registry_(NULL) {
61 IPhotoFileUtil::~IPhotoFileUtil() {
64 void IPhotoFileUtil::GetFileInfoOnTaskRunnerThread(
65 scoped_ptr<fileapi::FileSystemOperationContext> context,
66 const fileapi::FileSystemURL& url,
67 const GetFileInfoCallback& callback) {
68 GetDataProvider()->RefreshData(
69 base::Bind(&IPhotoFileUtil::GetFileInfoWithFreshDataProvider,
70 weak_factory_.GetWeakPtr(), base::Passed(&context), url,
71 callback));
74 void IPhotoFileUtil::ReadDirectoryOnTaskRunnerThread(
75 scoped_ptr<fileapi::FileSystemOperationContext> context,
76 const fileapi::FileSystemURL& url,
77 const ReadDirectoryCallback& callback) {
78 GetDataProvider()->RefreshData(
79 base::Bind(&IPhotoFileUtil::ReadDirectoryWithFreshDataProvider,
80 weak_factory_.GetWeakPtr(), base::Passed(&context), url,
81 callback));
84 void IPhotoFileUtil::CreateSnapshotFileOnTaskRunnerThread(
85 scoped_ptr<fileapi::FileSystemOperationContext> context,
86 const fileapi::FileSystemURL& url,
87 const CreateSnapshotFileCallback& callback) {
88 GetDataProvider()->RefreshData(
89 base::Bind(&IPhotoFileUtil::CreateSnapshotFileWithFreshDataProvider,
90 weak_factory_.GetWeakPtr(), base::Passed(&context), url,
91 callback));
94 void IPhotoFileUtil::GetFileInfoWithFreshDataProvider(
95 scoped_ptr<fileapi::FileSystemOperationContext> context,
96 const fileapi::FileSystemURL& url,
97 const GetFileInfoCallback& callback,
98 bool valid_parse) {
99 if (!valid_parse) {
100 if (!callback.is_null()) {
101 content::BrowserThread::PostTask(
102 content::BrowserThread::IO,
103 FROM_HERE,
104 base::Bind(callback, base::File::FILE_ERROR_IO, base::File::Info()));
106 return;
108 NativeMediaFileUtil::GetFileInfoOnTaskRunnerThread(context.Pass(), url,
109 callback);
112 void IPhotoFileUtil::ReadDirectoryWithFreshDataProvider(
113 scoped_ptr<fileapi::FileSystemOperationContext> context,
114 const fileapi::FileSystemURL& url,
115 const ReadDirectoryCallback& callback,
116 bool valid_parse) {
117 if (!valid_parse) {
118 if (!callback.is_null()) {
119 content::BrowserThread::PostTask(
120 content::BrowserThread::IO,
121 FROM_HERE,
122 base::Bind(callback, base::File::FILE_ERROR_IO, EntryList(), false));
124 return;
126 NativeMediaFileUtil::ReadDirectoryOnTaskRunnerThread(context.Pass(), url,
127 callback);
130 void IPhotoFileUtil::CreateSnapshotFileWithFreshDataProvider(
131 scoped_ptr<fileapi::FileSystemOperationContext> context,
132 const fileapi::FileSystemURL& url,
133 const CreateSnapshotFileCallback& callback,
134 bool valid_parse) {
135 if (!valid_parse) {
136 if (!callback.is_null()) {
137 base::File::Info file_info;
138 base::FilePath platform_path;
139 scoped_refptr<webkit_blob::ShareableFileReference> file_ref;
140 content::BrowserThread::PostTask(
141 content::BrowserThread::IO,
142 FROM_HERE,
143 base::Bind(callback, base::File::FILE_ERROR_IO, file_info,
144 platform_path, file_ref));
146 return;
148 NativeMediaFileUtil::CreateSnapshotFileOnTaskRunnerThread(context.Pass(), url,
149 callback);
152 // Begin actual implementation.
154 base::File::Error IPhotoFileUtil::GetFileInfoSync(
155 fileapi::FileSystemOperationContext* context,
156 const fileapi::FileSystemURL& url,
157 base::File::Info* file_info,
158 base::FilePath* platform_path) {
159 std::vector<std::string> components;
160 fileapi::VirtualPath::GetComponentsUTF8Unsafe(url.path(), &components);
162 if (components.size() == 0) {
163 return MakeDirectoryFileInfo(file_info);
166 // The 'Albums' directory.
167 if (components[0] == kIPhotoAlbumsDir) {
168 if (components.size() == 1) {
169 return MakeDirectoryFileInfo(file_info);
170 } else if (components.size() == 2) {
171 std::vector<std::string> albums =
172 GetDataProvider()->GetAlbumNames();
173 if (ContainsElement(albums, components[1]))
174 return MakeDirectoryFileInfo(file_info);
175 } else if (components.size() == 3) {
176 if (components[2] == kIPhotoOriginalsDir) {
177 if (GetDataProvider()->HasOriginals(components[1]))
178 return MakeDirectoryFileInfo(file_info);
179 else
180 return base::File::FILE_ERROR_NOT_FOUND;
183 base::FilePath location = GetDataProvider()->GetPhotoLocationInAlbum(
184 components[1], components[2]);
185 if (!location.empty()) {
186 return NativeMediaFileUtil::GetFileInfoSync(
187 context, url, file_info, platform_path);
189 } else if (components.size() == 4 &&
190 GetDataProvider()->HasOriginals(components[1]) &&
191 components[2] == kIPhotoOriginalsDir) {
192 base::FilePath location = GetDataProvider()->GetOriginalPhotoLocation(
193 components[1], components[3]);
194 if (!location.empty()) {
195 return NativeMediaFileUtil::GetFileInfoSync(
196 context, url, file_info, platform_path);
201 return base::File::FILE_ERROR_NOT_FOUND;
204 base::File::Error IPhotoFileUtil::ReadDirectorySync(
205 fileapi::FileSystemOperationContext* context,
206 const fileapi::FileSystemURL& url,
207 EntryList* file_list) {
208 DCHECK(file_list->empty());
209 std::vector<std::string> components;
210 fileapi::VirtualPath::GetComponentsUTF8Unsafe(url.path(), &components);
212 // Root directory. Child is the /Albums dir.
213 if (components.size() == 0) {
214 file_list->push_back(DirectoryEntry(kIPhotoAlbumsDir,
215 DirectoryEntry::DIRECTORY,
216 0, base::Time()));
217 return base::File::FILE_OK;
220 if (components[0] == kIPhotoAlbumsDir) {
221 if (components.size() == 1) {
222 // Albums dir contains all album names.
223 std::vector<std::string> albums =
224 GetDataProvider()->GetAlbumNames();
225 for (std::vector<std::string>::const_iterator it = albums.begin();
226 it != albums.end(); it++) {
227 file_list->push_back(DirectoryEntry(*it, DirectoryEntry::DIRECTORY,
228 0, base::Time()));
230 return base::File::FILE_OK;
231 } else if (components.size() == 2) {
232 std::vector<std::string> albums =
233 GetDataProvider()->GetAlbumNames();
234 if (!ContainsElement(albums, components[1]))
235 return base::File::FILE_ERROR_NOT_FOUND;
237 // Album dirs contain all photos in them.
238 if (GetDataProvider()->HasOriginals(components[1])) {
239 file_list->push_back(DirectoryEntry(kIPhotoOriginalsDir,
240 DirectoryEntry::DIRECTORY,
241 0, base::Time()));
243 std::map<std::string, base::FilePath> locations =
244 GetDataProvider()->GetAlbumContents(components[1]);
245 for (std::map<std::string, base::FilePath>::const_iterator it =
246 locations.begin();
247 it != locations.end(); it++) {
248 base::File::Info info;
249 if (!base::GetFileInfo(it->second, &info))
250 return base::File::FILE_ERROR_IO;
251 file_list->push_back(DirectoryEntry(it->first, DirectoryEntry::FILE,
252 info.size, info.last_modified));
254 return base::File::FILE_OK;
255 } else if (components.size() == 3 &&
256 components[2] == kIPhotoOriginalsDir &&
257 GetDataProvider()->HasOriginals(components[1])) {
258 std::map<std::string, base::FilePath> originals =
259 GetDataProvider()->GetOriginals(components[1]);
260 for (std::map<std::string, base::FilePath>::const_iterator it =
261 originals.begin();
262 it != originals.end(); it++) {
263 base::File::Info info;
264 if (!base::GetFileInfo(it->second, &info))
265 return base::File::FILE_ERROR_IO;
266 file_list->push_back(DirectoryEntry(it->first, DirectoryEntry::FILE,
267 info.size, info.last_modified));
269 return base::File::FILE_OK;
273 return base::File::FILE_ERROR_NOT_FOUND;
276 base::File::Error IPhotoFileUtil::DeleteDirectorySync(
277 fileapi::FileSystemOperationContext* context,
278 const fileapi::FileSystemURL& url) {
279 return base::File::FILE_ERROR_SECURITY;
282 base::File::Error IPhotoFileUtil::DeleteFileSync(
283 fileapi::FileSystemOperationContext* context,
284 const fileapi::FileSystemURL& url) {
285 return base::File::FILE_ERROR_SECURITY;
289 base::File::Error IPhotoFileUtil::GetLocalFilePath(
290 fileapi::FileSystemOperationContext* context,
291 const fileapi::FileSystemURL& url,
292 base::FilePath* local_file_path) {
293 std::vector<std::string> components;
294 fileapi::VirtualPath::GetComponentsUTF8Unsafe(url.path(), &components);
296 if (components.size() == 3 && components[0] == kIPhotoAlbumsDir) {
297 base::FilePath location = GetDataProvider()->GetPhotoLocationInAlbum(
298 components[1], components[2]);
299 if (!location.empty()) {
300 *local_file_path = location;
301 return base::File::FILE_OK;
305 if (components.size() == 4 && components[0] == kIPhotoAlbumsDir &&
306 GetDataProvider()->HasOriginals(components[1]) &&
307 components[2] == kIPhotoOriginalsDir) {
308 base::FilePath location = GetDataProvider()->GetOriginalPhotoLocation(
309 components[1], components[3]);
310 if (!location.empty()) {
311 *local_file_path = location;
312 return base::File::FILE_OK;
316 return base::File::FILE_ERROR_NOT_FOUND;
319 IPhotoDataProvider* IPhotoFileUtil::GetDataProvider() {
320 if (!imported_registry_)
321 imported_registry_ = ImportedMediaGalleryRegistry::GetInstance();
322 return imported_registry_->IPhotoDataProvider();
325 } // namespace iphoto