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/file_util.h"
12 #include "base/files/file_enumerator.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"
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"
27 // Returns true if the current thread is capable of doing IO.
28 bool IsOnTaskRunnerThread(fileapi::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<webkit_blob::ShareableFileReference>& file_ref) {
54 const fileapi::AsyncFileUtil::CreateOrOpenCallback& callback,
55 const scoped_refptr<webkit_blob::ShareableFileReference>& file_ref,
57 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
58 if (file.error_details() != base::File::FILE_OK) {
59 base::PlatformFile invalid_file(base::kInvalidPlatformFileValue);
60 callback.Run(file.error_details(),
61 base::PassPlatformFile(&invalid_file),
65 base::PlatformFile platform_file = file.TakePlatformFile();
66 callback.Run(base::File::FILE_OK,
67 base::PassPlatformFile(&platform_file),
68 base::Bind(&HoldFileRef, file_ref));
73 NativeMediaFileUtil::NativeMediaFileUtil(MediaPathFilter* media_path_filter)
74 : media_path_filter_(media_path_filter),
78 NativeMediaFileUtil::~NativeMediaFileUtil() {
82 base::File::Error NativeMediaFileUtil::IsMediaFile(
83 const base::FilePath& path) {
84 base::File file(path, base::File::FLAG_OPEN | base::File::FLAG_READ);
86 return file.error_details();
88 char buffer[net::kMaxBytesToSniff];
90 // Read as much as net::SniffMimeTypeFromLocalData() will bother looking at.
91 int64 len = file.Read(0, buffer, net::kMaxBytesToSniff);
93 return base::File::FILE_ERROR_FAILED;
95 return IsMediaHeader(buffer, len);
99 base::File::Error NativeMediaFileUtil::BufferIsMediaHeader(
100 net::IOBuffer* buf, size_t length) {
101 return IsMediaHeader(buf->data(), length);
105 void NativeMediaFileUtil::CreatedSnapshotFileForCreateOrOpen(
106 base::SequencedTaskRunner* media_task_runner,
108 const fileapi::AsyncFileUtil::CreateOrOpenCallback& callback,
109 base::File::Error result,
110 const base::File::Info& file_info,
111 const base::FilePath& platform_path,
112 const scoped_refptr<webkit_blob::ShareableFileReference>& file_ref) {
113 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
114 if (result != base::File::FILE_OK) {
115 base::PlatformFile invalid_file(base::kInvalidPlatformFileValue);
117 base::PassPlatformFile(&invalid_file),
121 base::PostTaskAndReplyWithResult(
124 base::Bind(&fileapi::NativeFileUtil::CreateOrOpen,
127 base::Bind(&DidOpenSnapshot,
132 void NativeMediaFileUtil::CreateOrOpen(
133 scoped_ptr<fileapi::FileSystemOperationContext> context,
134 const fileapi::FileSystemURL& url,
136 const CreateOrOpenCallback& callback) {
137 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
138 // Returns an error if any unsupported flag is found.
139 if (file_flags & ~(base::File::FLAG_OPEN |
140 base::File::FLAG_READ |
141 base::File::FLAG_WRITE_ATTRIBUTES)) {
142 base::PlatformFile invalid_file(base::kInvalidPlatformFileValue);
143 callback.Run(base::File::FILE_ERROR_SECURITY,
144 base::PassPlatformFile(&invalid_file),
148 scoped_refptr<base::SequencedTaskRunner> task_runner = context->task_runner();
152 base::Bind(&NativeMediaFileUtil::CreatedSnapshotFileForCreateOrOpen,
158 void NativeMediaFileUtil::EnsureFileExists(
159 scoped_ptr<fileapi::FileSystemOperationContext> context,
160 const fileapi::FileSystemURL& url,
161 const EnsureFileExistsCallback& callback) {
162 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
163 callback.Run(base::File::FILE_ERROR_SECURITY, false);
166 void NativeMediaFileUtil::CreateDirectory(
167 scoped_ptr<fileapi::FileSystemOperationContext> context,
168 const fileapi::FileSystemURL& url,
171 const StatusCallback& callback) {
172 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
173 fileapi::FileSystemOperationContext* context_ptr = context.get();
174 const bool success = context_ptr->task_runner()->PostTask(
176 base::Bind(&NativeMediaFileUtil::CreateDirectoryOnTaskRunnerThread,
177 weak_factory_.GetWeakPtr(), base::Passed(&context),
178 url, exclusive, recursive, callback));
182 void NativeMediaFileUtil::GetFileInfo(
183 scoped_ptr<fileapi::FileSystemOperationContext> context,
184 const fileapi::FileSystemURL& url,
185 const GetFileInfoCallback& callback) {
186 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
187 fileapi::FileSystemOperationContext* context_ptr = context.get();
188 const bool success = context_ptr->task_runner()->PostTask(
190 base::Bind(&NativeMediaFileUtil::GetFileInfoOnTaskRunnerThread,
191 weak_factory_.GetWeakPtr(), base::Passed(&context),
196 void NativeMediaFileUtil::ReadDirectory(
197 scoped_ptr<fileapi::FileSystemOperationContext> context,
198 const fileapi::FileSystemURL& url,
199 const ReadDirectoryCallback& callback) {
200 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
201 fileapi::FileSystemOperationContext* context_ptr = context.get();
202 const bool success = context_ptr->task_runner()->PostTask(
204 base::Bind(&NativeMediaFileUtil::ReadDirectoryOnTaskRunnerThread,
205 weak_factory_.GetWeakPtr(), base::Passed(&context),
210 void NativeMediaFileUtil::Touch(
211 scoped_ptr<fileapi::FileSystemOperationContext> context,
212 const fileapi::FileSystemURL& url,
213 const base::Time& last_access_time,
214 const base::Time& last_modified_time,
215 const StatusCallback& callback) {
216 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
217 callback.Run(base::File::FILE_ERROR_SECURITY);
220 void NativeMediaFileUtil::Truncate(
221 scoped_ptr<fileapi::FileSystemOperationContext> context,
222 const fileapi::FileSystemURL& url,
224 const StatusCallback& callback) {
225 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
226 callback.Run(base::File::FILE_ERROR_SECURITY);
229 void NativeMediaFileUtil::CopyFileLocal(
230 scoped_ptr<fileapi::FileSystemOperationContext> context,
231 const fileapi::FileSystemURL& src_url,
232 const fileapi::FileSystemURL& dest_url,
233 CopyOrMoveOption option,
234 const CopyFileProgressCallback& progress_callback,
235 const StatusCallback& callback) {
236 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
237 fileapi::FileSystemOperationContext* context_ptr = context.get();
238 const bool success = context_ptr->task_runner()->PostTask(
240 base::Bind(&NativeMediaFileUtil::CopyOrMoveFileLocalOnTaskRunnerThread,
241 weak_factory_.GetWeakPtr(), base::Passed(&context),
242 src_url, dest_url, option, true /* copy */, callback));
246 void NativeMediaFileUtil::MoveFileLocal(
247 scoped_ptr<fileapi::FileSystemOperationContext> context,
248 const fileapi::FileSystemURL& src_url,
249 const fileapi::FileSystemURL& dest_url,
250 CopyOrMoveOption option,
251 const StatusCallback& callback) {
252 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
253 fileapi::FileSystemOperationContext* context_ptr = context.get();
254 const bool success = context_ptr->task_runner()->PostTask(
256 base::Bind(&NativeMediaFileUtil::CopyOrMoveFileLocalOnTaskRunnerThread,
257 weak_factory_.GetWeakPtr(), base::Passed(&context),
258 src_url, dest_url, option, false /* copy */, callback));
262 void NativeMediaFileUtil::CopyInForeignFile(
263 scoped_ptr<fileapi::FileSystemOperationContext> context,
264 const base::FilePath& src_file_path,
265 const fileapi::FileSystemURL& dest_url,
266 const StatusCallback& callback) {
267 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
268 fileapi::FileSystemOperationContext* context_ptr = context.get();
269 const bool success = context_ptr->task_runner()->PostTask(
271 base::Bind(&NativeMediaFileUtil::CopyInForeignFileOnTaskRunnerThread,
272 weak_factory_.GetWeakPtr(), base::Passed(&context),
273 src_file_path, dest_url, callback));
277 void NativeMediaFileUtil::DeleteFile(
278 scoped_ptr<fileapi::FileSystemOperationContext> context,
279 const fileapi::FileSystemURL& url,
280 const StatusCallback& callback) {
281 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
282 fileapi::FileSystemOperationContext* context_ptr = context.get();
283 const bool success = context_ptr->task_runner()->PostTask(
285 base::Bind(&NativeMediaFileUtil::DeleteFileOnTaskRunnerThread,
286 weak_factory_.GetWeakPtr(), base::Passed(&context),
291 // This is needed to support Copy and Move.
292 void NativeMediaFileUtil::DeleteDirectory(
293 scoped_ptr<fileapi::FileSystemOperationContext> context,
294 const fileapi::FileSystemURL& url,
295 const StatusCallback& callback) {
296 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
297 fileapi::FileSystemOperationContext* context_ptr = context.get();
298 const bool success = context_ptr->task_runner()->PostTask(
300 base::Bind(&NativeMediaFileUtil::DeleteDirectoryOnTaskRunnerThread,
301 weak_factory_.GetWeakPtr(), base::Passed(&context),
306 void NativeMediaFileUtil::DeleteRecursively(
307 scoped_ptr<fileapi::FileSystemOperationContext> context,
308 const fileapi::FileSystemURL& url,
309 const StatusCallback& callback) {
310 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
311 callback.Run(base::File::FILE_ERROR_INVALID_OPERATION);
314 void NativeMediaFileUtil::CreateSnapshotFile(
315 scoped_ptr<fileapi::FileSystemOperationContext> context,
316 const fileapi::FileSystemURL& url,
317 const CreateSnapshotFileCallback& callback) {
318 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
319 fileapi::FileSystemOperationContext* context_ptr = context.get();
320 const bool success = context_ptr->task_runner()->PostTask(
322 base::Bind(&NativeMediaFileUtil::CreateSnapshotFileOnTaskRunnerThread,
323 weak_factory_.GetWeakPtr(), base::Passed(&context),
328 void NativeMediaFileUtil::CreateDirectoryOnTaskRunnerThread(
329 scoped_ptr<fileapi::FileSystemOperationContext> context,
330 const fileapi::FileSystemURL& url,
333 const StatusCallback& callback) {
334 DCHECK(IsOnTaskRunnerThread(context.get()));
335 base::File::Error error =
336 CreateDirectorySync(context.get(), url, exclusive, recursive);
337 content::BrowserThread::PostTask(
338 content::BrowserThread::IO,
340 base::Bind(callback, error));
343 void NativeMediaFileUtil::GetFileInfoOnTaskRunnerThread(
344 scoped_ptr<fileapi::FileSystemOperationContext> context,
345 const fileapi::FileSystemURL& url,
346 const GetFileInfoCallback& callback) {
347 DCHECK(IsOnTaskRunnerThread(context.get()));
348 base::File::Info file_info;
349 base::File::Error error =
350 GetFileInfoSync(context.get(), url, &file_info, NULL);
351 content::BrowserThread::PostTask(
352 content::BrowserThread::IO,
354 base::Bind(callback, error, file_info));
357 void NativeMediaFileUtil::ReadDirectoryOnTaskRunnerThread(
358 scoped_ptr<fileapi::FileSystemOperationContext> context,
359 const fileapi::FileSystemURL& url,
360 const ReadDirectoryCallback& callback) {
361 DCHECK(IsOnTaskRunnerThread(context.get()));
362 EntryList entry_list;
363 base::File::Error error =
364 ReadDirectorySync(context.get(), url, &entry_list);
365 content::BrowserThread::PostTask(
366 content::BrowserThread::IO,
368 base::Bind(callback, error, entry_list, false /* has_more */));
371 void NativeMediaFileUtil::CopyOrMoveFileLocalOnTaskRunnerThread(
372 scoped_ptr<fileapi::FileSystemOperationContext> context,
373 const fileapi::FileSystemURL& src_url,
374 const fileapi::FileSystemURL& dest_url,
375 CopyOrMoveOption option,
377 const StatusCallback& callback) {
378 DCHECK(IsOnTaskRunnerThread(context.get()));
379 base::File::Error error =
380 CopyOrMoveFileSync(context.get(), src_url, dest_url, option, copy);
381 content::BrowserThread::PostTask(
382 content::BrowserThread::IO,
384 base::Bind(callback, error));
387 void NativeMediaFileUtil::CopyInForeignFileOnTaskRunnerThread(
388 scoped_ptr<fileapi::FileSystemOperationContext> context,
389 const base::FilePath& src_file_path,
390 const fileapi::FileSystemURL& dest_url,
391 const StatusCallback& callback) {
392 DCHECK(IsOnTaskRunnerThread(context.get()));
393 base::File::Error error =
394 CopyInForeignFileSync(context.get(), src_file_path, dest_url);
395 content::BrowserThread::PostTask(
396 content::BrowserThread::IO,
398 base::Bind(callback, error));
401 void NativeMediaFileUtil::DeleteFileOnTaskRunnerThread(
402 scoped_ptr<fileapi::FileSystemOperationContext> context,
403 const fileapi::FileSystemURL& url,
404 const StatusCallback& callback) {
405 DCHECK(IsOnTaskRunnerThread(context.get()));
406 base::File::Error error = DeleteFileSync(context.get(), url);
407 content::BrowserThread::PostTask(
408 content::BrowserThread::IO,
410 base::Bind(callback, error));
413 void NativeMediaFileUtil::DeleteDirectoryOnTaskRunnerThread(
414 scoped_ptr<fileapi::FileSystemOperationContext> context,
415 const fileapi::FileSystemURL& url,
416 const StatusCallback& callback) {
417 DCHECK(IsOnTaskRunnerThread(context.get()));
418 base::File::Error error = DeleteDirectorySync(context.get(), url);
419 content::BrowserThread::PostTask(
420 content::BrowserThread::IO,
422 base::Bind(callback, error));
425 void NativeMediaFileUtil::CreateSnapshotFileOnTaskRunnerThread(
426 scoped_ptr<fileapi::FileSystemOperationContext> context,
427 const fileapi::FileSystemURL& url,
428 const CreateSnapshotFileCallback& callback) {
429 DCHECK(IsOnTaskRunnerThread(context.get()));
430 base::File::Info file_info;
431 base::FilePath platform_path;
432 scoped_refptr<webkit_blob::ShareableFileReference> file_ref;
433 base::File::Error error =
434 CreateSnapshotFileSync(context.get(), url, &file_info, &platform_path,
436 content::BrowserThread::PostTask(
437 content::BrowserThread::IO,
439 base::Bind(callback, error, file_info, platform_path, file_ref));
442 base::File::Error NativeMediaFileUtil::CreateDirectorySync(
443 fileapi::FileSystemOperationContext* context,
444 const fileapi::FileSystemURL& url,
447 base::FilePath file_path;
448 base::File::Error error = GetLocalFilePath(context, url, &file_path);
449 if (error != base::File::FILE_OK)
451 return fileapi::NativeFileUtil::CreateDirectory(file_path, exclusive,
455 base::File::Error NativeMediaFileUtil::CopyOrMoveFileSync(
456 fileapi::FileSystemOperationContext* context,
457 const fileapi::FileSystemURL& src_url,
458 const fileapi::FileSystemURL& dest_url,
459 CopyOrMoveOption option,
461 DCHECK(IsOnTaskRunnerThread(context));
462 base::FilePath src_file_path;
463 base::File::Error error =
464 GetFilteredLocalFilePathForExistingFileOrDirectory(
466 base::File::FILE_ERROR_NOT_FOUND,
468 if (error != base::File::FILE_OK)
470 if (fileapi::NativeFileUtil::DirectoryExists(src_file_path))
471 return base::File::FILE_ERROR_NOT_A_FILE;
473 base::FilePath dest_file_path;
474 error = GetLocalFilePath(context, dest_url, &dest_file_path);
475 if (error != base::File::FILE_OK)
477 base::File::Info file_info;
478 error = fileapi::NativeFileUtil::GetFileInfo(dest_file_path, &file_info);
479 if (error != base::File::FILE_OK &&
480 error != base::File::FILE_ERROR_NOT_FOUND) {
483 if (error == base::File::FILE_OK && file_info.is_directory)
484 return base::File::FILE_ERROR_INVALID_OPERATION;
485 if (!media_path_filter_->Match(dest_file_path))
486 return base::File::FILE_ERROR_SECURITY;
488 return fileapi::NativeFileUtil::CopyOrMoveFile(
489 src_file_path, dest_file_path, option,
490 fileapi::NativeFileUtil::CopyOrMoveModeForDestination(dest_url, copy));
493 base::File::Error NativeMediaFileUtil::CopyInForeignFileSync(
494 fileapi::FileSystemOperationContext* context,
495 const base::FilePath& src_file_path,
496 const fileapi::FileSystemURL& dest_url) {
497 DCHECK(IsOnTaskRunnerThread(context));
498 if (src_file_path.empty())
499 return base::File::FILE_ERROR_INVALID_OPERATION;
501 base::FilePath dest_file_path;
502 base::File::Error error =
503 GetFilteredLocalFilePath(context, dest_url, &dest_file_path);
504 if (error != base::File::FILE_OK)
506 return fileapi::NativeFileUtil::CopyOrMoveFile(
507 src_file_path, dest_file_path,
508 fileapi::FileSystemOperation::OPTION_NONE,
509 fileapi::NativeFileUtil::CopyOrMoveModeForDestination(dest_url,
513 base::File::Error NativeMediaFileUtil::GetFileInfoSync(
514 fileapi::FileSystemOperationContext* context,
515 const fileapi::FileSystemURL& url,
516 base::File::Info* file_info,
517 base::FilePath* platform_path) {
519 DCHECK(IsOnTaskRunnerThread(context));
522 base::FilePath file_path;
523 base::File::Error error = GetLocalFilePath(context, url, &file_path);
524 if (error != base::File::FILE_OK)
526 if (base::IsLink(file_path))
527 return base::File::FILE_ERROR_NOT_FOUND;
528 error = fileapi::NativeFileUtil::GetFileInfo(file_path, file_info);
529 if (error != base::File::FILE_OK)
533 *platform_path = file_path;
534 if (file_info->is_directory ||
535 media_path_filter_->Match(file_path)) {
536 return base::File::FILE_OK;
538 return base::File::FILE_ERROR_NOT_FOUND;
541 base::File::Error NativeMediaFileUtil::GetLocalFilePath(
542 fileapi::FileSystemOperationContext* context,
543 const fileapi::FileSystemURL& url,
544 base::FilePath* local_file_path) {
545 DCHECK(local_file_path);
546 DCHECK(url.is_valid());
547 if (url.path().empty()) {
548 // Root direcory case, which should not be accessed.
549 return base::File::FILE_ERROR_ACCESS_DENIED;
551 *local_file_path = url.path();
552 return base::File::FILE_OK;
555 base::File::Error NativeMediaFileUtil::ReadDirectorySync(
556 fileapi::FileSystemOperationContext* context,
557 const fileapi::FileSystemURL& url,
558 EntryList* file_list) {
559 DCHECK(IsOnTaskRunnerThread(context));
561 DCHECK(file_list->empty());
562 base::File::Info file_info;
563 base::FilePath dir_path;
564 base::File::Error error =
565 GetFileInfoSync(context, url, &file_info, &dir_path);
567 if (error != base::File::FILE_OK)
570 if (!file_info.is_directory)
571 return base::File::FILE_ERROR_NOT_A_DIRECTORY;
573 base::FileEnumerator file_enum(
575 false /* recursive */,
576 base::FileEnumerator::FILES | base::FileEnumerator::DIRECTORIES);
577 for (base::FilePath enum_path = file_enum.Next();
579 enum_path = file_enum.Next()) {
581 if (base::IsLink(enum_path))
584 base::FileEnumerator::FileInfo info = file_enum.GetInfo();
586 // NativeMediaFileUtil skip criteria.
587 if (MediaPathFilter::ShouldSkip(enum_path))
589 if (!info.IsDirectory() && !media_path_filter_->Match(enum_path))
592 fileapi::DirectoryEntry entry;
593 entry.is_directory = info.IsDirectory();
594 entry.name = enum_path.BaseName().value();
595 entry.size = info.GetSize();
596 entry.last_modified_time = info.GetLastModifiedTime();
598 file_list->push_back(entry);
601 return base::File::FILE_OK;
604 base::File::Error NativeMediaFileUtil::DeleteFileSync(
605 fileapi::FileSystemOperationContext* context,
606 const fileapi::FileSystemURL& url) {
607 DCHECK(IsOnTaskRunnerThread(context));
608 base::File::Info file_info;
609 base::FilePath file_path;
610 base::File::Error error =
611 GetFileInfoSync(context, url, &file_info, &file_path);
612 if (error != base::File::FILE_OK)
614 if (file_info.is_directory)
615 return base::File::FILE_ERROR_NOT_A_FILE;
616 return fileapi::NativeFileUtil::DeleteFile(file_path);
619 base::File::Error NativeMediaFileUtil::DeleteDirectorySync(
620 fileapi::FileSystemOperationContext* context,
621 const fileapi::FileSystemURL& url) {
622 DCHECK(IsOnTaskRunnerThread(context));
623 base::FilePath file_path;
624 base::File::Error error = GetLocalFilePath(context, url, &file_path);
625 if (error != base::File::FILE_OK)
627 return fileapi::NativeFileUtil::DeleteDirectory(file_path);
630 base::File::Error NativeMediaFileUtil::CreateSnapshotFileSync(
631 fileapi::FileSystemOperationContext* context,
632 const fileapi::FileSystemURL& url,
633 base::File::Info* file_info,
634 base::FilePath* platform_path,
635 scoped_refptr<webkit_blob::ShareableFileReference>* file_ref) {
636 DCHECK(IsOnTaskRunnerThread(context));
637 base::File::Error error =
638 GetFileInfoSync(context, url, file_info, platform_path);
639 if (error == base::File::FILE_OK && file_info->is_directory)
640 error = base::File::FILE_ERROR_NOT_A_FILE;
641 if (error == base::File::FILE_OK)
642 error = NativeMediaFileUtil::IsMediaFile(*platform_path);
644 // We're just returning the local file information.
645 *file_ref = scoped_refptr<webkit_blob::ShareableFileReference>();
650 base::File::Error NativeMediaFileUtil::GetFilteredLocalFilePath(
651 fileapi::FileSystemOperationContext* context,
652 const fileapi::FileSystemURL& file_system_url,
653 base::FilePath* local_file_path) {
654 DCHECK(IsOnTaskRunnerThread(context));
655 base::FilePath file_path;
656 base::File::Error error =
657 GetLocalFilePath(context, file_system_url, &file_path);
658 if (error != base::File::FILE_OK)
660 if (!media_path_filter_->Match(file_path))
661 return base::File::FILE_ERROR_SECURITY;
663 *local_file_path = file_path;
664 return base::File::FILE_OK;
668 NativeMediaFileUtil::GetFilteredLocalFilePathForExistingFileOrDirectory(
669 fileapi::FileSystemOperationContext* context,
670 const fileapi::FileSystemURL& file_system_url,
671 base::File::Error failure_error,
672 base::FilePath* local_file_path) {
673 DCHECK(IsOnTaskRunnerThread(context));
674 base::FilePath file_path;
675 base::File::Error error =
676 GetLocalFilePath(context, file_system_url, &file_path);
677 if (error != base::File::FILE_OK)
680 if (!base::PathExists(file_path))
681 return failure_error;
682 base::File::Info file_info;
683 if (!base::GetFileInfo(file_path, &file_info))
684 return base::File::FILE_ERROR_FAILED;
686 if (!file_info.is_directory &&
687 !media_path_filter_->Match(file_path)) {
688 return failure_error;
691 *local_file_path = file_path;
692 return base::File::FILE_OK;