1 // Copyright (c) 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/device_media_async_file_util.h"
7 #include "base/callback.h"
8 #include "base/files/file_util.h"
9 #include "base/single_thread_task_runner.h"
10 #include "base/task_runner_util.h"
11 #include "chrome/browser/media_galleries/fileapi/media_path_filter.h"
12 #include "chrome/browser/media_galleries/fileapi/mtp_device_async_delegate.h"
13 #include "chrome/browser/media_galleries/fileapi/mtp_device_map_service.h"
14 #include "chrome/browser/media_galleries/fileapi/mtp_file_stream_reader.h"
15 #include "chrome/browser/media_galleries/fileapi/native_media_file_util.h"
16 #include "chrome/browser/media_galleries/fileapi/readahead_file_stream_reader.h"
17 #include "content/public/browser/browser_thread.h"
18 #include "storage/browser/blob/shareable_file_reference.h"
19 #include "storage/browser/fileapi/file_stream_reader.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/file_system_url.h"
23 #include "storage/browser/fileapi/native_file_util.h"
25 using storage::AsyncFileUtil
;
26 using storage::FileSystemOperationContext
;
27 using storage::FileSystemURL
;
28 using storage::ShareableFileReference
;
32 const char kDeviceMediaAsyncFileUtilTempDir
[] = "DeviceMediaFileSystem";
34 MTPDeviceAsyncDelegate
* GetMTPDeviceDelegate(const FileSystemURL
& url
) {
35 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
36 return MTPDeviceMapService::GetInstance()->GetMTPDeviceAsyncDelegate(
40 // Called when GetFileInfo method call failed to get the details of file
41 // specified by the requested url. |callback| is invoked to notify the
42 // caller about the file |error|.
43 void OnGetFileInfoError(const AsyncFileUtil::GetFileInfoCallback
& callback
,
44 base::File::Error error
) {
45 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
46 callback
.Run(error
, base::File::Info());
49 // Called after OnDidGetFileInfo finishes media check.
50 // |callback| is invoked to complete the GetFileInfo request.
51 void OnDidCheckMediaForGetFileInfo(
52 const AsyncFileUtil::GetFileInfoCallback
& callback
,
53 const base::File::Info
& file_info
,
55 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
57 OnGetFileInfoError(callback
, base::File::FILE_ERROR_NOT_FOUND
);
60 callback
.Run(base::File::FILE_OK
, file_info
);
63 // Called after OnDidReadDirectory finishes media check.
64 // |callback| is invoked to complete the ReadDirectory request.
65 void OnDidCheckMediaForReadDirectory(
66 const AsyncFileUtil::ReadDirectoryCallback
& callback
,
68 const AsyncFileUtil::EntryList
& file_list
) {
69 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
70 callback
.Run(base::File::FILE_OK
, file_list
, has_more
);
73 // Called when CreateDirectory method call failed.
74 void OnCreateDirectoryError(const AsyncFileUtil::StatusCallback
& callback
,
75 base::File::Error error
) {
76 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
80 // Called when ReadDirectory method call failed to enumerate the directory
81 // objects. |callback| is invoked to notify the caller about the |error|
82 // that occured while reading the directory objects.
83 void OnReadDirectoryError(const AsyncFileUtil::ReadDirectoryCallback
& callback
,
84 base::File::Error error
) {
85 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
86 callback
.Run(error
, AsyncFileUtil::EntryList(), false /*no more*/);
89 // Called when CopyFileLocal method call failed.
90 void OnCopyFileLocalError(const AsyncFileUtil::StatusCallback
& callback
,
91 base::File::Error error
) {
92 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
96 // Called when MoveFileLocal method call failed.
97 void OnMoveFileLocalError(const AsyncFileUtil::StatusCallback
& callback
,
98 base::File::Error error
) {
99 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
103 // Called when CopyInForeignFile method call failed.
104 void OnCopyInForeignFileError(const AsyncFileUtil::StatusCallback
& callback
,
105 base::File::Error error
) {
106 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
110 // Called when DeleteFile method call failed.
111 void OnDeleteFileError(const AsyncFileUtil::StatusCallback
& callback
,
112 base::File::Error error
) {
113 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
117 // Called when DeleteDirectory method call failed.
118 void OnDeleteDirectoryError(const AsyncFileUtil::StatusCallback
& callback
,
119 base::File::Error error
) {
120 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
124 // Called on a blocking pool thread to create a snapshot file to hold the
125 // contents of |device_file_path|. The snapshot file is created in the
126 // "profile_path/kDeviceMediaAsyncFileUtilTempDir" directory. Return the
127 // snapshot file path or an empty path on failure.
128 base::FilePath
CreateSnapshotFileOnBlockingPool(
129 const base::FilePath
& profile_path
) {
130 base::FilePath snapshot_file_path
;
131 base::FilePath media_file_system_dir_path
=
132 profile_path
.AppendASCII(kDeviceMediaAsyncFileUtilTempDir
);
133 if (!base::CreateDirectory(media_file_system_dir_path
) ||
134 !base::CreateTemporaryFileInDir(media_file_system_dir_path
,
135 &snapshot_file_path
)) {
136 LOG(WARNING
) << "Could not create media snapshot file "
137 << media_file_system_dir_path
.value();
138 snapshot_file_path
= base::FilePath();
140 return snapshot_file_path
;
143 // Called after OnDidCreateSnapshotFile finishes media check.
144 // |callback| is invoked to complete the CreateSnapshotFile request.
145 void OnDidCheckMediaForCreateSnapshotFile(
146 const AsyncFileUtil::CreateSnapshotFileCallback
& callback
,
147 const base::File::Info
& file_info
,
148 scoped_refptr
<storage::ShareableFileReference
> platform_file
,
149 base::File::Error error
) {
150 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
151 base::FilePath
platform_path(platform_file
.get()->path());
152 if (error
!= base::File::FILE_OK
)
153 platform_file
= NULL
;
154 callback
.Run(error
, file_info
, platform_path
, platform_file
);
157 // Called when the snapshot file specified by the |platform_path| is
158 // successfully created. |file_info| contains the device media file details
159 // for which the snapshot file is created.
160 void OnDidCreateSnapshotFile(
161 const AsyncFileUtil::CreateSnapshotFileCallback
& callback
,
162 base::SequencedTaskRunner
* media_task_runner
,
163 bool validate_media_files
,
164 const base::File::Info
& file_info
,
165 const base::FilePath
& platform_path
) {
166 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
167 scoped_refptr
<storage::ShareableFileReference
> file
=
168 ShareableFileReference::GetOrCreate(
170 ShareableFileReference::DELETE_ON_FINAL_RELEASE
,
173 if (validate_media_files
) {
174 base::PostTaskAndReplyWithResult(
177 base::Bind(&NativeMediaFileUtil::IsMediaFile
, platform_path
),
178 base::Bind(&OnDidCheckMediaForCreateSnapshotFile
,
183 OnDidCheckMediaForCreateSnapshotFile(callback
, file_info
, file
,
184 base::File::FILE_OK
);
188 // Called when CreateSnapshotFile method call fails. |callback| is invoked to
189 // notify the caller about the |error|.
190 void OnCreateSnapshotFileError(
191 const AsyncFileUtil::CreateSnapshotFileCallback
& callback
,
192 base::File::Error error
) {
193 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
194 callback
.Run(error
, base::File::Info(), base::FilePath(),
195 scoped_refptr
<ShareableFileReference
>());
198 // Called when the snapshot file specified by the |snapshot_file_path| is
199 // created to hold the contents of the url.path(). If the snapshot
200 // file is successfully created, |snapshot_file_path| will be an non-empty
201 // file path. In case of failure, |snapshot_file_path| will be an empty file
202 // path. Forwards the CreateSnapshot request to the delegate to copy the
203 // contents of url.path() to |snapshot_file_path|.
204 void OnSnapshotFileCreatedRunTask(
205 scoped_ptr
<FileSystemOperationContext
> context
,
206 const AsyncFileUtil::CreateSnapshotFileCallback
& callback
,
207 const FileSystemURL
& url
,
208 bool validate_media_files
,
209 const base::FilePath
& snapshot_file_path
) {
210 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
211 if (snapshot_file_path
.empty()) {
212 OnCreateSnapshotFileError(callback
, base::File::FILE_ERROR_FAILED
);
215 MTPDeviceAsyncDelegate
* delegate
= GetMTPDeviceDelegate(url
);
217 OnCreateSnapshotFileError(callback
, base::File::FILE_ERROR_NOT_FOUND
);
220 delegate
->CreateSnapshotFile(
221 url
.path(), // device file path
223 base::Bind(&OnDidCreateSnapshotFile
,
225 make_scoped_refptr(context
->task_runner()),
226 validate_media_files
),
227 base::Bind(&OnCreateSnapshotFileError
, callback
));
232 class DeviceMediaAsyncFileUtil::MediaPathFilterWrapper
233 : public base::RefCountedThreadSafe
<MediaPathFilterWrapper
> {
235 MediaPathFilterWrapper();
237 // Check if entries in |file_list| look like media files.
238 // Append the ones that look like media files to |results|.
239 // Should run on a media task runner.
240 AsyncFileUtil::EntryList
FilterMediaEntries(
241 const AsyncFileUtil::EntryList
& file_list
);
243 // Check if |path| looks like a media file.
244 bool CheckFilePath(const base::FilePath
& path
);
247 friend class base::RefCountedThreadSafe
<MediaPathFilterWrapper
>;
249 virtual ~MediaPathFilterWrapper();
251 scoped_ptr
<MediaPathFilter
> media_path_filter_
;
253 DISALLOW_COPY_AND_ASSIGN(MediaPathFilterWrapper
);
256 DeviceMediaAsyncFileUtil::MediaPathFilterWrapper::MediaPathFilterWrapper()
257 : media_path_filter_(new MediaPathFilter
) {
260 DeviceMediaAsyncFileUtil::MediaPathFilterWrapper::~MediaPathFilterWrapper() {
263 AsyncFileUtil::EntryList
264 DeviceMediaAsyncFileUtil::MediaPathFilterWrapper::FilterMediaEntries(
265 const AsyncFileUtil::EntryList
& file_list
) {
266 AsyncFileUtil::EntryList results
;
267 for (size_t i
= 0; i
< file_list
.size(); ++i
) {
268 const storage::DirectoryEntry
& entry
= file_list
[i
];
269 if (entry
.is_directory
|| CheckFilePath(base::FilePath(entry
.name
))) {
270 results
.push_back(entry
);
276 bool DeviceMediaAsyncFileUtil::MediaPathFilterWrapper::CheckFilePath(
277 const base::FilePath
& path
) {
278 return media_path_filter_
->Match(path
);
281 DeviceMediaAsyncFileUtil::~DeviceMediaAsyncFileUtil() {
285 scoped_ptr
<DeviceMediaAsyncFileUtil
> DeviceMediaAsyncFileUtil::Create(
286 const base::FilePath
& profile_path
,
287 MediaFileValidationType validation_type
) {
288 DCHECK(!profile_path
.empty());
289 return make_scoped_ptr(
290 new DeviceMediaAsyncFileUtil(profile_path
, validation_type
));
293 bool DeviceMediaAsyncFileUtil::SupportsStreaming(
294 const storage::FileSystemURL
& url
) {
295 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
296 MTPDeviceAsyncDelegate
* delegate
= GetMTPDeviceDelegate(url
);
299 return delegate
->IsStreaming();
302 void DeviceMediaAsyncFileUtil::CreateOrOpen(
303 scoped_ptr
<FileSystemOperationContext
> context
,
304 const FileSystemURL
& url
,
306 const CreateOrOpenCallback
& callback
) {
307 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
308 // Returns an error if any unsupported flag is found.
309 if (file_flags
& ~(base::File::FLAG_OPEN
|
310 base::File::FLAG_READ
|
311 base::File::FLAG_WRITE_ATTRIBUTES
)) {
312 callback
.Run(base::File(base::File::FILE_ERROR_SECURITY
), base::Closure());
318 base::Bind(&NativeMediaFileUtil::CreatedSnapshotFileForCreateOrOpen
,
319 make_scoped_refptr(context
->task_runner()),
324 void DeviceMediaAsyncFileUtil::EnsureFileExists(
325 scoped_ptr
<FileSystemOperationContext
> context
,
326 const FileSystemURL
& url
,
327 const EnsureFileExistsCallback
& callback
) {
328 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
330 callback
.Run(base::File::FILE_ERROR_SECURITY
, false);
333 void DeviceMediaAsyncFileUtil::CreateDirectory(
334 scoped_ptr
<FileSystemOperationContext
> context
,
335 const FileSystemURL
& url
,
338 const StatusCallback
& callback
) {
339 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
340 MTPDeviceAsyncDelegate
* delegate
= GetMTPDeviceDelegate(url
);
342 OnCreateDirectoryError(callback
, base::File::FILE_ERROR_NOT_FOUND
);
345 if (delegate
->IsReadOnly()) {
346 OnCreateDirectoryError(callback
, base::File::FILE_ERROR_SECURITY
);
349 delegate
->CreateDirectory(
350 url
.path(), exclusive
, recursive
,
351 base::Bind(&DeviceMediaAsyncFileUtil::OnDidCreateDirectory
,
352 weak_ptr_factory_
.GetWeakPtr(), callback
),
353 base::Bind(&OnCreateDirectoryError
, callback
));
356 void DeviceMediaAsyncFileUtil::GetFileInfo(
357 scoped_ptr
<FileSystemOperationContext
> context
,
358 const FileSystemURL
& url
,
359 const GetFileInfoCallback
& callback
) {
360 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
361 MTPDeviceAsyncDelegate
* delegate
= GetMTPDeviceDelegate(url
);
363 OnGetFileInfoError(callback
, base::File::FILE_ERROR_NOT_FOUND
);
366 delegate
->GetFileInfo(
368 base::Bind(&DeviceMediaAsyncFileUtil::OnDidGetFileInfo
,
369 weak_ptr_factory_
.GetWeakPtr(),
370 make_scoped_refptr(context
->task_runner()),
373 base::Bind(&OnGetFileInfoError
, callback
));
376 void DeviceMediaAsyncFileUtil::ReadDirectory(
377 scoped_ptr
<FileSystemOperationContext
> context
,
378 const FileSystemURL
& url
,
379 const ReadDirectoryCallback
& callback
) {
380 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
381 MTPDeviceAsyncDelegate
* delegate
= GetMTPDeviceDelegate(url
);
383 OnReadDirectoryError(callback
, base::File::FILE_ERROR_NOT_FOUND
);
387 delegate
->ReadDirectory(
389 base::Bind(&DeviceMediaAsyncFileUtil::OnDidReadDirectory
,
390 weak_ptr_factory_
.GetWeakPtr(),
391 make_scoped_refptr(context
->task_runner()),
393 base::Bind(&OnReadDirectoryError
, callback
));
396 void DeviceMediaAsyncFileUtil::Touch(
397 scoped_ptr
<FileSystemOperationContext
> context
,
398 const FileSystemURL
& url
,
399 const base::Time
& last_access_time
,
400 const base::Time
& last_modified_time
,
401 const StatusCallback
& callback
) {
402 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
404 callback
.Run(base::File::FILE_ERROR_SECURITY
);
407 void DeviceMediaAsyncFileUtil::Truncate(
408 scoped_ptr
<FileSystemOperationContext
> context
,
409 const FileSystemURL
& url
,
411 const StatusCallback
& callback
) {
412 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
414 callback
.Run(base::File::FILE_ERROR_SECURITY
);
417 void DeviceMediaAsyncFileUtil::CopyFileLocal(
418 scoped_ptr
<FileSystemOperationContext
> context
,
419 const FileSystemURL
& src_url
,
420 const FileSystemURL
& dest_url
,
421 CopyOrMoveOption option
,
422 const CopyFileProgressCallback
& progress_callback
,
423 const StatusCallback
& callback
) {
424 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
426 MTPDeviceAsyncDelegate
* delegate
= GetMTPDeviceDelegate(dest_url
);
428 OnCopyFileLocalError(callback
, base::File::FILE_ERROR_NOT_FOUND
);
431 if (delegate
->IsReadOnly()) {
432 OnCopyFileLocalError(callback
, base::File::FILE_ERROR_SECURITY
);
436 delegate
->CopyFileLocal(
437 src_url
.path(), dest_url
.path(),
438 base::Bind(&CreateSnapshotFileOnBlockingPool
, profile_path_
),
440 base::Bind(&DeviceMediaAsyncFileUtil::OnDidCopyFileLocal
,
441 weak_ptr_factory_
.GetWeakPtr(), callback
),
442 base::Bind(&OnCopyFileLocalError
, callback
));
445 void DeviceMediaAsyncFileUtil::MoveFileLocal(
446 scoped_ptr
<FileSystemOperationContext
> context
,
447 const FileSystemURL
& src_url
,
448 const FileSystemURL
& dest_url
,
449 CopyOrMoveOption option
,
450 const StatusCallback
& callback
) {
451 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
453 MTPDeviceAsyncDelegate
* delegate
= GetMTPDeviceDelegate(dest_url
);
455 OnMoveFileLocalError(callback
, base::File::FILE_ERROR_NOT_FOUND
);
458 if (delegate
->IsReadOnly()) {
459 OnMoveFileLocalError(callback
, base::File::FILE_ERROR_SECURITY
);
463 delegate
->MoveFileLocal(
464 src_url
.path(), dest_url
.path(),
465 base::Bind(&CreateSnapshotFileOnBlockingPool
, profile_path_
),
466 base::Bind(&DeviceMediaAsyncFileUtil::OnDidMoveFileLocal
,
467 weak_ptr_factory_
.GetWeakPtr(), callback
),
468 base::Bind(&OnMoveFileLocalError
, callback
));
471 void DeviceMediaAsyncFileUtil::CopyInForeignFile(
472 scoped_ptr
<FileSystemOperationContext
> context
,
473 const base::FilePath
& src_file_path
,
474 const FileSystemURL
& dest_url
,
475 const StatusCallback
& callback
) {
476 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
478 MTPDeviceAsyncDelegate
* delegate
= GetMTPDeviceDelegate(dest_url
);
480 OnCopyInForeignFileError(callback
, base::File::FILE_ERROR_NOT_FOUND
);
483 if (delegate
->IsReadOnly()) {
484 OnCopyInForeignFileError(callback
, base::File::FILE_ERROR_SECURITY
);
488 delegate
->CopyFileFromLocal(
489 src_file_path
, dest_url
.path(),
490 base::Bind(&DeviceMediaAsyncFileUtil::OnDidCopyInForeignFile
,
491 weak_ptr_factory_
.GetWeakPtr(), callback
),
492 base::Bind(&OnCopyInForeignFileError
, callback
));
495 void DeviceMediaAsyncFileUtil::DeleteFile(
496 scoped_ptr
<FileSystemOperationContext
> context
,
497 const FileSystemURL
& url
,
498 const StatusCallback
& callback
) {
499 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
501 MTPDeviceAsyncDelegate
* const delegate
= GetMTPDeviceDelegate(url
);
503 OnDeleteFileError(callback
, base::File::FILE_ERROR_NOT_FOUND
);
506 if (delegate
->IsReadOnly()) {
507 OnDeleteFileError(callback
, base::File::FILE_ERROR_SECURITY
);
511 delegate
->DeleteFile(url
.path(),
512 base::Bind(&DeviceMediaAsyncFileUtil::OnDidDeleteFile
,
513 weak_ptr_factory_
.GetWeakPtr(), callback
),
514 base::Bind(&OnDeleteFileError
, callback
));
517 void DeviceMediaAsyncFileUtil::DeleteDirectory(
518 scoped_ptr
<FileSystemOperationContext
> context
,
519 const FileSystemURL
& url
,
520 const StatusCallback
& callback
) {
521 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
523 MTPDeviceAsyncDelegate
* const delegate
= GetMTPDeviceDelegate(url
);
525 OnDeleteDirectoryError(callback
, base::File::FILE_ERROR_NOT_FOUND
);
528 if (delegate
->IsReadOnly()) {
529 OnDeleteDirectoryError(callback
, base::File::FILE_ERROR_SECURITY
);
533 delegate
->DeleteDirectory(
534 url
.path(), base::Bind(&DeviceMediaAsyncFileUtil::OnDidDeleteDirectory
,
535 weak_ptr_factory_
.GetWeakPtr(), callback
),
536 base::Bind(&OnDeleteDirectoryError
, callback
));
539 void DeviceMediaAsyncFileUtil::DeleteRecursively(
540 scoped_ptr
<FileSystemOperationContext
> context
,
541 const FileSystemURL
& url
,
542 const StatusCallback
& callback
) {
543 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
544 callback
.Run(base::File::FILE_ERROR_INVALID_OPERATION
);
547 void DeviceMediaAsyncFileUtil::CreateSnapshotFile(
548 scoped_ptr
<FileSystemOperationContext
> context
,
549 const FileSystemURL
& url
,
550 const CreateSnapshotFileCallback
& callback
) {
551 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
552 MTPDeviceAsyncDelegate
* delegate
= GetMTPDeviceDelegate(url
);
554 OnCreateSnapshotFileError(callback
, base::File::FILE_ERROR_NOT_FOUND
);
558 scoped_refptr
<base::SequencedTaskRunner
> task_runner(context
->task_runner());
559 base::PostTaskAndReplyWithResult(
560 task_runner
.get(), FROM_HERE
,
561 base::Bind(&CreateSnapshotFileOnBlockingPool
, profile_path_
),
562 base::Bind(&OnSnapshotFileCreatedRunTask
, base::Passed(&context
),
563 callback
, url
, validate_media_files()));
566 scoped_ptr
<storage::FileStreamReader
>
567 DeviceMediaAsyncFileUtil::GetFileStreamReader(
568 const FileSystemURL
& url
,
570 const base::Time
& expected_modification_time
,
571 storage::FileSystemContext
* context
) {
572 MTPDeviceAsyncDelegate
* delegate
= GetMTPDeviceDelegate(url
);
574 return scoped_ptr
<storage::FileStreamReader
>();
576 DCHECK(delegate
->IsStreaming());
577 return scoped_ptr
<storage::FileStreamReader
>(new ReadaheadFileStreamReader(
578 new MTPFileStreamReader(context
,
581 expected_modification_time
,
582 validate_media_files())));
585 void DeviceMediaAsyncFileUtil::AddWatcher(
586 const storage::FileSystemURL
& url
,
588 const storage::WatcherManager::StatusCallback
& callback
,
589 const storage::WatcherManager::NotificationCallback
&
590 notification_callback
) {
591 MTPDeviceAsyncDelegate
* const delegate
= GetMTPDeviceDelegate(url
);
593 callback
.Run(base::File::FILE_ERROR_FAILED
);
597 delegate
->AddWatcher(url
.origin(), url
.path(), recursive
, callback
,
598 notification_callback
);
601 void DeviceMediaAsyncFileUtil::RemoveWatcher(
602 const storage::FileSystemURL
& url
,
603 const bool recursive
,
604 const storage::WatcherManager::StatusCallback
& callback
) {
605 MTPDeviceAsyncDelegate
* const delegate
= GetMTPDeviceDelegate(url
);
607 callback
.Run(base::File::FILE_ERROR_FAILED
);
611 delegate
->RemoveWatcher(url
.origin(), url
.path(), recursive
, callback
);
614 DeviceMediaAsyncFileUtil::DeviceMediaAsyncFileUtil(
615 const base::FilePath
& profile_path
,
616 MediaFileValidationType validation_type
)
617 : profile_path_(profile_path
),
618 weak_ptr_factory_(this) {
619 if (validation_type
== APPLY_MEDIA_FILE_VALIDATION
) {
620 media_path_filter_wrapper_
= new MediaPathFilterWrapper
;
624 void DeviceMediaAsyncFileUtil::OnDidCreateDirectory(
625 const StatusCallback
& callback
) {
626 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
628 callback
.Run(base::File::FILE_OK
);
631 void DeviceMediaAsyncFileUtil::OnDidGetFileInfo(
632 base::SequencedTaskRunner
* task_runner
,
633 const base::FilePath
& path
,
634 const AsyncFileUtil::GetFileInfoCallback
& callback
,
635 const base::File::Info
& file_info
) {
636 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
637 if (file_info
.is_directory
|| !validate_media_files()) {
638 OnDidCheckMediaForGetFileInfo(callback
, file_info
, true /* valid */);
642 base::PostTaskAndReplyWithResult(
645 base::Bind(&MediaPathFilterWrapper::CheckFilePath
,
646 media_path_filter_wrapper_
,
648 base::Bind(&OnDidCheckMediaForGetFileInfo
, callback
, file_info
));
651 void DeviceMediaAsyncFileUtil::OnDidReadDirectory(
652 base::SequencedTaskRunner
* task_runner
,
653 const AsyncFileUtil::ReadDirectoryCallback
& callback
,
654 const AsyncFileUtil::EntryList
& file_list
,
656 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
657 if (!validate_media_files()) {
658 OnDidCheckMediaForReadDirectory(callback
, has_more
, file_list
);
662 base::PostTaskAndReplyWithResult(
665 base::Bind(&MediaPathFilterWrapper::FilterMediaEntries
,
666 media_path_filter_wrapper_
,
668 base::Bind(&OnDidCheckMediaForReadDirectory
, callback
, has_more
));
671 void DeviceMediaAsyncFileUtil::OnDidCopyFileLocal(
672 const StatusCallback
& callback
) {
673 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
675 callback
.Run(base::File::FILE_OK
);
678 void DeviceMediaAsyncFileUtil::OnDidMoveFileLocal(
679 const StatusCallback
& callback
) {
680 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
682 callback
.Run(base::File::FILE_OK
);
685 void DeviceMediaAsyncFileUtil::OnDidCopyInForeignFile(
686 const StatusCallback
& callback
) {
687 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
689 callback
.Run(base::File::FILE_OK
);
692 void DeviceMediaAsyncFileUtil::OnDidDeleteFile(const StatusCallback
& callback
) {
693 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
695 callback
.Run(base::File::FILE_OK
);
698 void DeviceMediaAsyncFileUtil::OnDidDeleteDirectory(
699 const StatusCallback
& callback
) {
700 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
702 callback
.Run(base::File::FILE_OK
);
705 bool DeviceMediaAsyncFileUtil::validate_media_files() const {
706 return media_path_filter_wrapper_
.get() != NULL
;