12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/media_galleries/fileapi/device_media_async_file_util.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/callback.h"
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/file_util.h"
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/single_thread_task_runner.h"
1090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/task_runner_util.h"
11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/media_galleries/fileapi/media_path_filter.h"
12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/media_galleries/fileapi/mtp_device_async_delegate.h"
13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/media_galleries/fileapi/mtp_device_map_service.h"
145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/media_galleries/fileapi/mtp_file_stream_reader.h"
15a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#include "chrome/browser/media_galleries/fileapi/native_media_file_util.h"
16a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "chrome/browser/media_galleries/fileapi/readahead_file_stream_reader.h"
17bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch#include "content/public/browser/browser_thread.h"
185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "webkit/browser/blob/file_stream_reader.h"
195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "webkit/browser/fileapi/file_system_context.h"
2090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "webkit/browser/fileapi/file_system_operation_context.h"
2190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "webkit/browser/fileapi/file_system_url.h"
22a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "webkit/browser/fileapi/native_file_util.h"
2390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "webkit/common/blob/shareable_file_reference.h"
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
25cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)using fileapi::AsyncFileUtil;
26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using fileapi::FileSystemOperationContext;
27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using fileapi::FileSystemURL;
28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using webkit_blob::ShareableFileReference;
29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
32bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdochconst char kDeviceMediaAsyncFileUtilTempDir[] = "DeviceMediaFileSystem";
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
34bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben MurdochMTPDeviceAsyncDelegate* GetMTPDeviceDelegate(const FileSystemURL& url) {
35e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return MTPDeviceMapService::GetInstance()->GetMTPDeviceAsyncDelegate(
37bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch      url.filesystem_id());
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
40cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Called when GetFileInfo method call failed to get the details of file
41cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// specified by the requested url. |callback| is invoked to notify the
42cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// caller about the file |error|.
43cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void OnGetFileInfoError(const AsyncFileUtil::GetFileInfoCallback& callback,
44cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                        base::File::Error error) {
45cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
46cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  callback.Run(error, base::File::Info());
47cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
48cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
49cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Called after OnDidGetFileInfo finishes media check.
50cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// |callback| is invoked to complete the GetFileInfo request.
51cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void OnDidCheckMediaForGetFileInfo(
52cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const AsyncFileUtil::GetFileInfoCallback& callback,
53cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const base::File::Info& file_info,
54cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    bool is_valid_file) {
55cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
56cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!is_valid_file) {
57cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    OnGetFileInfoError(callback, base::File::FILE_ERROR_NOT_FOUND);
58cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
59cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
60cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  callback.Run(base::File::FILE_OK, file_info);
61cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
62cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
63cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Called after OnDidReadDirectory finishes media check.
64cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// |callback| is invoked to complete the ReadDirectory request.
65cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void OnDidCheckMediaForReadDirectory(
66cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const AsyncFileUtil::ReadDirectoryCallback& callback,
67cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    bool has_more,
68cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const AsyncFileUtil::EntryList& file_list) {
69cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
70cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  callback.Run(base::File::FILE_OK, file_list, has_more);
71cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
72cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
73cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Called when ReadDirectory method call failed to enumerate the directory
74cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// objects. |callback| is invoked to notify the caller about the |error|
75cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// that occured while reading the directory objects.
76cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void OnReadDirectoryError(const AsyncFileUtil::ReadDirectoryCallback& callback,
77cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                          base::File::Error error) {
78cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
79cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  callback.Run(error, AsyncFileUtil::EntryList(), false /*no more*/);
80cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
81cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Called on a blocking pool thread to create a snapshot file to hold the
83a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch// contents of |device_file_path|. The snapshot file is created in the
84a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch// "profile_path/kDeviceMediaAsyncFileUtilTempDir" directory. Return the
85a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch// snapshot file path or an empty path on failure.
86a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochbase::FilePath CreateSnapshotFileOnBlockingPool(
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::FilePath& device_file_path,
88a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    const base::FilePath& profile_path) {
89a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  base::FilePath snapshot_file_path;
90effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  base::FilePath media_file_system_dir_path =
91bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      profile_path.AppendASCII(kDeviceMediaAsyncFileUtilTempDir);
92effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (!base::CreateDirectory(media_file_system_dir_path) ||
93effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      !base::CreateTemporaryFileInDir(media_file_system_dir_path,
94a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                      &snapshot_file_path)) {
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    LOG(WARNING) << "Could not create media snapshot file "
96effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                 << media_file_system_dir_path.value();
97a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    snapshot_file_path = base::FilePath();
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
99a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  return snapshot_file_path;
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
102cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Called after OnDidCreateSnapshotFile finishes media check.
103cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// |callback| is invoked to complete the CreateSnapshotFile request.
104cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void OnDidCheckMediaForCreateSnapshotFile(
105cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const AsyncFileUtil::CreateSnapshotFileCallback& callback,
106cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const base::File::Info& file_info,
107cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    scoped_refptr<webkit_blob::ShareableFileReference> platform_file,
108cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    base::File::Error error) {
109cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
110cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::FilePath platform_path(platform_file.get()->path());
111cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (error != base::File::FILE_OK)
112cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    platform_file = NULL;
113cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  callback.Run(error, file_info, platform_path, platform_file);
114cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
115cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
116cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Called when the snapshot file specified by the |platform_path| is
117cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// successfully created. |file_info| contains the device media file details
118cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// for which the snapshot file is created.
119cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void OnDidCreateSnapshotFile(
120cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const AsyncFileUtil::CreateSnapshotFileCallback& callback,
121cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    base::SequencedTaskRunner* media_task_runner,
122cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    bool validate_media_files,
123cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const base::File::Info& file_info,
124cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const base::FilePath& platform_path) {
125cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
126cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_refptr<webkit_blob::ShareableFileReference> file =
127cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      ShareableFileReference::GetOrCreate(
128cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          platform_path,
129cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          ShareableFileReference::DELETE_ON_FINAL_RELEASE,
130cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          media_task_runner);
131cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
132cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (validate_media_files) {
133cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    base::PostTaskAndReplyWithResult(
134cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        media_task_runner,
135cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        FROM_HERE,
136cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        base::Bind(&NativeMediaFileUtil::IsMediaFile, platform_path),
137cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        base::Bind(&OnDidCheckMediaForCreateSnapshotFile,
138cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                   callback,
139cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                   file_info,
140cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                   file));
141cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  } else {
142cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    OnDidCheckMediaForCreateSnapshotFile(callback, file_info, file,
143cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                         base::File::FILE_OK);
144cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
145cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
146cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
147cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Called when CreateSnapshotFile method call fails. |callback| is invoked to
148cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// notify the caller about the |error|.
149cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void OnCreateSnapshotFileError(
150cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const AsyncFileUtil::CreateSnapshotFileCallback& callback,
151cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    base::File::Error error) {
152cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
153cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  callback.Run(error, base::File::Info(), base::FilePath(),
154cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)               scoped_refptr<ShareableFileReference>());
155cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
156cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
157cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Called when the snapshot file specified by the |snapshot_file_path| is
158cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// created to hold the contents of the url.path(). If the snapshot
159cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// file is successfully created, |snapshot_file_path| will be an non-empty
160cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// file path. In case of failure, |snapshot_file_path| will be an empty file
161cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// path. Forwards the CreateSnapshot request to the delegate to copy the
162cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// contents of url.path() to |snapshot_file_path|.
163cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void OnSnapshotFileCreatedRunTask(
164cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    scoped_ptr<FileSystemOperationContext> context,
165cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const AsyncFileUtil::CreateSnapshotFileCallback& callback,
166cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const FileSystemURL& url,
167cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    bool validate_media_files,
168cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const base::FilePath& snapshot_file_path) {
169cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
170cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (snapshot_file_path.empty()) {
171cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    OnCreateSnapshotFileError(callback, base::File::FILE_ERROR_FAILED);
172cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
173cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
174cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  MTPDeviceAsyncDelegate* delegate = GetMTPDeviceDelegate(url);
175cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!delegate) {
176cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    OnCreateSnapshotFileError(callback, base::File::FILE_ERROR_NOT_FOUND);
177cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
178cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
179cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  delegate->CreateSnapshotFile(
180cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      url.path(),  // device file path
181cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      snapshot_file_path,
182cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      base::Bind(&OnDidCreateSnapshotFile,
183cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 callback,
184cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 make_scoped_refptr(context->task_runner()),
185cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 validate_media_files),
186cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      base::Bind(&OnCreateSnapshotFileError, callback));
187cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
188cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
191cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)class DeviceMediaAsyncFileUtil::MediaPathFilterWrapper
192cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    : public base::RefCountedThreadSafe<MediaPathFilterWrapper> {
193cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) public:
194cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  MediaPathFilterWrapper();
195cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
196cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Check if entries in |file_list| look like media files.
197cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Append the ones that look like media files to |results|.
198cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Should run on a media task runner.
199cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  AsyncFileUtil::EntryList FilterMediaEntries(
200cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      const AsyncFileUtil::EntryList& file_list);
201cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
202cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Check if |path| looks like a media file.
203cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  bool CheckFilePath(const base::FilePath& path);
204cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
205cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) private:
206cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  friend class base::RefCountedThreadSafe<MediaPathFilterWrapper>;
207cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
208cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  virtual ~MediaPathFilterWrapper();
209cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
210cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_ptr<MediaPathFilter> media_path_filter_;
211cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
212cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(MediaPathFilterWrapper);
213cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
214cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
215cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)DeviceMediaAsyncFileUtil::MediaPathFilterWrapper::MediaPathFilterWrapper()
216cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    : media_path_filter_(new MediaPathFilter) {
217cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
218cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
219cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)DeviceMediaAsyncFileUtil::MediaPathFilterWrapper::~MediaPathFilterWrapper() {
220cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
221cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
222cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)AsyncFileUtil::EntryList
223cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)DeviceMediaAsyncFileUtil::MediaPathFilterWrapper::FilterMediaEntries(
224cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const AsyncFileUtil::EntryList& file_list) {
225cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  AsyncFileUtil::EntryList results;
226cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  for (size_t i = 0; i < file_list.size(); ++i) {
227cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const fileapi::DirectoryEntry& entry = file_list[i];
228cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (entry.is_directory || CheckFilePath(base::FilePath(entry.name))) {
229cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      results.push_back(entry);
230cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
231cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
232cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return results;
233cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
234cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
235cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool DeviceMediaAsyncFileUtil::MediaPathFilterWrapper::CheckFilePath(
236cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const base::FilePath& path) {
237cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return media_path_filter_->Match(path);
238cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
239cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)DeviceMediaAsyncFileUtil::~DeviceMediaAsyncFileUtil() {
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
244cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)scoped_ptr<DeviceMediaAsyncFileUtil> DeviceMediaAsyncFileUtil::Create(
2455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    const base::FilePath& profile_path,
2465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    MediaFileValidationType validation_type) {
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!profile_path.empty());
248cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return make_scoped_ptr(
249cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      new DeviceMediaAsyncFileUtil(profile_path, validation_type));
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
252a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool DeviceMediaAsyncFileUtil::SupportsStreaming(
253a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const fileapi::FileSystemURL& url) {
254e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
255a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  MTPDeviceAsyncDelegate* delegate = GetMTPDeviceDelegate(url);
256a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!delegate)
257a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return false;
258a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return delegate->IsStreaming();
259a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
260a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
2617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid DeviceMediaAsyncFileUtil::CreateOrOpen(
262868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    scoped_ptr<FileSystemOperationContext> context,
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const FileSystemURL& url,
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int file_flags,
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const CreateOrOpenCallback& callback) {
266e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
267a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // Returns an error if any unsupported flag is found.
268a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (file_flags & ~(base::File::FLAG_OPEN |
269a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                     base::File::FLAG_READ |
270a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                     base::File::FLAG_WRITE_ATTRIBUTES)) {
271cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    callback.Run(base::File(base::File::FILE_ERROR_SECURITY), base::Closure());
272a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    return;
273a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  }
274a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  CreateSnapshotFile(
275a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      context.Pass(),
276a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      url,
277a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      base::Bind(&NativeMediaFileUtil::CreatedSnapshotFileForCreateOrOpen,
278a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                 make_scoped_refptr(context->task_runner()),
279a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                 file_flags,
280a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                 callback));
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid DeviceMediaAsyncFileUtil::EnsureFileExists(
284868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    scoped_ptr<FileSystemOperationContext> context,
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const FileSystemURL& url,
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const EnsureFileExistsCallback& callback) {
287e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NOTIMPLEMENTED();
2895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  callback.Run(base::File::FILE_ERROR_SECURITY, false);
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid DeviceMediaAsyncFileUtil::CreateDirectory(
293868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    scoped_ptr<FileSystemOperationContext> context,
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const FileSystemURL& url,
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool exclusive,
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool recursive,
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const StatusCallback& callback) {
298e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NOTIMPLEMENTED();
3005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  callback.Run(base::File::FILE_ERROR_SECURITY);
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid DeviceMediaAsyncFileUtil::GetFileInfo(
304868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    scoped_ptr<FileSystemOperationContext> context,
3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const FileSystemURL& url,
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const GetFileInfoCallback& callback) {
307e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
308bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  MTPDeviceAsyncDelegate* delegate = GetMTPDeviceDelegate(url);
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!delegate) {
3105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    OnGetFileInfoError(callback, base::File::FILE_ERROR_NOT_FOUND);
3117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return;
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  delegate->GetFileInfo(
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      url.path(),
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&DeviceMediaAsyncFileUtil::OnDidGetFileInfo,
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr(),
317cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 base::Passed(&context),
318cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 url.path(),
319bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch                 callback),
320cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      base::Bind(&OnGetFileInfoError, callback));
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid DeviceMediaAsyncFileUtil::ReadDirectory(
324868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    scoped_ptr<FileSystemOperationContext> context,
3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const FileSystemURL& url,
3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ReadDirectoryCallback& callback) {
327e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
328bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  MTPDeviceAsyncDelegate* delegate = GetMTPDeviceDelegate(url);
3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!delegate) {
3305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    OnReadDirectoryError(callback, base::File::FILE_ERROR_NOT_FOUND);
3317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return;
3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  delegate->ReadDirectory(
3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      url.path(),
3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&DeviceMediaAsyncFileUtil::OnDidReadDirectory,
3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr(),
337cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 base::Passed(&context),
3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 callback),
339cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      base::Bind(&OnReadDirectoryError, callback));
3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid DeviceMediaAsyncFileUtil::Touch(
343868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    scoped_ptr<FileSystemOperationContext> context,
3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const FileSystemURL& url,
3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::Time& last_access_time,
3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::Time& last_modified_time,
3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const StatusCallback& callback) {
348e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NOTIMPLEMENTED();
3505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  callback.Run(base::File::FILE_ERROR_SECURITY);
3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid DeviceMediaAsyncFileUtil::Truncate(
354868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    scoped_ptr<FileSystemOperationContext> context,
3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const FileSystemURL& url,
3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int64 length,
3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const StatusCallback& callback) {
358e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NOTIMPLEMENTED();
3605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  callback.Run(base::File::FILE_ERROR_SECURITY);
3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid DeviceMediaAsyncFileUtil::CopyFileLocal(
364868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    scoped_ptr<FileSystemOperationContext> context,
3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const FileSystemURL& src_url,
3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const FileSystemURL& dest_url,
36768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    CopyOrMoveOption option,
36858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    const CopyFileProgressCallback& progress_callback,
3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const StatusCallback& callback) {
370e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NOTIMPLEMENTED();
3725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  callback.Run(base::File::FILE_ERROR_SECURITY);
3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid DeviceMediaAsyncFileUtil::MoveFileLocal(
376868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    scoped_ptr<FileSystemOperationContext> context,
3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const FileSystemURL& src_url,
3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const FileSystemURL& dest_url,
37968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    CopyOrMoveOption option,
3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const StatusCallback& callback) {
381e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NOTIMPLEMENTED();
3835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  callback.Run(base::File::FILE_ERROR_SECURITY);
3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid DeviceMediaAsyncFileUtil::CopyInForeignFile(
387868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    scoped_ptr<FileSystemOperationContext> context,
3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::FilePath& src_file_path,
3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const FileSystemURL& dest_url,
3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const StatusCallback& callback) {
391e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NOTIMPLEMENTED();
3935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  callback.Run(base::File::FILE_ERROR_SECURITY);
3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid DeviceMediaAsyncFileUtil::DeleteFile(
397868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    scoped_ptr<FileSystemOperationContext> context,
3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const FileSystemURL& url,
3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const StatusCallback& callback) {
400e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NOTIMPLEMENTED();
4025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  callback.Run(base::File::FILE_ERROR_SECURITY);
4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid DeviceMediaAsyncFileUtil::DeleteDirectory(
406868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    scoped_ptr<FileSystemOperationContext> context,
4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const FileSystemURL& url,
4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const StatusCallback& callback) {
409e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
4102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NOTIMPLEMENTED();
4115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  callback.Run(base::File::FILE_ERROR_SECURITY);
412eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
413eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid DeviceMediaAsyncFileUtil::DeleteRecursively(
415eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_ptr<FileSystemOperationContext> context,
416eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const FileSystemURL& url,
417eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const StatusCallback& callback) {
418e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
4195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  callback.Run(base::File::FILE_ERROR_INVALID_OPERATION);
4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid DeviceMediaAsyncFileUtil::CreateSnapshotFile(
423868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    scoped_ptr<FileSystemOperationContext> context,
4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const FileSystemURL& url,
4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const CreateSnapshotFileCallback& callback) {
426e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
427bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  MTPDeviceAsyncDelegate* delegate = GetMTPDeviceDelegate(url);
4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!delegate) {
4295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    OnCreateSnapshotFileError(callback, base::File::FILE_ERROR_NOT_FOUND);
4307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return;
4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
433a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  scoped_refptr<base::SequencedTaskRunner> task_runner(context->task_runner());
434a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  base::PostTaskAndReplyWithResult(
435a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      task_runner,
436a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      FROM_HERE,
437cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      base::Bind(&CreateSnapshotFileOnBlockingPool, url.path(), profile_path_),
438cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      base::Bind(&OnSnapshotFileCreatedRunTask,
439a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                 base::Passed(&context),
440a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                 callback,
441cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 url,
442cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 validate_media_files()));
4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)scoped_ptr<webkit_blob::FileStreamReader>
4465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)DeviceMediaAsyncFileUtil::GetFileStreamReader(
4475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const FileSystemURL& url,
4485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    int64 offset,
4495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const base::Time& expected_modification_time,
4505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    fileapi::FileSystemContext* context) {
4515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  MTPDeviceAsyncDelegate* delegate = GetMTPDeviceDelegate(url);
4525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!delegate)
4535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return scoped_ptr<webkit_blob::FileStreamReader>();
4545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(delegate->IsStreaming());
456a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return scoped_ptr<webkit_blob::FileStreamReader>(
457cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      new ReadaheadFileStreamReader(
458cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          new MTPFileStreamReader(context,
459cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                  url,
460cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                  offset,
461cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                  expected_modification_time,
462cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                  validate_media_files())));
4635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
4645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)DeviceMediaAsyncFileUtil::DeviceMediaAsyncFileUtil(
4665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    const base::FilePath& profile_path,
4675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    MediaFileValidationType validation_type)
4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : profile_path_(profile_path),
469c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      weak_ptr_factory_(this) {
470cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (validation_type == APPLY_MEDIA_FILE_VALIDATION) {
471cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    media_path_filter_wrapper_ = new MediaPathFilterWrapper;
472cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DeviceMediaAsyncFileUtil::OnDidGetFileInfo(
476cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    scoped_ptr<FileSystemOperationContext> context,
477cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const base::FilePath& path,
4782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const AsyncFileUtil::GetFileInfoCallback& callback,
4795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const base::File::Info& file_info) {
480cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
481cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (file_info.is_directory || !validate_media_files()) {
482cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    OnDidCheckMediaForGetFileInfo(callback, file_info, true /* valid */);
483cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
484cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
486cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::PostTaskAndReplyWithResult(
487cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      context->task_runner(),
488cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      FROM_HERE,
489cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      base::Bind(&MediaPathFilterWrapper::CheckFilePath,
490cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 media_path_filter_wrapper_,
491cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 path),
492cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      base::Bind(&OnDidCheckMediaForGetFileInfo, callback, file_info));
4932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DeviceMediaAsyncFileUtil::OnDidReadDirectory(
496cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    scoped_ptr<fileapi::FileSystemOperationContext> context,
4972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const AsyncFileUtil::ReadDirectoryCallback& callback,
4982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const AsyncFileUtil::EntryList& file_list,
4992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool has_more) {
500cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
501cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!validate_media_files()) {
502cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    OnDidCheckMediaForReadDirectory(callback, has_more, file_list);
503cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
5045c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
505a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
506cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::PostTaskAndReplyWithResult(
507cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      context->task_runner(),
508cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      FROM_HERE,
509cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      base::Bind(&MediaPathFilterWrapper::FilterMediaEntries,
510cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 media_path_filter_wrapper_,
511cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 file_list),
512cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      base::Bind(&OnDidCheckMediaForReadDirectory, callback, has_more));
5132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
515cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool DeviceMediaAsyncFileUtil::validate_media_files() const {
516cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return media_path_filter_wrapper_.get() != NULL;
5172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
518