NaCl: Update revision in DEPS, r12770 -> r12773
[chromium-blink-merge.git] / chrome / browser / media_galleries / fileapi / device_media_async_file_util.cc
blobe28e3f3d51b47c4b30c31eb0c184316503c87aae
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/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 "content/public/browser/browser_thread.h"
17 #include "net/base/io_buffer.h"
18 #include "net/base/mime_sniffer.h"
19 #include "webkit/browser/blob/file_stream_reader.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/file_system_url.h"
23 #include "webkit/common/blob/shareable_file_reference.h"
25 using fileapi::FileSystemOperationContext;
26 using fileapi::FileSystemURL;
27 using webkit_blob::ShareableFileReference;
29 namespace {
31 const char kDeviceMediaAsyncFileUtilTempDir[] = "DeviceMediaFileSystem";
33 // Called on the IO thread.
34 MTPDeviceAsyncDelegate* GetMTPDeviceDelegate(const FileSystemURL& url) {
35 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
36 return MTPDeviceMapService::GetInstance()->GetMTPDeviceAsyncDelegate(
37 url.filesystem_id());
40 // Called on a blocking pool thread to create a snapshot file to hold the
41 // contents of |device_file_path|. The snapshot file is created in
42 // "profile_path/kDeviceMediaAsyncFileUtilTempDir" directory. If the snapshot
43 // file is created successfully, |snapshot_file_path| will be a non-empty file
44 // path. In case of failure, the |snapshot_file_path| will be an empty file
45 // path.
46 void CreateSnapshotFileOnBlockingPool(
47 const base::FilePath& device_file_path,
48 const base::FilePath& profile_path,
49 base::FilePath* snapshot_file_path) {
50 DCHECK(snapshot_file_path);
51 base::FilePath isolated_media_file_system_dir_path =
52 profile_path.AppendASCII(kDeviceMediaAsyncFileUtilTempDir);
53 if (!base::CreateDirectory(isolated_media_file_system_dir_path) ||
54 !base::CreateTemporaryFileInDir(isolated_media_file_system_dir_path,
55 snapshot_file_path)) {
56 LOG(WARNING) << "Could not create media snapshot file "
57 << isolated_media_file_system_dir_path.value();
58 *snapshot_file_path = base::FilePath();
62 } // namespace
64 DeviceMediaAsyncFileUtil::~DeviceMediaAsyncFileUtil() {
67 // static
68 DeviceMediaAsyncFileUtil* DeviceMediaAsyncFileUtil::Create(
69 const base::FilePath& profile_path) {
70 DCHECK(!profile_path.empty());
71 return new DeviceMediaAsyncFileUtil(profile_path);
74 void DeviceMediaAsyncFileUtil::CreateOrOpen(
75 scoped_ptr<FileSystemOperationContext> context,
76 const FileSystemURL& url,
77 int file_flags,
78 const CreateOrOpenCallback& callback) {
79 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
80 NOTIMPLEMENTED();
81 base::PlatformFile invalid_file = base::kInvalidPlatformFileValue;
82 callback.Run(base::File::FILE_ERROR_SECURITY,
83 base::PassPlatformFile(&invalid_file),
84 base::Closure());
87 void DeviceMediaAsyncFileUtil::EnsureFileExists(
88 scoped_ptr<FileSystemOperationContext> context,
89 const FileSystemURL& url,
90 const EnsureFileExistsCallback& callback) {
91 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
92 NOTIMPLEMENTED();
93 callback.Run(base::File::FILE_ERROR_SECURITY, false);
96 void DeviceMediaAsyncFileUtil::CreateDirectory(
97 scoped_ptr<FileSystemOperationContext> context,
98 const FileSystemURL& url,
99 bool exclusive,
100 bool recursive,
101 const StatusCallback& callback) {
102 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
103 NOTIMPLEMENTED();
104 callback.Run(base::File::FILE_ERROR_SECURITY);
107 void DeviceMediaAsyncFileUtil::GetFileInfo(
108 scoped_ptr<FileSystemOperationContext> context,
109 const FileSystemURL& url,
110 const GetFileInfoCallback& callback) {
111 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
112 MTPDeviceAsyncDelegate* delegate = GetMTPDeviceDelegate(url);
113 if (!delegate) {
114 OnGetFileInfoError(callback, base::File::FILE_ERROR_NOT_FOUND);
115 return;
117 delegate->GetFileInfo(
118 url.path(),
119 base::Bind(&DeviceMediaAsyncFileUtil::OnDidGetFileInfo,
120 weak_ptr_factory_.GetWeakPtr(),
121 callback),
122 base::Bind(&DeviceMediaAsyncFileUtil::OnGetFileInfoError,
123 weak_ptr_factory_.GetWeakPtr(),
124 callback));
127 void DeviceMediaAsyncFileUtil::ReadDirectory(
128 scoped_ptr<FileSystemOperationContext> context,
129 const FileSystemURL& url,
130 const ReadDirectoryCallback& callback) {
131 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
132 MTPDeviceAsyncDelegate* delegate = GetMTPDeviceDelegate(url);
133 if (!delegate) {
134 OnReadDirectoryError(callback, base::File::FILE_ERROR_NOT_FOUND);
135 return;
137 delegate->ReadDirectory(
138 url.path(),
139 base::Bind(&DeviceMediaAsyncFileUtil::OnDidReadDirectory,
140 weak_ptr_factory_.GetWeakPtr(),
141 callback),
142 base::Bind(&DeviceMediaAsyncFileUtil::OnReadDirectoryError,
143 weak_ptr_factory_.GetWeakPtr(),
144 callback));
147 void DeviceMediaAsyncFileUtil::Touch(
148 scoped_ptr<FileSystemOperationContext> context,
149 const FileSystemURL& url,
150 const base::Time& last_access_time,
151 const base::Time& last_modified_time,
152 const StatusCallback& callback) {
153 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
154 NOTIMPLEMENTED();
155 callback.Run(base::File::FILE_ERROR_SECURITY);
158 void DeviceMediaAsyncFileUtil::Truncate(
159 scoped_ptr<FileSystemOperationContext> context,
160 const FileSystemURL& url,
161 int64 length,
162 const StatusCallback& callback) {
163 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
164 NOTIMPLEMENTED();
165 callback.Run(base::File::FILE_ERROR_SECURITY);
168 void DeviceMediaAsyncFileUtil::CopyFileLocal(
169 scoped_ptr<FileSystemOperationContext> context,
170 const FileSystemURL& src_url,
171 const FileSystemURL& dest_url,
172 CopyOrMoveOption option,
173 const CopyFileProgressCallback& progress_callback,
174 const StatusCallback& callback) {
175 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
176 NOTIMPLEMENTED();
177 callback.Run(base::File::FILE_ERROR_SECURITY);
180 void DeviceMediaAsyncFileUtil::MoveFileLocal(
181 scoped_ptr<FileSystemOperationContext> context,
182 const FileSystemURL& src_url,
183 const FileSystemURL& dest_url,
184 CopyOrMoveOption option,
185 const StatusCallback& callback) {
186 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
187 NOTIMPLEMENTED();
188 callback.Run(base::File::FILE_ERROR_SECURITY);
191 void DeviceMediaAsyncFileUtil::CopyInForeignFile(
192 scoped_ptr<FileSystemOperationContext> context,
193 const base::FilePath& src_file_path,
194 const FileSystemURL& dest_url,
195 const StatusCallback& callback) {
196 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
197 NOTIMPLEMENTED();
198 callback.Run(base::File::FILE_ERROR_SECURITY);
201 void DeviceMediaAsyncFileUtil::DeleteFile(
202 scoped_ptr<FileSystemOperationContext> context,
203 const FileSystemURL& url,
204 const StatusCallback& callback) {
205 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
206 NOTIMPLEMENTED();
207 callback.Run(base::File::FILE_ERROR_SECURITY);
210 void DeviceMediaAsyncFileUtil::DeleteDirectory(
211 scoped_ptr<FileSystemOperationContext> context,
212 const FileSystemURL& url,
213 const StatusCallback& callback) {
214 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
215 NOTIMPLEMENTED();
216 callback.Run(base::File::FILE_ERROR_SECURITY);
219 void DeviceMediaAsyncFileUtil::DeleteRecursively(
220 scoped_ptr<FileSystemOperationContext> context,
221 const FileSystemURL& url,
222 const StatusCallback& callback) {
223 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
224 callback.Run(base::File::FILE_ERROR_INVALID_OPERATION);
227 void DeviceMediaAsyncFileUtil::CreateSnapshotFile(
228 scoped_ptr<FileSystemOperationContext> context,
229 const FileSystemURL& url,
230 const CreateSnapshotFileCallback& callback) {
231 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
232 MTPDeviceAsyncDelegate* delegate = GetMTPDeviceDelegate(url);
233 if (!delegate) {
234 OnCreateSnapshotFileError(callback, base::File::FILE_ERROR_NOT_FOUND);
235 return;
238 scoped_refptr<base::SequencedTaskRunner> task_runner = context->task_runner();
240 if (delegate->IsStreaming()) {
241 GetFileInfo(
242 context.Pass(),
243 url,
244 base::Bind(&DeviceMediaAsyncFileUtil::GetHeaderBytesForMIMESniffing,
245 weak_ptr_factory_.GetWeakPtr(), url, task_runner, callback));
246 return;
249 base::FilePath* snapshot_file_path = new base::FilePath;
250 const bool success = task_runner->PostTaskAndReply(
251 FROM_HERE,
252 base::Bind(&CreateSnapshotFileOnBlockingPool,
253 url.path(),
254 profile_path_,
255 base::Unretained(snapshot_file_path)),
256 base::Bind(&DeviceMediaAsyncFileUtil::OnSnapshotFileCreatedRunTask,
257 weak_ptr_factory_.GetWeakPtr(),
258 base::Passed(&context),
259 callback,
260 url,
261 base::Owned(snapshot_file_path)));
262 DCHECK(success);
265 scoped_ptr<webkit_blob::FileStreamReader>
266 DeviceMediaAsyncFileUtil::GetFileStreamReader(
267 const FileSystemURL& url,
268 int64 offset,
269 const base::Time& expected_modification_time,
270 fileapi::FileSystemContext* context) {
271 MTPDeviceAsyncDelegate* delegate = GetMTPDeviceDelegate(url);
272 if (!delegate)
273 return scoped_ptr<webkit_blob::FileStreamReader>();
275 DCHECK(delegate->IsStreaming());
276 return scoped_ptr<webkit_blob::FileStreamReader>(new MTPFileStreamReader(
277 context, url, offset, expected_modification_time));
280 DeviceMediaAsyncFileUtil::DeviceMediaAsyncFileUtil(
281 const base::FilePath& profile_path)
282 : profile_path_(profile_path),
283 weak_ptr_factory_(this) {
286 void DeviceMediaAsyncFileUtil::OnDidGetFileInfo(
287 const AsyncFileUtil::GetFileInfoCallback& callback,
288 const base::File::Info& file_info) {
289 callback.Run(base::File::FILE_OK, file_info);
292 void DeviceMediaAsyncFileUtil::OnGetFileInfoError(
293 const AsyncFileUtil::GetFileInfoCallback& callback,
294 base::File::Error error) {
295 callback.Run(error, base::File::Info());
298 void DeviceMediaAsyncFileUtil::OnDidReadDirectory(
299 const AsyncFileUtil::ReadDirectoryCallback& callback,
300 const AsyncFileUtil::EntryList& file_list,
301 bool has_more) {
302 callback.Run(base::File::FILE_OK, file_list, has_more);
305 void DeviceMediaAsyncFileUtil::OnReadDirectoryError(
306 const AsyncFileUtil::ReadDirectoryCallback& callback,
307 base::File::Error error) {
308 callback.Run(error, AsyncFileUtil::EntryList(), false /*no more*/);
311 void DeviceMediaAsyncFileUtil::OnDidCreateSnapshotFile(
312 const AsyncFileUtil::CreateSnapshotFileCallback& callback,
313 base::SequencedTaskRunner* media_task_runner,
314 const base::File::Info& file_info,
315 const base::FilePath& platform_path) {
316 base::PostTaskAndReplyWithResult(
317 media_task_runner,
318 FROM_HERE,
319 base::Bind(&NativeMediaFileUtil::IsMediaFile, platform_path),
320 base::Bind(&DeviceMediaAsyncFileUtil::OnDidCheckMedia,
321 weak_ptr_factory_.GetWeakPtr(),
322 callback,
323 file_info,
324 ShareableFileReference::GetOrCreate(
325 platform_path,
326 ShareableFileReference::DELETE_ON_FINAL_RELEASE,
327 media_task_runner)));
330 void DeviceMediaAsyncFileUtil::OnDidCheckMedia(
331 const AsyncFileUtil::CreateSnapshotFileCallback& callback,
332 const base::File::Info& file_info,
333 scoped_refptr<webkit_blob::ShareableFileReference> platform_file,
334 base::File::Error error) {
335 base::FilePath platform_path(platform_file.get()->path());
336 if (error != base::File::FILE_OK)
337 platform_file = NULL;
338 callback.Run(error, file_info, platform_path, platform_file);
341 void DeviceMediaAsyncFileUtil::GetHeaderBytesForMIMESniffing(
342 const fileapi::FileSystemURL& url,
343 base::SequencedTaskRunner* media_task_runner,
344 const AsyncFileUtil::CreateSnapshotFileCallback& callback,
345 base::File::Error error,
346 const base::File::Info& file_info) {
347 MTPDeviceAsyncDelegate* delegate = GetMTPDeviceDelegate(url);
348 if (!delegate) {
349 OnCreateSnapshotFileError(callback, base::File::FILE_ERROR_NOT_FOUND);
350 return;
353 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(net::kMaxBytesToSniff));
354 delegate->ReadBytes(
355 url.path(),
356 buffer,
358 net::kMaxBytesToSniff,
359 base::Bind(&DeviceMediaAsyncFileUtil::FinishStreamingSnapshotFile,
360 weak_ptr_factory_.GetWeakPtr(), url,
361 make_scoped_refptr(media_task_runner), callback, file_info,
362 buffer),
363 base::Bind(&DeviceMediaAsyncFileUtil::OnCreateSnapshotFileError,
364 weak_ptr_factory_.GetWeakPtr(), callback));
367 void DeviceMediaAsyncFileUtil::FinishStreamingSnapshotFile(
368 const fileapi::FileSystemURL& url,
369 base::SequencedTaskRunner* media_task_runner,
370 const AsyncFileUtil::CreateSnapshotFileCallback& callback,
371 const base::File::Info& file_info,
372 net::IOBuffer* buffer,
373 int buffer_size) {
374 base::File::Error error =
375 NativeMediaFileUtil::BufferIsMediaHeader(buffer, buffer_size);
376 if (error != base::File::FILE_OK) {
377 OnCreateSnapshotFileError(callback, error);
378 return;
380 callback.Run(base::File::FILE_OK, file_info, base::FilePath(),
381 scoped_refptr<ShareableFileReference>());
384 void DeviceMediaAsyncFileUtil::OnCreateSnapshotFileError(
385 const AsyncFileUtil::CreateSnapshotFileCallback& callback,
386 base::File::Error error) {
387 callback.Run(error, base::File::Info(), base::FilePath(),
388 scoped_refptr<ShareableFileReference>());
391 void DeviceMediaAsyncFileUtil::OnSnapshotFileCreatedRunTask(
392 scoped_ptr<FileSystemOperationContext> context,
393 const AsyncFileUtil::CreateSnapshotFileCallback& callback,
394 const FileSystemURL& url,
395 base::FilePath* snapshot_file_path) {
396 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
397 if (!snapshot_file_path || snapshot_file_path->empty()) {
398 OnCreateSnapshotFileError(callback, base::File::FILE_ERROR_FAILED);
399 return;
401 MTPDeviceAsyncDelegate* delegate = GetMTPDeviceDelegate(url);
402 if (!delegate) {
403 OnCreateSnapshotFileError(callback, base::File::FILE_ERROR_NOT_FOUND);
404 return;
406 delegate->CreateSnapshotFile(
407 url.path(), // device file path
408 *snapshot_file_path,
409 base::Bind(&DeviceMediaAsyncFileUtil::OnDidCreateSnapshotFile,
410 weak_ptr_factory_.GetWeakPtr(),
411 callback,
412 make_scoped_refptr(context->task_runner())),
413 base::Bind(&DeviceMediaAsyncFileUtil::OnCreateSnapshotFileError,
414 weak_ptr_factory_.GetWeakPtr(),
415 callback));