- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / media_galleries / fileapi / native_media_file_util.cc
1 // Copyright (c) 2012 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.
4
5 #include "chrome/browser/media_galleries/fileapi/native_media_file_util.h"
6
7 #include <string>
8
9 #include "base/bind.h"
10 #include "base/bind_helpers.h"
11 #include "base/file_util.h"
12 #include "base/files/file_enumerator.h"
13 #include "base/files/scoped_platform_file_closer.h"
14 #include "base/strings/string_util.h"
15 #include "base/task_runner_util.h"
16 #include "chrome/browser/media_galleries/fileapi/media_path_filter.h"
17 #include "content/public/browser/browser_thread.h"
18 #include "net/base/mime_sniffer.h"
19 #include "url/gurl.h"
20 #include "webkit/browser/fileapi/file_system_context.h"
21 #include "webkit/browser/fileapi/file_system_operation_context.h"
22 #include "webkit/browser/fileapi/native_file_util.h"
23 #include "webkit/common/blob/shareable_file_reference.h"
24
25 namespace {
26
27 // Used to skip the hidden folders and files. Returns true if the file specified
28 // by |path| should be skipped.
29 bool ShouldSkip(const base::FilePath& path) {
30   const base::FilePath::StringType base_name = path.BaseName().value();
31   if (base_name.empty())
32     return false;
33
34   // Dot files (aka hidden files)
35   if (base_name[0] == '.')
36     return true;
37
38   // Mac OS X file.
39   if (base_name == FILE_PATH_LITERAL("__MACOSX"))
40     return true;
41
42 #if defined(OS_WIN)
43   DWORD file_attributes = ::GetFileAttributes(path.value().c_str());
44   if ((file_attributes != INVALID_FILE_ATTRIBUTES) &&
45       ((file_attributes & FILE_ATTRIBUTE_HIDDEN) != 0))
46     return true;
47 #else
48   // Windows always creates a recycle bin folder in the attached device to store
49   // all the deleted contents. On non-windows operating systems, there is no way
50   // to get the hidden attribute of windows recycle bin folders that are present
51   // on the attached device. Therefore, compare the file path name to the
52   // recycle bin name and exclude those folders. For more details, please refer
53   // to http://support.microsoft.com/kb/171694.
54   const char win_98_recycle_bin_name[] = "RECYCLED";
55   const char win_xp_recycle_bin_name[] = "RECYCLER";
56   const char win_vista_recycle_bin_name[] = "$Recycle.bin";
57   if ((base::strncasecmp(base_name.c_str(),
58                          win_98_recycle_bin_name,
59                          strlen(win_98_recycle_bin_name)) == 0) ||
60       (base::strncasecmp(base_name.c_str(),
61                          win_xp_recycle_bin_name,
62                          strlen(win_xp_recycle_bin_name)) == 0) ||
63       (base::strncasecmp(base_name.c_str(),
64                          win_vista_recycle_bin_name,
65                          strlen(win_vista_recycle_bin_name)) == 0))
66     return true;
67 #endif
68   return false;
69 }
70
71 // Returns true if the current thread is capable of doing IO.
72 bool IsOnTaskRunnerThread(fileapi::FileSystemOperationContext* context) {
73   return context->task_runner()->RunsTasksOnCurrentThread();
74 }
75
76 }  // namespace
77
78 NativeMediaFileUtil::NativeMediaFileUtil(MediaPathFilter* media_path_filter)
79     : media_path_filter_(media_path_filter),
80       weak_factory_(this) {
81 }
82
83 NativeMediaFileUtil::~NativeMediaFileUtil() {
84 }
85
86 // static
87 base::PlatformFileError NativeMediaFileUtil::IsMediaFile(
88     const base::FilePath& path) {
89   base::PlatformFile file_handle;
90   const int flags = base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ;
91   base::PlatformFileError error =
92       fileapi::NativeFileUtil::CreateOrOpen(path, flags, &file_handle, NULL);
93   if (error != base::PLATFORM_FILE_OK)
94     return error;
95
96   base::ScopedPlatformFileCloser scoped_platform_file(&file_handle);
97   char buffer[net::kMaxBytesToSniff];
98
99   // Read as much as net::SniffMimeTypeFromLocalData() will bother looking at.
100   int64 len =
101       base::ReadPlatformFile(file_handle, 0, buffer, net::kMaxBytesToSniff);
102   if (len < 0)
103     return base::PLATFORM_FILE_ERROR_FAILED;
104   if (len == 0)
105     return base::PLATFORM_FILE_ERROR_SECURITY;
106
107   std::string mime_type;
108   if (!net::SniffMimeTypeFromLocalData(buffer, len, &mime_type))
109     return base::PLATFORM_FILE_ERROR_SECURITY;
110
111   if (StartsWithASCII(mime_type, "image/", true) ||
112       StartsWithASCII(mime_type, "audio/", true) ||
113       StartsWithASCII(mime_type, "video/", true) ||
114       mime_type == "application/x-shockwave-flash") {
115     return base::PLATFORM_FILE_OK;
116   }
117   return base::PLATFORM_FILE_ERROR_SECURITY;
118 }
119
120 void NativeMediaFileUtil::CreateOrOpen(
121     scoped_ptr<fileapi::FileSystemOperationContext> context,
122     const fileapi::FileSystemURL& url,
123     int file_flags,
124     const CreateOrOpenCallback& callback) {
125   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
126   // Only called by NaCl, which should not have access to media file systems.
127   base::PlatformFile invalid_file(base::kInvalidPlatformFileValue);
128   callback.Run(base::PLATFORM_FILE_ERROR_SECURITY,
129                base::PassPlatformFile(&invalid_file),
130                base::Closure());
131 }
132
133 void NativeMediaFileUtil::EnsureFileExists(
134     scoped_ptr<fileapi::FileSystemOperationContext> context,
135     const fileapi::FileSystemURL& url,
136     const EnsureFileExistsCallback& callback) {
137   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
138   callback.Run(base::PLATFORM_FILE_ERROR_SECURITY, false);
139 }
140
141 void NativeMediaFileUtil::CreateDirectory(
142     scoped_ptr<fileapi::FileSystemOperationContext> context,
143     const fileapi::FileSystemURL& url,
144     bool exclusive,
145     bool recursive,
146     const StatusCallback& callback) {
147   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
148   fileapi::FileSystemOperationContext* context_ptr = context.get();
149   const bool success = context_ptr->task_runner()->PostTask(
150       FROM_HERE,
151       base::Bind(&NativeMediaFileUtil::CreateDirectoryOnTaskRunnerThread,
152                  weak_factory_.GetWeakPtr(), base::Passed(&context),
153                  url, exclusive, recursive, callback));
154   DCHECK(success);
155 }
156
157 void NativeMediaFileUtil::GetFileInfo(
158     scoped_ptr<fileapi::FileSystemOperationContext> context,
159     const fileapi::FileSystemURL& url,
160     const GetFileInfoCallback& callback) {
161   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
162   fileapi::FileSystemOperationContext* context_ptr = context.get();
163   const bool success = context_ptr->task_runner()->PostTask(
164       FROM_HERE,
165       base::Bind(&NativeMediaFileUtil::GetFileInfoOnTaskRunnerThread,
166                  weak_factory_.GetWeakPtr(), base::Passed(&context),
167                  url, callback));
168   DCHECK(success);
169 }
170
171 void NativeMediaFileUtil::ReadDirectory(
172     scoped_ptr<fileapi::FileSystemOperationContext> context,
173     const fileapi::FileSystemURL& url,
174     const ReadDirectoryCallback& callback) {
175   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
176   fileapi::FileSystemOperationContext* context_ptr = context.get();
177   const bool success = context_ptr->task_runner()->PostTask(
178       FROM_HERE,
179       base::Bind(&NativeMediaFileUtil::ReadDirectoryOnTaskRunnerThread,
180                  weak_factory_.GetWeakPtr(), base::Passed(&context),
181                  url, callback));
182   DCHECK(success);
183 }
184
185 void NativeMediaFileUtil::Touch(
186     scoped_ptr<fileapi::FileSystemOperationContext> context,
187     const fileapi::FileSystemURL& url,
188     const base::Time& last_access_time,
189     const base::Time& last_modified_time,
190     const StatusCallback& callback) {
191   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
192   callback.Run(base::PLATFORM_FILE_ERROR_SECURITY);
193 }
194
195 void NativeMediaFileUtil::Truncate(
196     scoped_ptr<fileapi::FileSystemOperationContext> context,
197     const fileapi::FileSystemURL& url,
198     int64 length,
199     const StatusCallback& callback) {
200   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
201   callback.Run(base::PLATFORM_FILE_ERROR_SECURITY);
202 }
203
204 void NativeMediaFileUtil::CopyFileLocal(
205     scoped_ptr<fileapi::FileSystemOperationContext> context,
206     const fileapi::FileSystemURL& src_url,
207     const fileapi::FileSystemURL& dest_url,
208     CopyOrMoveOption option,
209     const CopyFileProgressCallback& progress_callback,
210     const StatusCallback& callback) {
211   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
212   fileapi::FileSystemOperationContext* context_ptr = context.get();
213   const bool success = context_ptr->task_runner()->PostTask(
214       FROM_HERE,
215       base::Bind(&NativeMediaFileUtil::CopyOrMoveFileLocalOnTaskRunnerThread,
216                  weak_factory_.GetWeakPtr(), base::Passed(&context),
217                  src_url, dest_url, option, true /* copy */, callback));
218   DCHECK(success);
219 }
220
221 void NativeMediaFileUtil::MoveFileLocal(
222     scoped_ptr<fileapi::FileSystemOperationContext> context,
223     const fileapi::FileSystemURL& src_url,
224     const fileapi::FileSystemURL& dest_url,
225     CopyOrMoveOption option,
226     const StatusCallback& callback) {
227   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
228   fileapi::FileSystemOperationContext* context_ptr = context.get();
229   const bool success = context_ptr->task_runner()->PostTask(
230       FROM_HERE,
231       base::Bind(&NativeMediaFileUtil::CopyOrMoveFileLocalOnTaskRunnerThread,
232                  weak_factory_.GetWeakPtr(), base::Passed(&context),
233                  src_url, dest_url, option, false /* copy */, callback));
234   DCHECK(success);
235 }
236
237 void NativeMediaFileUtil::CopyInForeignFile(
238     scoped_ptr<fileapi::FileSystemOperationContext> context,
239     const base::FilePath& src_file_path,
240     const fileapi::FileSystemURL& dest_url,
241     const StatusCallback& callback) {
242   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
243   fileapi::FileSystemOperationContext* context_ptr = context.get();
244   const bool success = context_ptr->task_runner()->PostTask(
245       FROM_HERE,
246       base::Bind(&NativeMediaFileUtil::CopyInForeignFileOnTaskRunnerThread,
247                  weak_factory_.GetWeakPtr(), base::Passed(&context),
248                  src_file_path, dest_url, callback));
249   DCHECK(success);
250 }
251
252 void NativeMediaFileUtil::DeleteFile(
253     scoped_ptr<fileapi::FileSystemOperationContext> context,
254     const fileapi::FileSystemURL& url,
255     const StatusCallback& callback) {
256   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
257   callback.Run(base::PLATFORM_FILE_ERROR_SECURITY);
258 }
259
260 // This is needed to support Copy and Move.
261 void NativeMediaFileUtil::DeleteDirectory(
262     scoped_ptr<fileapi::FileSystemOperationContext> context,
263     const fileapi::FileSystemURL& url,
264     const StatusCallback& callback) {
265   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
266   fileapi::FileSystemOperationContext* context_ptr = context.get();
267   const bool success = context_ptr->task_runner()->PostTask(
268       FROM_HERE,
269       base::Bind(&NativeMediaFileUtil::DeleteDirectoryOnTaskRunnerThread,
270                  weak_factory_.GetWeakPtr(), base::Passed(&context),
271                  url, callback));
272   DCHECK(success);
273 }
274
275 void NativeMediaFileUtil::DeleteRecursively(
276     scoped_ptr<fileapi::FileSystemOperationContext> context,
277     const fileapi::FileSystemURL& url,
278     const StatusCallback& callback) {
279   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
280   callback.Run(base::PLATFORM_FILE_ERROR_INVALID_OPERATION);
281 }
282
283 void NativeMediaFileUtil::CreateSnapshotFile(
284     scoped_ptr<fileapi::FileSystemOperationContext> context,
285     const fileapi::FileSystemURL& url,
286     const CreateSnapshotFileCallback& callback) {
287   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
288   fileapi::FileSystemOperationContext* context_ptr = context.get();
289   const bool success = context_ptr->task_runner()->PostTask(
290       FROM_HERE,
291       base::Bind(&NativeMediaFileUtil::CreateSnapshotFileOnTaskRunnerThread,
292                  weak_factory_.GetWeakPtr(), base::Passed(&context),
293                  url, callback));
294   DCHECK(success);
295 }
296
297 void NativeMediaFileUtil::CreateDirectoryOnTaskRunnerThread(
298     scoped_ptr<fileapi::FileSystemOperationContext> context,
299     const fileapi::FileSystemURL& url,
300     bool exclusive,
301     bool recursive,
302     const StatusCallback& callback) {
303   DCHECK(IsOnTaskRunnerThread(context.get()));
304   base::PlatformFileError error =
305       CreateDirectorySync(context.get(), url, exclusive, recursive);
306   content::BrowserThread::PostTask(
307       content::BrowserThread::IO,
308       FROM_HERE,
309       base::Bind(callback, error));
310 }
311
312 void NativeMediaFileUtil::GetFileInfoOnTaskRunnerThread(
313     scoped_ptr<fileapi::FileSystemOperationContext> context,
314     const fileapi::FileSystemURL& url,
315     const GetFileInfoCallback& callback) {
316   DCHECK(IsOnTaskRunnerThread(context.get()));
317   base::PlatformFileInfo file_info;
318   base::PlatformFileError error =
319       GetFileInfoSync(context.get(), url, &file_info, NULL);
320   content::BrowserThread::PostTask(
321       content::BrowserThread::IO,
322       FROM_HERE,
323       base::Bind(callback, error, file_info));
324 }
325
326 void NativeMediaFileUtil::ReadDirectoryOnTaskRunnerThread(
327     scoped_ptr<fileapi::FileSystemOperationContext> context,
328     const fileapi::FileSystemURL& url,
329     const ReadDirectoryCallback& callback) {
330   DCHECK(IsOnTaskRunnerThread(context.get()));
331   EntryList entry_list;
332   base::PlatformFileError error =
333       ReadDirectorySync(context.get(), url, &entry_list);
334   content::BrowserThread::PostTask(
335       content::BrowserThread::IO,
336       FROM_HERE,
337       base::Bind(callback, error, entry_list, false /* has_more */));
338 }
339
340 void NativeMediaFileUtil::CopyOrMoveFileLocalOnTaskRunnerThread(
341     scoped_ptr<fileapi::FileSystemOperationContext> context,
342     const fileapi::FileSystemURL& src_url,
343     const fileapi::FileSystemURL& dest_url,
344     CopyOrMoveOption option,
345     bool copy,
346     const StatusCallback& callback) {
347   DCHECK(IsOnTaskRunnerThread(context.get()));
348   base::PlatformFileError error =
349       CopyOrMoveFileSync(context.get(), src_url, dest_url, option, copy);
350   content::BrowserThread::PostTask(
351       content::BrowserThread::IO,
352       FROM_HERE,
353       base::Bind(callback, error));
354 }
355
356 void NativeMediaFileUtil::CopyInForeignFileOnTaskRunnerThread(
357     scoped_ptr<fileapi::FileSystemOperationContext> context,
358     const base::FilePath& src_file_path,
359     const fileapi::FileSystemURL& dest_url,
360     const StatusCallback& callback) {
361   DCHECK(IsOnTaskRunnerThread(context.get()));
362   base::PlatformFileError error =
363       CopyInForeignFileSync(context.get(), src_file_path, dest_url);
364   content::BrowserThread::PostTask(
365       content::BrowserThread::IO,
366       FROM_HERE,
367       base::Bind(callback, error));
368 }
369
370 void NativeMediaFileUtil::DeleteDirectoryOnTaskRunnerThread(
371     scoped_ptr<fileapi::FileSystemOperationContext> context,
372     const fileapi::FileSystemURL& url,
373     const StatusCallback& callback) {
374   DCHECK(IsOnTaskRunnerThread(context.get()));
375   base::PlatformFileError error = DeleteDirectorySync(context.get(), url);
376   content::BrowserThread::PostTask(
377       content::BrowserThread::IO,
378       FROM_HERE,
379       base::Bind(callback, error));
380 }
381
382 void NativeMediaFileUtil::CreateSnapshotFileOnTaskRunnerThread(
383     scoped_ptr<fileapi::FileSystemOperationContext> context,
384     const fileapi::FileSystemURL& url,
385     const CreateSnapshotFileCallback& callback) {
386   DCHECK(IsOnTaskRunnerThread(context.get()));
387   base::PlatformFileInfo file_info;
388   base::FilePath platform_path;
389   scoped_refptr<webkit_blob::ShareableFileReference> file_ref;
390   base::PlatformFileError error =
391       CreateSnapshotFileSync(context.get(), url, &file_info, &platform_path,
392                              &file_ref);
393   content::BrowserThread::PostTask(
394       content::BrowserThread::IO,
395       FROM_HERE,
396       base::Bind(callback, error, file_info, platform_path, file_ref));
397 }
398
399 base::PlatformFileError NativeMediaFileUtil::CreateDirectorySync(
400     fileapi::FileSystemOperationContext* context,
401     const fileapi::FileSystemURL& url,
402     bool exclusive,
403     bool recursive) {
404   base::FilePath file_path;
405   base::PlatformFileError error = GetLocalFilePath(context, url, &file_path);
406   if (error != base::PLATFORM_FILE_OK)
407     return error;
408   return fileapi::NativeFileUtil::CreateDirectory(file_path, exclusive,
409                                                   recursive);
410 }
411
412 base::PlatformFileError NativeMediaFileUtil::CopyOrMoveFileSync(
413     fileapi::FileSystemOperationContext* context,
414     const fileapi::FileSystemURL& src_url,
415     const fileapi::FileSystemURL& dest_url,
416     CopyOrMoveOption option,
417     bool copy) {
418   DCHECK(IsOnTaskRunnerThread(context));
419   base::FilePath src_file_path;
420   base::PlatformFileError error =
421       GetFilteredLocalFilePathForExistingFileOrDirectory(
422           context, src_url,
423           base::PLATFORM_FILE_ERROR_NOT_FOUND,
424           &src_file_path);
425   if (error != base::PLATFORM_FILE_OK)
426     return error;
427   if (fileapi::NativeFileUtil::DirectoryExists(src_file_path))
428     return base::PLATFORM_FILE_ERROR_NOT_A_FILE;
429
430   base::FilePath dest_file_path;
431   error = GetLocalFilePath(context, dest_url, &dest_file_path);
432   if (error != base::PLATFORM_FILE_OK)
433     return error;
434   base::PlatformFileInfo file_info;
435   error = fileapi::NativeFileUtil::GetFileInfo(dest_file_path, &file_info);
436   if (error != base::PLATFORM_FILE_OK &&
437       error != base::PLATFORM_FILE_ERROR_NOT_FOUND)
438     return error;
439   if (error == base::PLATFORM_FILE_OK && file_info.is_directory)
440     return base::PLATFORM_FILE_ERROR_INVALID_OPERATION;
441   if (!media_path_filter_->Match(dest_file_path))
442     return base::PLATFORM_FILE_ERROR_SECURITY;
443
444   return fileapi::NativeFileUtil::CopyOrMoveFile(
445       src_file_path, dest_file_path, option, copy);
446 }
447
448 base::PlatformFileError NativeMediaFileUtil::CopyInForeignFileSync(
449     fileapi::FileSystemOperationContext* context,
450     const base::FilePath& src_file_path,
451     const fileapi::FileSystemURL& dest_url) {
452   DCHECK(IsOnTaskRunnerThread(context));
453   if (src_file_path.empty())
454     return base::PLATFORM_FILE_ERROR_INVALID_OPERATION;
455
456   base::FilePath dest_file_path;
457   base::PlatformFileError error =
458       GetFilteredLocalFilePath(context, dest_url, &dest_file_path);
459   if (error != base::PLATFORM_FILE_OK)
460     return error;
461   return fileapi::NativeFileUtil::CopyOrMoveFile(
462       src_file_path, dest_file_path,
463       fileapi::FileSystemOperation::OPTION_NONE, true);
464 }
465
466 base::PlatformFileError NativeMediaFileUtil::GetFileInfoSync(
467     fileapi::FileSystemOperationContext* context,
468     const fileapi::FileSystemURL& url,
469     base::PlatformFileInfo* file_info,
470     base::FilePath* platform_path) {
471   DCHECK(context);
472   DCHECK(IsOnTaskRunnerThread(context));
473   DCHECK(file_info);
474
475   base::FilePath file_path;
476   base::PlatformFileError error = GetLocalFilePath(context, url, &file_path);
477   if (error != base::PLATFORM_FILE_OK)
478     return error;
479   if (file_util::IsLink(file_path))
480     return base::PLATFORM_FILE_ERROR_NOT_FOUND;
481   error = fileapi::NativeFileUtil::GetFileInfo(file_path, file_info);
482   if (error != base::PLATFORM_FILE_OK)
483     return error;
484
485   if (platform_path)
486     *platform_path = file_path;
487   if (file_info->is_directory ||
488       media_path_filter_->Match(file_path)) {
489     return base::PLATFORM_FILE_OK;
490   }
491   return base::PLATFORM_FILE_ERROR_NOT_FOUND;
492 }
493
494 base::PlatformFileError NativeMediaFileUtil::GetLocalFilePath(
495     fileapi::FileSystemOperationContext* context,
496     const fileapi::FileSystemURL& url,
497     base::FilePath* local_file_path) {
498   DCHECK(local_file_path);
499   DCHECK(url.is_valid());
500   if (url.path().empty()) {
501     // Root direcory case, which should not be accessed.
502     return base::PLATFORM_FILE_ERROR_ACCESS_DENIED;
503   }
504   *local_file_path = url.path();
505   return base::PLATFORM_FILE_OK;
506 }
507
508 base::PlatformFileError NativeMediaFileUtil::ReadDirectorySync(
509       fileapi::FileSystemOperationContext* context,
510       const fileapi::FileSystemURL& url,
511       EntryList* file_list) {
512   DCHECK(IsOnTaskRunnerThread(context));
513   DCHECK(file_list);
514   DCHECK(file_list->empty());
515   base::PlatformFileInfo file_info;
516   base::FilePath dir_path;
517   base::PlatformFileError error =
518       GetFileInfoSync(context, url, &file_info, &dir_path);
519
520   if (error != base::PLATFORM_FILE_OK)
521     return error;
522
523   if (!file_info.is_directory)
524     return base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY;
525
526   base::FileEnumerator file_enum(
527       dir_path,
528       false /* recursive */,
529       base::FileEnumerator::FILES | base::FileEnumerator::DIRECTORIES);
530   for (base::FilePath enum_path = file_enum.Next();
531        !enum_path.empty();
532        enum_path = file_enum.Next()) {
533     // Skip symlinks.
534     if (file_util::IsLink(enum_path))
535       continue;
536
537     base::FileEnumerator::FileInfo info = file_enum.GetInfo();
538
539     // NativeMediaFileUtil skip criteria.
540     if (ShouldSkip(enum_path))
541       continue;
542     if (!info.IsDirectory() && !media_path_filter_->Match(enum_path))
543       continue;
544
545     fileapi::DirectoryEntry entry;
546     entry.is_directory = info.IsDirectory();
547     entry.name = enum_path.BaseName().value();
548     entry.size = info.GetSize();
549     entry.last_modified_time = info.GetLastModifiedTime();
550
551     file_list->push_back(entry);
552   }
553
554   return base::PLATFORM_FILE_OK;
555 }
556
557 base::PlatformFileError NativeMediaFileUtil::DeleteDirectorySync(
558     fileapi::FileSystemOperationContext* context,
559     const fileapi::FileSystemURL& url) {
560   DCHECK(IsOnTaskRunnerThread(context));
561   base::FilePath file_path;
562   base::PlatformFileError error = GetLocalFilePath(context, url, &file_path);
563   if (error != base::PLATFORM_FILE_OK)
564     return error;
565   return fileapi::NativeFileUtil::DeleteDirectory(file_path);
566 }
567
568 base::PlatformFileError NativeMediaFileUtil::CreateSnapshotFileSync(
569     fileapi::FileSystemOperationContext* context,
570     const fileapi::FileSystemURL& url,
571     base::PlatformFileInfo* file_info,
572     base::FilePath* platform_path,
573     scoped_refptr<webkit_blob::ShareableFileReference>* file_ref) {
574   DCHECK(IsOnTaskRunnerThread(context));
575   base::PlatformFileError error =
576       GetFileInfoSync(context, url, file_info, platform_path);
577   if (error == base::PLATFORM_FILE_OK && file_info->is_directory)
578     error = base::PLATFORM_FILE_ERROR_NOT_A_FILE;
579   if (error == base::PLATFORM_FILE_OK)
580     error = NativeMediaFileUtil::IsMediaFile(*platform_path);
581
582   // We're just returning the local file information.
583   *file_ref = scoped_refptr<webkit_blob::ShareableFileReference>();
584
585   return error;
586 }
587
588 base::PlatformFileError NativeMediaFileUtil::GetFilteredLocalFilePath(
589     fileapi::FileSystemOperationContext* context,
590     const fileapi::FileSystemURL& file_system_url,
591     base::FilePath* local_file_path) {
592   DCHECK(IsOnTaskRunnerThread(context));
593   base::FilePath file_path;
594   base::PlatformFileError error =
595       GetLocalFilePath(context, file_system_url, &file_path);
596   if (error != base::PLATFORM_FILE_OK)
597     return error;
598   if (!media_path_filter_->Match(file_path))
599     return base::PLATFORM_FILE_ERROR_SECURITY;
600
601   *local_file_path = file_path;
602   return base::PLATFORM_FILE_OK;
603 }
604
605 base::PlatformFileError
606 NativeMediaFileUtil::GetFilteredLocalFilePathForExistingFileOrDirectory(
607     fileapi::FileSystemOperationContext* context,
608     const fileapi::FileSystemURL& file_system_url,
609     base::PlatformFileError failure_error,
610     base::FilePath* local_file_path) {
611   DCHECK(IsOnTaskRunnerThread(context));
612   base::FilePath file_path;
613   base::PlatformFileError error =
614       GetLocalFilePath(context, file_system_url, &file_path);
615   if (error != base::PLATFORM_FILE_OK)
616     return error;
617
618   if (!base::PathExists(file_path))
619     return failure_error;
620   base::PlatformFileInfo file_info;
621   if (!file_util::GetFileInfo(file_path, &file_info))
622     return base::PLATFORM_FILE_ERROR_FAILED;
623
624   if (!file_info.is_directory &&
625       !media_path_filter_->Match(file_path)) {
626     return failure_error;
627   }
628
629   *local_file_path = file_path;
630   return base::PLATFORM_FILE_OK;
631 }