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.
5 #include "chrome/browser/media_galleries/fileapi/native_media_file_util.h"
10 #include "base/bind_helpers.h"
11 #include "base/files/file_enumerator.h"
12 #include "base/files/file_util.h"
13 #include "base/strings/string_util.h"
14 #include "base/task_runner_util.h"
15 #include "chrome/browser/media_galleries/fileapi/media_path_filter.h"
16 #include "content/public/browser/browser_thread.h"
17 #include "net/base/io_buffer.h"
18 #include "net/base/mime_sniffer.h"
19 #include "storage/browser/blob/shareable_file_reference.h"
20 #include "storage/browser/fileapi/file_system_context.h"
21 #include "storage/browser/fileapi/file_system_operation_context.h"
22 #include "storage/browser/fileapi/native_file_util.h"
27 // Returns true if the current thread is capable of doing IO.
28 bool IsOnTaskRunnerThread(storage::FileSystemOperationContext
* context
) {
29 return context
->task_runner()->RunsTasksOnCurrentThread();
32 base::File::Error
IsMediaHeader(const char* buf
, size_t length
) {
34 return base::File::FILE_ERROR_SECURITY
;
36 std::string mime_type
;
37 if (!net::SniffMimeTypeFromLocalData(buf
, length
, &mime_type
))
38 return base::File::FILE_ERROR_SECURITY
;
40 if (StartsWithASCII(mime_type
, "image/", true) ||
41 StartsWithASCII(mime_type
, "audio/", true) ||
42 StartsWithASCII(mime_type
, "video/", true) ||
43 mime_type
== "application/x-shockwave-flash") {
44 return base::File::FILE_OK
;
46 return base::File::FILE_ERROR_SECURITY
;
50 const scoped_refptr
<storage::ShareableFileReference
>& file_ref
) {
54 const storage::AsyncFileUtil::CreateOrOpenCallback
& callback
,
55 const scoped_refptr
<storage::ShareableFileReference
>& file_ref
,
57 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO
));
58 if (!file
.IsValid()) {
59 callback
.Run(file
.Pass(), base::Closure());
62 callback
.Run(file
.Pass(), base::Bind(&HoldFileRef
, file_ref
));
67 NativeMediaFileUtil::NativeMediaFileUtil(MediaPathFilter
* media_path_filter
)
68 : media_path_filter_(media_path_filter
),
72 NativeMediaFileUtil::~NativeMediaFileUtil() {
76 base::File::Error
NativeMediaFileUtil::IsMediaFile(
77 const base::FilePath
& path
) {
78 base::File
file(path
, base::File::FLAG_OPEN
| base::File::FLAG_READ
);
80 return file
.error_details();
82 char buffer
[net::kMaxBytesToSniff
];
84 // Read as much as net::SniffMimeTypeFromLocalData() will bother looking at.
85 int64 len
= file
.Read(0, buffer
, net::kMaxBytesToSniff
);
87 return base::File::FILE_ERROR_FAILED
;
89 return IsMediaHeader(buffer
, len
);
93 base::File::Error
NativeMediaFileUtil::BufferIsMediaHeader(
94 net::IOBuffer
* buf
, size_t length
) {
95 return IsMediaHeader(buf
->data(), length
);
99 void NativeMediaFileUtil::CreatedSnapshotFileForCreateOrOpen(
100 base::SequencedTaskRunner
* media_task_runner
,
102 const storage::AsyncFileUtil::CreateOrOpenCallback
& callback
,
103 base::File::Error result
,
104 const base::File::Info
& file_info
,
105 const base::FilePath
& platform_path
,
106 const scoped_refptr
<storage::ShareableFileReference
>& file_ref
) {
107 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO
));
108 if (result
!= base::File::FILE_OK
) {
109 callback
.Run(base::File(), base::Closure());
112 base::PostTaskAndReplyWithResult(
116 &storage::NativeFileUtil::CreateOrOpen
, platform_path
, file_flags
),
117 base::Bind(&DidOpenSnapshot
, callback
, file_ref
));
120 void NativeMediaFileUtil::CreateOrOpen(
121 scoped_ptr
<storage::FileSystemOperationContext
> context
,
122 const storage::FileSystemURL
& url
,
124 const CreateOrOpenCallback
& callback
) {
125 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
126 // Returns an error if any unsupported flag is found.
127 if (file_flags
& ~(base::File::FLAG_OPEN
|
128 base::File::FLAG_READ
|
129 base::File::FLAG_WRITE_ATTRIBUTES
)) {
130 callback
.Run(base::File(base::File::FILE_ERROR_SECURITY
), base::Closure());
133 scoped_refptr
<base::SequencedTaskRunner
> task_runner
= context
->task_runner();
137 base::Bind(&NativeMediaFileUtil::CreatedSnapshotFileForCreateOrOpen
,
143 void NativeMediaFileUtil::EnsureFileExists(
144 scoped_ptr
<storage::FileSystemOperationContext
> context
,
145 const storage::FileSystemURL
& url
,
146 const EnsureFileExistsCallback
& callback
) {
147 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
148 callback
.Run(base::File::FILE_ERROR_SECURITY
, false);
151 void NativeMediaFileUtil::CreateDirectory(
152 scoped_ptr
<storage::FileSystemOperationContext
> context
,
153 const storage::FileSystemURL
& url
,
156 const StatusCallback
& callback
) {
157 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
158 storage::FileSystemOperationContext
* context_ptr
= context
.get();
159 const bool success
= context_ptr
->task_runner()->PostTask(
161 base::Bind(&NativeMediaFileUtil::CreateDirectoryOnTaskRunnerThread
,
162 weak_factory_
.GetWeakPtr(), base::Passed(&context
),
163 url
, exclusive
, recursive
, callback
));
167 void NativeMediaFileUtil::GetFileInfo(
168 scoped_ptr
<storage::FileSystemOperationContext
> context
,
169 const storage::FileSystemURL
& url
,
170 const GetFileInfoCallback
& callback
) {
171 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
172 storage::FileSystemOperationContext
* context_ptr
= context
.get();
173 const bool success
= context_ptr
->task_runner()->PostTask(
175 base::Bind(&NativeMediaFileUtil::GetFileInfoOnTaskRunnerThread
,
176 weak_factory_
.GetWeakPtr(), base::Passed(&context
),
181 void NativeMediaFileUtil::ReadDirectory(
182 scoped_ptr
<storage::FileSystemOperationContext
> context
,
183 const storage::FileSystemURL
& url
,
184 const ReadDirectoryCallback
& callback
) {
185 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
186 storage::FileSystemOperationContext
* context_ptr
= context
.get();
187 const bool success
= context_ptr
->task_runner()->PostTask(
189 base::Bind(&NativeMediaFileUtil::ReadDirectoryOnTaskRunnerThread
,
190 weak_factory_
.GetWeakPtr(), base::Passed(&context
),
195 void NativeMediaFileUtil::Touch(
196 scoped_ptr
<storage::FileSystemOperationContext
> context
,
197 const storage::FileSystemURL
& url
,
198 const base::Time
& last_access_time
,
199 const base::Time
& last_modified_time
,
200 const StatusCallback
& callback
) {
201 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
202 callback
.Run(base::File::FILE_ERROR_SECURITY
);
205 void NativeMediaFileUtil::Truncate(
206 scoped_ptr
<storage::FileSystemOperationContext
> context
,
207 const storage::FileSystemURL
& url
,
209 const StatusCallback
& callback
) {
210 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
211 callback
.Run(base::File::FILE_ERROR_SECURITY
);
214 void NativeMediaFileUtil::CopyFileLocal(
215 scoped_ptr
<storage::FileSystemOperationContext
> context
,
216 const storage::FileSystemURL
& src_url
,
217 const storage::FileSystemURL
& dest_url
,
218 CopyOrMoveOption option
,
219 const CopyFileProgressCallback
& progress_callback
,
220 const StatusCallback
& callback
) {
221 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
222 storage::FileSystemOperationContext
* context_ptr
= context
.get();
223 const bool success
= context_ptr
->task_runner()->PostTask(
225 base::Bind(&NativeMediaFileUtil::CopyOrMoveFileLocalOnTaskRunnerThread
,
226 weak_factory_
.GetWeakPtr(), base::Passed(&context
),
227 src_url
, dest_url
, option
, true /* copy */, callback
));
231 void NativeMediaFileUtil::MoveFileLocal(
232 scoped_ptr
<storage::FileSystemOperationContext
> context
,
233 const storage::FileSystemURL
& src_url
,
234 const storage::FileSystemURL
& dest_url
,
235 CopyOrMoveOption option
,
236 const StatusCallback
& callback
) {
237 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
238 storage::FileSystemOperationContext
* context_ptr
= context
.get();
239 const bool success
= context_ptr
->task_runner()->PostTask(
241 base::Bind(&NativeMediaFileUtil::CopyOrMoveFileLocalOnTaskRunnerThread
,
242 weak_factory_
.GetWeakPtr(), base::Passed(&context
),
243 src_url
, dest_url
, option
, false /* copy */, callback
));
247 void NativeMediaFileUtil::CopyInForeignFile(
248 scoped_ptr
<storage::FileSystemOperationContext
> context
,
249 const base::FilePath
& src_file_path
,
250 const storage::FileSystemURL
& dest_url
,
251 const StatusCallback
& callback
) {
252 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
253 storage::FileSystemOperationContext
* context_ptr
= context
.get();
254 const bool success
= context_ptr
->task_runner()->PostTask(
256 base::Bind(&NativeMediaFileUtil::CopyInForeignFileOnTaskRunnerThread
,
257 weak_factory_
.GetWeakPtr(), base::Passed(&context
),
258 src_file_path
, dest_url
, callback
));
262 void NativeMediaFileUtil::DeleteFile(
263 scoped_ptr
<storage::FileSystemOperationContext
> context
,
264 const storage::FileSystemURL
& url
,
265 const StatusCallback
& callback
) {
266 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
267 storage::FileSystemOperationContext
* context_ptr
= context
.get();
268 const bool success
= context_ptr
->task_runner()->PostTask(
270 base::Bind(&NativeMediaFileUtil::DeleteFileOnTaskRunnerThread
,
271 weak_factory_
.GetWeakPtr(), base::Passed(&context
),
276 // This is needed to support Copy and Move.
277 void NativeMediaFileUtil::DeleteDirectory(
278 scoped_ptr
<storage::FileSystemOperationContext
> context
,
279 const storage::FileSystemURL
& url
,
280 const StatusCallback
& callback
) {
281 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
282 storage::FileSystemOperationContext
* context_ptr
= context
.get();
283 const bool success
= context_ptr
->task_runner()->PostTask(
285 base::Bind(&NativeMediaFileUtil::DeleteDirectoryOnTaskRunnerThread
,
286 weak_factory_
.GetWeakPtr(), base::Passed(&context
),
291 void NativeMediaFileUtil::DeleteRecursively(
292 scoped_ptr
<storage::FileSystemOperationContext
> context
,
293 const storage::FileSystemURL
& url
,
294 const StatusCallback
& callback
) {
295 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
296 callback
.Run(base::File::FILE_ERROR_INVALID_OPERATION
);
299 void NativeMediaFileUtil::CreateSnapshotFile(
300 scoped_ptr
<storage::FileSystemOperationContext
> context
,
301 const storage::FileSystemURL
& url
,
302 const CreateSnapshotFileCallback
& callback
) {
303 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
304 storage::FileSystemOperationContext
* context_ptr
= context
.get();
305 const bool success
= context_ptr
->task_runner()->PostTask(
307 base::Bind(&NativeMediaFileUtil::CreateSnapshotFileOnTaskRunnerThread
,
308 weak_factory_
.GetWeakPtr(), base::Passed(&context
),
313 void NativeMediaFileUtil::CreateDirectoryOnTaskRunnerThread(
314 scoped_ptr
<storage::FileSystemOperationContext
> context
,
315 const storage::FileSystemURL
& url
,
318 const StatusCallback
& callback
) {
319 DCHECK(IsOnTaskRunnerThread(context
.get()));
320 base::File::Error error
=
321 CreateDirectorySync(context
.get(), url
, exclusive
, recursive
);
322 content::BrowserThread::PostTask(
323 content::BrowserThread::IO
,
325 base::Bind(callback
, error
));
328 void NativeMediaFileUtil::GetFileInfoOnTaskRunnerThread(
329 scoped_ptr
<storage::FileSystemOperationContext
> context
,
330 const storage::FileSystemURL
& url
,
331 const GetFileInfoCallback
& callback
) {
332 DCHECK(IsOnTaskRunnerThread(context
.get()));
333 base::File::Info file_info
;
334 base::File::Error error
=
335 GetFileInfoSync(context
.get(), url
, &file_info
, NULL
);
336 content::BrowserThread::PostTask(
337 content::BrowserThread::IO
,
339 base::Bind(callback
, error
, file_info
));
342 void NativeMediaFileUtil::ReadDirectoryOnTaskRunnerThread(
343 scoped_ptr
<storage::FileSystemOperationContext
> context
,
344 const storage::FileSystemURL
& url
,
345 const ReadDirectoryCallback
& callback
) {
346 DCHECK(IsOnTaskRunnerThread(context
.get()));
347 EntryList entry_list
;
348 base::File::Error error
=
349 ReadDirectorySync(context
.get(), url
, &entry_list
);
350 content::BrowserThread::PostTask(
351 content::BrowserThread::IO
,
353 base::Bind(callback
, error
, entry_list
, false /* has_more */));
356 void NativeMediaFileUtil::CopyOrMoveFileLocalOnTaskRunnerThread(
357 scoped_ptr
<storage::FileSystemOperationContext
> context
,
358 const storage::FileSystemURL
& src_url
,
359 const storage::FileSystemURL
& dest_url
,
360 CopyOrMoveOption option
,
362 const StatusCallback
& callback
) {
363 DCHECK(IsOnTaskRunnerThread(context
.get()));
364 base::File::Error error
=
365 CopyOrMoveFileSync(context
.get(), src_url
, dest_url
, option
, copy
);
366 content::BrowserThread::PostTask(
367 content::BrowserThread::IO
,
369 base::Bind(callback
, error
));
372 void NativeMediaFileUtil::CopyInForeignFileOnTaskRunnerThread(
373 scoped_ptr
<storage::FileSystemOperationContext
> context
,
374 const base::FilePath
& src_file_path
,
375 const storage::FileSystemURL
& dest_url
,
376 const StatusCallback
& callback
) {
377 DCHECK(IsOnTaskRunnerThread(context
.get()));
378 base::File::Error error
=
379 CopyInForeignFileSync(context
.get(), src_file_path
, dest_url
);
380 content::BrowserThread::PostTask(
381 content::BrowserThread::IO
,
383 base::Bind(callback
, error
));
386 void NativeMediaFileUtil::DeleteFileOnTaskRunnerThread(
387 scoped_ptr
<storage::FileSystemOperationContext
> context
,
388 const storage::FileSystemURL
& url
,
389 const StatusCallback
& callback
) {
390 DCHECK(IsOnTaskRunnerThread(context
.get()));
391 base::File::Error error
= DeleteFileSync(context
.get(), url
);
392 content::BrowserThread::PostTask(
393 content::BrowserThread::IO
,
395 base::Bind(callback
, error
));
398 void NativeMediaFileUtil::DeleteDirectoryOnTaskRunnerThread(
399 scoped_ptr
<storage::FileSystemOperationContext
> context
,
400 const storage::FileSystemURL
& url
,
401 const StatusCallback
& callback
) {
402 DCHECK(IsOnTaskRunnerThread(context
.get()));
403 base::File::Error error
= DeleteDirectorySync(context
.get(), url
);
404 content::BrowserThread::PostTask(
405 content::BrowserThread::IO
,
407 base::Bind(callback
, error
));
410 void NativeMediaFileUtil::CreateSnapshotFileOnTaskRunnerThread(
411 scoped_ptr
<storage::FileSystemOperationContext
> context
,
412 const storage::FileSystemURL
& url
,
413 const CreateSnapshotFileCallback
& callback
) {
414 DCHECK(IsOnTaskRunnerThread(context
.get()));
415 base::File::Info file_info
;
416 base::FilePath platform_path
;
417 scoped_refptr
<storage::ShareableFileReference
> file_ref
;
418 base::File::Error error
= CreateSnapshotFileSync(
419 context
.get(), url
, &file_info
, &platform_path
, &file_ref
);
420 content::BrowserThread::PostTask(
421 content::BrowserThread::IO
,
423 base::Bind(callback
, error
, file_info
, platform_path
, file_ref
));
426 base::File::Error
NativeMediaFileUtil::CreateDirectorySync(
427 storage::FileSystemOperationContext
* context
,
428 const storage::FileSystemURL
& url
,
431 base::FilePath file_path
;
432 base::File::Error error
= GetLocalFilePath(context
, url
, &file_path
);
433 if (error
!= base::File::FILE_OK
)
435 return storage::NativeFileUtil::CreateDirectory(
436 file_path
, exclusive
, recursive
);
439 base::File::Error
NativeMediaFileUtil::CopyOrMoveFileSync(
440 storage::FileSystemOperationContext
* context
,
441 const storage::FileSystemURL
& src_url
,
442 const storage::FileSystemURL
& dest_url
,
443 CopyOrMoveOption option
,
445 DCHECK(IsOnTaskRunnerThread(context
));
446 base::FilePath src_file_path
;
447 base::File::Error error
=
448 GetFilteredLocalFilePathForExistingFileOrDirectory(
450 base::File::FILE_ERROR_NOT_FOUND
,
452 if (error
!= base::File::FILE_OK
)
454 if (storage::NativeFileUtil::DirectoryExists(src_file_path
))
455 return base::File::FILE_ERROR_NOT_A_FILE
;
457 base::FilePath dest_file_path
;
458 error
= GetLocalFilePath(context
, dest_url
, &dest_file_path
);
459 if (error
!= base::File::FILE_OK
)
461 base::File::Info file_info
;
462 error
= storage::NativeFileUtil::GetFileInfo(dest_file_path
, &file_info
);
463 if (error
!= base::File::FILE_OK
&&
464 error
!= base::File::FILE_ERROR_NOT_FOUND
) {
467 if (error
== base::File::FILE_OK
&& file_info
.is_directory
)
468 return base::File::FILE_ERROR_INVALID_OPERATION
;
469 if (!media_path_filter_
->Match(dest_file_path
))
470 return base::File::FILE_ERROR_SECURITY
;
472 return storage::NativeFileUtil::CopyOrMoveFile(
476 storage::NativeFileUtil::CopyOrMoveModeForDestination(dest_url
, copy
));
479 base::File::Error
NativeMediaFileUtil::CopyInForeignFileSync(
480 storage::FileSystemOperationContext
* context
,
481 const base::FilePath
& src_file_path
,
482 const storage::FileSystemURL
& dest_url
) {
483 DCHECK(IsOnTaskRunnerThread(context
));
484 if (src_file_path
.empty())
485 return base::File::FILE_ERROR_INVALID_OPERATION
;
487 base::FilePath dest_file_path
;
488 base::File::Error error
=
489 GetFilteredLocalFilePath(context
, dest_url
, &dest_file_path
);
490 if (error
!= base::File::FILE_OK
)
492 return storage::NativeFileUtil::CopyOrMoveFile(
495 storage::FileSystemOperation::OPTION_NONE
,
496 storage::NativeFileUtil::CopyOrMoveModeForDestination(dest_url
,
500 base::File::Error
NativeMediaFileUtil::GetFileInfoSync(
501 storage::FileSystemOperationContext
* context
,
502 const storage::FileSystemURL
& url
,
503 base::File::Info
* file_info
,
504 base::FilePath
* platform_path
) {
506 DCHECK(IsOnTaskRunnerThread(context
));
509 base::FilePath file_path
;
510 base::File::Error error
= GetLocalFilePath(context
, url
, &file_path
);
511 if (error
!= base::File::FILE_OK
)
513 if (base::IsLink(file_path
))
514 return base::File::FILE_ERROR_NOT_FOUND
;
515 error
= storage::NativeFileUtil::GetFileInfo(file_path
, file_info
);
516 if (error
!= base::File::FILE_OK
)
520 *platform_path
= file_path
;
521 if (file_info
->is_directory
||
522 media_path_filter_
->Match(file_path
)) {
523 return base::File::FILE_OK
;
525 return base::File::FILE_ERROR_NOT_FOUND
;
528 base::File::Error
NativeMediaFileUtil::GetLocalFilePath(
529 storage::FileSystemOperationContext
* context
,
530 const storage::FileSystemURL
& url
,
531 base::FilePath
* local_file_path
) {
532 DCHECK(local_file_path
);
533 DCHECK(url
.is_valid());
534 if (url
.path().empty()) {
535 // Root direcory case, which should not be accessed.
536 return base::File::FILE_ERROR_ACCESS_DENIED
;
538 *local_file_path
= url
.path();
539 return base::File::FILE_OK
;
542 base::File::Error
NativeMediaFileUtil::ReadDirectorySync(
543 storage::FileSystemOperationContext
* context
,
544 const storage::FileSystemURL
& url
,
545 EntryList
* file_list
) {
546 DCHECK(IsOnTaskRunnerThread(context
));
548 DCHECK(file_list
->empty());
549 base::File::Info file_info
;
550 base::FilePath dir_path
;
551 base::File::Error error
=
552 GetFileInfoSync(context
, url
, &file_info
, &dir_path
);
554 if (error
!= base::File::FILE_OK
)
557 if (!file_info
.is_directory
)
558 return base::File::FILE_ERROR_NOT_A_DIRECTORY
;
560 base::FileEnumerator
file_enum(
562 false /* recursive */,
563 base::FileEnumerator::FILES
| base::FileEnumerator::DIRECTORIES
);
564 for (base::FilePath enum_path
= file_enum
.Next();
566 enum_path
= file_enum
.Next()) {
568 if (base::IsLink(enum_path
))
571 base::FileEnumerator::FileInfo info
= file_enum
.GetInfo();
573 // NativeMediaFileUtil skip criteria.
574 if (MediaPathFilter::ShouldSkip(enum_path
))
576 if (!info
.IsDirectory() && !media_path_filter_
->Match(enum_path
))
579 storage::DirectoryEntry entry
;
580 entry
.is_directory
= info
.IsDirectory();
581 entry
.name
= enum_path
.BaseName().value();
582 entry
.size
= info
.GetSize();
583 entry
.last_modified_time
= info
.GetLastModifiedTime();
585 file_list
->push_back(entry
);
588 return base::File::FILE_OK
;
591 base::File::Error
NativeMediaFileUtil::DeleteFileSync(
592 storage::FileSystemOperationContext
* context
,
593 const storage::FileSystemURL
& url
) {
594 DCHECK(IsOnTaskRunnerThread(context
));
595 base::File::Info file_info
;
596 base::FilePath file_path
;
597 base::File::Error error
=
598 GetFileInfoSync(context
, url
, &file_info
, &file_path
);
599 if (error
!= base::File::FILE_OK
)
601 if (file_info
.is_directory
)
602 return base::File::FILE_ERROR_NOT_A_FILE
;
603 return storage::NativeFileUtil::DeleteFile(file_path
);
606 base::File::Error
NativeMediaFileUtil::DeleteDirectorySync(
607 storage::FileSystemOperationContext
* context
,
608 const storage::FileSystemURL
& url
) {
609 DCHECK(IsOnTaskRunnerThread(context
));
610 base::FilePath file_path
;
611 base::File::Error error
= GetLocalFilePath(context
, url
, &file_path
);
612 if (error
!= base::File::FILE_OK
)
614 return storage::NativeFileUtil::DeleteDirectory(file_path
);
617 base::File::Error
NativeMediaFileUtil::CreateSnapshotFileSync(
618 storage::FileSystemOperationContext
* context
,
619 const storage::FileSystemURL
& url
,
620 base::File::Info
* file_info
,
621 base::FilePath
* platform_path
,
622 scoped_refptr
<storage::ShareableFileReference
>* file_ref
) {
623 DCHECK(IsOnTaskRunnerThread(context
));
624 base::File::Error error
=
625 GetFileInfoSync(context
, url
, file_info
, platform_path
);
626 if (error
== base::File::FILE_OK
&& file_info
->is_directory
)
627 error
= base::File::FILE_ERROR_NOT_A_FILE
;
628 if (error
== base::File::FILE_OK
)
629 error
= NativeMediaFileUtil::IsMediaFile(*platform_path
);
631 // We're just returning the local file information.
632 *file_ref
= scoped_refptr
<storage::ShareableFileReference
>();
637 base::File::Error
NativeMediaFileUtil::GetFilteredLocalFilePath(
638 storage::FileSystemOperationContext
* context
,
639 const storage::FileSystemURL
& file_system_url
,
640 base::FilePath
* local_file_path
) {
641 DCHECK(IsOnTaskRunnerThread(context
));
642 base::FilePath file_path
;
643 base::File::Error error
=
644 GetLocalFilePath(context
, file_system_url
, &file_path
);
645 if (error
!= base::File::FILE_OK
)
647 if (!media_path_filter_
->Match(file_path
))
648 return base::File::FILE_ERROR_SECURITY
;
650 *local_file_path
= file_path
;
651 return base::File::FILE_OK
;
655 NativeMediaFileUtil::GetFilteredLocalFilePathForExistingFileOrDirectory(
656 storage::FileSystemOperationContext
* context
,
657 const storage::FileSystemURL
& file_system_url
,
658 base::File::Error failure_error
,
659 base::FilePath
* local_file_path
) {
660 DCHECK(IsOnTaskRunnerThread(context
));
661 base::FilePath file_path
;
662 base::File::Error error
=
663 GetLocalFilePath(context
, file_system_url
, &file_path
);
664 if (error
!= base::File::FILE_OK
)
667 if (!base::PathExists(file_path
))
668 return failure_error
;
669 base::File::Info file_info
;
670 if (!base::GetFileInfo(file_path
, &file_info
))
671 return base::File::FILE_ERROR_FAILED
;
673 if (!file_info
.is_directory
&&
674 !media_path_filter_
->Match(file_path
)) {
675 return failure_error
;
678 *local_file_path
= file_path
;
679 return base::File::FILE_OK
;