- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / media_galleries / fileapi / device_media_async_file_util.cc
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.
4
5 #include "chrome/browser/media_galleries/fileapi/device_media_async_file_util.h"
6
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/native_media_file_util.h"
15 #include "content/public/browser/browser_thread.h"
16 #include "webkit/browser/fileapi/file_system_operation_context.h"
17 #include "webkit/browser/fileapi/file_system_url.h"
18 #include "webkit/common/blob/shareable_file_reference.h"
19
20 using fileapi::FileSystemOperationContext;
21 using fileapi::FileSystemURL;
22 using webkit_blob::ShareableFileReference;
23
24 namespace {
25
26 const char kDeviceMediaAsyncFileUtilTempDir[] = "DeviceMediaFileSystem";
27
28 // Called on the IO thread.
29 MTPDeviceAsyncDelegate* GetMTPDeviceDelegate(const FileSystemURL& url) {
30   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
31   return MTPDeviceMapService::GetInstance()->GetMTPDeviceAsyncDelegate(
32       url.filesystem_id());
33 }
34
35 // Called on a blocking pool thread to create a snapshot file to hold the
36 // contents of |device_file_path|. The snapshot file is created in
37 // "profile_path/kDeviceMediaAsyncFileUtilTempDir" directory. If the snapshot
38 // file is created successfully, |snapshot_file_path| will be a non-empty file
39 // path. In case of failure, the |snapshot_file_path| will be an empty file
40 // path.
41 void CreateSnapshotFileOnBlockingPool(
42     const base::FilePath& device_file_path,
43     const base::FilePath& profile_path,
44     base::FilePath* snapshot_file_path) {
45   DCHECK(snapshot_file_path);
46   base::FilePath isolated_media_file_system_dir_path =
47       profile_path.AppendASCII(kDeviceMediaAsyncFileUtilTempDir);
48   if (!file_util::CreateDirectory(isolated_media_file_system_dir_path) ||
49       !file_util::CreateTemporaryFileInDir(isolated_media_file_system_dir_path,
50                                            snapshot_file_path)) {
51     LOG(WARNING) << "Could not create media snapshot file "
52                  << isolated_media_file_system_dir_path.value();
53     *snapshot_file_path = base::FilePath();
54   }
55 }
56
57 }  // namespace
58
59 DeviceMediaAsyncFileUtil::~DeviceMediaAsyncFileUtil() {
60 }
61
62 // static
63 DeviceMediaAsyncFileUtil* DeviceMediaAsyncFileUtil::Create(
64     const base::FilePath& profile_path) {
65   DCHECK(!profile_path.empty());
66   return new DeviceMediaAsyncFileUtil(profile_path);
67 }
68
69 void DeviceMediaAsyncFileUtil::CreateOrOpen(
70     scoped_ptr<FileSystemOperationContext> context,
71     const FileSystemURL& url,
72     int file_flags,
73     const CreateOrOpenCallback& callback) {
74   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
75   NOTIMPLEMENTED();
76   base::PlatformFile invalid_file = base::kInvalidPlatformFileValue;
77   callback.Run(base::PLATFORM_FILE_ERROR_SECURITY,
78                base::PassPlatformFile(&invalid_file),
79                base::Closure());
80 }
81
82 void DeviceMediaAsyncFileUtil::EnsureFileExists(
83     scoped_ptr<FileSystemOperationContext> context,
84     const FileSystemURL& url,
85     const EnsureFileExistsCallback& callback) {
86   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
87   NOTIMPLEMENTED();
88   callback.Run(base::PLATFORM_FILE_ERROR_SECURITY, false);
89 }
90
91 void DeviceMediaAsyncFileUtil::CreateDirectory(
92     scoped_ptr<FileSystemOperationContext> context,
93     const FileSystemURL& url,
94     bool exclusive,
95     bool recursive,
96     const StatusCallback& callback) {
97   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
98   NOTIMPLEMENTED();
99   callback.Run(base::PLATFORM_FILE_ERROR_SECURITY);
100 }
101
102 void DeviceMediaAsyncFileUtil::GetFileInfo(
103     scoped_ptr<FileSystemOperationContext> context,
104     const FileSystemURL& url,
105     const GetFileInfoCallback& callback) {
106   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
107   MTPDeviceAsyncDelegate* delegate = GetMTPDeviceDelegate(url);
108   if (!delegate) {
109     OnGetFileInfoError(callback, base::PLATFORM_FILE_ERROR_NOT_FOUND);
110     return;
111   }
112   delegate->GetFileInfo(
113       url.path(),
114       base::Bind(&DeviceMediaAsyncFileUtil::OnDidGetFileInfo,
115                  weak_ptr_factory_.GetWeakPtr(),
116                  callback),
117       base::Bind(&DeviceMediaAsyncFileUtil::OnGetFileInfoError,
118                  weak_ptr_factory_.GetWeakPtr(),
119                  callback));
120 }
121
122 void DeviceMediaAsyncFileUtil::ReadDirectory(
123     scoped_ptr<FileSystemOperationContext> context,
124     const FileSystemURL& url,
125     const ReadDirectoryCallback& callback) {
126   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
127   MTPDeviceAsyncDelegate* delegate = GetMTPDeviceDelegate(url);
128   if (!delegate) {
129     OnReadDirectoryError(callback, base::PLATFORM_FILE_ERROR_NOT_FOUND);
130     return;
131   }
132   delegate->ReadDirectory(
133       url.path(),
134       base::Bind(&DeviceMediaAsyncFileUtil::OnDidReadDirectory,
135                  weak_ptr_factory_.GetWeakPtr(),
136                  callback),
137       base::Bind(&DeviceMediaAsyncFileUtil::OnReadDirectoryError,
138                  weak_ptr_factory_.GetWeakPtr(),
139                  callback));
140 }
141
142 void DeviceMediaAsyncFileUtil::Touch(
143     scoped_ptr<FileSystemOperationContext> context,
144     const FileSystemURL& url,
145     const base::Time& last_access_time,
146     const base::Time& last_modified_time,
147     const StatusCallback& callback) {
148   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
149   NOTIMPLEMENTED();
150   callback.Run(base::PLATFORM_FILE_ERROR_SECURITY);
151 }
152
153 void DeviceMediaAsyncFileUtil::Truncate(
154     scoped_ptr<FileSystemOperationContext> context,
155     const FileSystemURL& url,
156     int64 length,
157     const StatusCallback& callback) {
158   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
159   NOTIMPLEMENTED();
160   callback.Run(base::PLATFORM_FILE_ERROR_SECURITY);
161 }
162
163 void DeviceMediaAsyncFileUtil::CopyFileLocal(
164     scoped_ptr<FileSystemOperationContext> context,
165     const FileSystemURL& src_url,
166     const FileSystemURL& dest_url,
167     CopyOrMoveOption option,
168     const CopyFileProgressCallback& progress_callback,
169     const StatusCallback& callback) {
170   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
171   NOTIMPLEMENTED();
172   callback.Run(base::PLATFORM_FILE_ERROR_SECURITY);
173 }
174
175 void DeviceMediaAsyncFileUtil::MoveFileLocal(
176     scoped_ptr<FileSystemOperationContext> context,
177     const FileSystemURL& src_url,
178     const FileSystemURL& dest_url,
179     CopyOrMoveOption option,
180     const StatusCallback& callback) {
181   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
182   NOTIMPLEMENTED();
183   callback.Run(base::PLATFORM_FILE_ERROR_SECURITY);
184 }
185
186 void DeviceMediaAsyncFileUtil::CopyInForeignFile(
187     scoped_ptr<FileSystemOperationContext> context,
188     const base::FilePath& src_file_path,
189     const FileSystemURL& dest_url,
190     const StatusCallback& callback) {
191   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
192   NOTIMPLEMENTED();
193   callback.Run(base::PLATFORM_FILE_ERROR_SECURITY);
194 }
195
196 void DeviceMediaAsyncFileUtil::DeleteFile(
197     scoped_ptr<FileSystemOperationContext> context,
198     const FileSystemURL& url,
199     const StatusCallback& callback) {
200   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
201   NOTIMPLEMENTED();
202   callback.Run(base::PLATFORM_FILE_ERROR_SECURITY);
203 }
204
205 void DeviceMediaAsyncFileUtil::DeleteDirectory(
206     scoped_ptr<FileSystemOperationContext> context,
207     const FileSystemURL& url,
208     const StatusCallback& callback) {
209   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
210   NOTIMPLEMENTED();
211   callback.Run(base::PLATFORM_FILE_ERROR_SECURITY);
212 }
213
214 void DeviceMediaAsyncFileUtil::DeleteRecursively(
215     scoped_ptr<FileSystemOperationContext> context,
216     const FileSystemURL& url,
217     const StatusCallback& callback) {
218   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
219   callback.Run(base::PLATFORM_FILE_ERROR_INVALID_OPERATION);
220 }
221
222 void DeviceMediaAsyncFileUtil::CreateSnapshotFile(
223     scoped_ptr<FileSystemOperationContext> context,
224     const FileSystemURL& url,
225     const CreateSnapshotFileCallback& callback) {
226   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
227   MTPDeviceAsyncDelegate* delegate = GetMTPDeviceDelegate(url);
228   if (!delegate) {
229     OnCreateSnapshotFileError(callback, base::PLATFORM_FILE_ERROR_NOT_FOUND);
230     return;
231   }
232   base::FilePath* snapshot_file_path = new base::FilePath;
233   base::SequencedTaskRunner* task_runner = context->task_runner();
234   const bool success = task_runner->PostTaskAndReply(
235           FROM_HERE,
236           base::Bind(&CreateSnapshotFileOnBlockingPool,
237                      url.path(),
238                      profile_path_,
239                      base::Unretained(snapshot_file_path)),
240           base::Bind(&DeviceMediaAsyncFileUtil::OnSnapshotFileCreatedRunTask,
241                      weak_ptr_factory_.GetWeakPtr(),
242                      base::Passed(&context),
243                      callback,
244                      url,
245                      base::Owned(snapshot_file_path)));
246   DCHECK(success);
247 }
248
249 DeviceMediaAsyncFileUtil::DeviceMediaAsyncFileUtil(
250     const base::FilePath& profile_path)
251     : profile_path_(profile_path),
252       weak_ptr_factory_(this) {
253 }
254
255 void DeviceMediaAsyncFileUtil::OnDidGetFileInfo(
256     const AsyncFileUtil::GetFileInfoCallback& callback,
257     const base::PlatformFileInfo& file_info) {
258   callback.Run(base::PLATFORM_FILE_OK, file_info);
259 }
260
261 void DeviceMediaAsyncFileUtil::OnGetFileInfoError(
262     const AsyncFileUtil::GetFileInfoCallback& callback,
263     base::PlatformFileError error) {
264   callback.Run(error, base::PlatformFileInfo());
265 }
266
267 void DeviceMediaAsyncFileUtil::OnDidReadDirectory(
268     const AsyncFileUtil::ReadDirectoryCallback& callback,
269     const AsyncFileUtil::EntryList& file_list,
270     bool has_more) {
271   callback.Run(base::PLATFORM_FILE_OK, file_list, has_more);
272 }
273
274 void DeviceMediaAsyncFileUtil::OnReadDirectoryError(
275     const AsyncFileUtil::ReadDirectoryCallback& callback,
276     base::PlatformFileError error) {
277   callback.Run(error, AsyncFileUtil::EntryList(), false /*no more*/);
278 }
279
280 void DeviceMediaAsyncFileUtil::OnDidCreateSnapshotFile(
281     const AsyncFileUtil::CreateSnapshotFileCallback& callback,
282     base::SequencedTaskRunner* media_task_runner,
283     const base::PlatformFileInfo& file_info,
284     const base::FilePath& platform_path) {
285   base::PostTaskAndReplyWithResult(
286       media_task_runner,
287       FROM_HERE,
288       base::Bind(&NativeMediaFileUtil::IsMediaFile, platform_path),
289       base::Bind(&DeviceMediaAsyncFileUtil::OnDidCheckMedia,
290                  weak_ptr_factory_.GetWeakPtr(),
291                  callback,
292                  file_info,
293                  ShareableFileReference::GetOrCreate(
294                      platform_path,
295                      ShareableFileReference::DELETE_ON_FINAL_RELEASE,
296                      media_task_runner)));
297 }
298
299 void DeviceMediaAsyncFileUtil::OnDidCheckMedia(
300     const AsyncFileUtil::CreateSnapshotFileCallback& callback,
301     const base::PlatformFileInfo& file_info,
302     scoped_refptr<webkit_blob::ShareableFileReference> platform_file,
303     base::PlatformFileError error) {
304   base::FilePath platform_path(platform_file.get()->path());
305   if (error != base::PLATFORM_FILE_OK)
306     platform_file = NULL;
307   callback.Run(error, file_info, platform_path, platform_file);
308 }
309
310 void DeviceMediaAsyncFileUtil::OnCreateSnapshotFileError(
311     const AsyncFileUtil::CreateSnapshotFileCallback& callback,
312     base::PlatformFileError error) {
313   callback.Run(error, base::PlatformFileInfo(), base::FilePath(),
314                scoped_refptr<ShareableFileReference>());
315 }
316
317 void DeviceMediaAsyncFileUtil::OnSnapshotFileCreatedRunTask(
318     scoped_ptr<FileSystemOperationContext> context,
319     const AsyncFileUtil::CreateSnapshotFileCallback& callback,
320     const FileSystemURL& url,
321     base::FilePath* snapshot_file_path) {
322   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
323   if (!snapshot_file_path || snapshot_file_path->empty()) {
324     OnCreateSnapshotFileError(callback, base::PLATFORM_FILE_ERROR_FAILED);
325     return;
326   }
327   MTPDeviceAsyncDelegate* delegate = GetMTPDeviceDelegate(url);
328   if (!delegate) {
329     OnCreateSnapshotFileError(callback, base::PLATFORM_FILE_ERROR_NOT_FOUND);
330     return;
331   }
332   delegate->CreateSnapshotFile(
333       url.path(),  // device file path
334       *snapshot_file_path,
335       base::Bind(&DeviceMediaAsyncFileUtil::OnDidCreateSnapshotFile,
336                  weak_ptr_factory_.GetWeakPtr(),
337                  callback,
338                  make_scoped_refptr(context->task_runner())),
339       base::Bind(&DeviceMediaAsyncFileUtil::OnCreateSnapshotFileError,
340                  weak_ptr_factory_.GetWeakPtr(),
341                  callback));
342 }