Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / chromeos / file_system_provider / fileapi / provider_async_file_util.cc
1 // Copyright 2014 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/chromeos/file_system_provider/fileapi/provider_async_file_util.h"
6
7 #include "base/callback.h"
8 #include "base/files/file.h"
9 #include "base/files/file_path.h"
10 #include "base/logging.h"
11 #include "chrome/browser/chromeos/file_system_provider/mount_path_util.h"
12 #include "chrome/browser/chromeos/file_system_provider/provided_file_system_interface.h"
13 #include "content/public/browser/browser_thread.h"
14 #include "storage/browser/fileapi/file_system_operation_context.h"
15 #include "storage/browser/fileapi/file_system_url.h"
16 #include "storage/common/blob/shareable_file_reference.h"
17
18 using content::BrowserThread;
19
20 namespace chromeos {
21 namespace file_system_provider {
22 namespace internal {
23 namespace {
24
25 // Executes GetFileInfo on the UI thread.
26 void GetFileInfoOnUIThread(
27     scoped_ptr<storage::FileSystemOperationContext> context,
28     const storage::FileSystemURL& url,
29     const ProvidedFileSystemInterface::GetMetadataCallback& callback) {
30   util::FileSystemURLParser parser(url);
31   if (!parser.Parse()) {
32     callback.Run(make_scoped_ptr<EntryMetadata>(NULL),
33                  base::File::FILE_ERROR_INVALID_OPERATION);
34     return;
35   }
36
37   parser.file_system()->GetMetadata(
38       parser.file_path(),
39       ProvidedFileSystemInterface::METADATA_FIELD_DEFAULT,
40       callback);
41 }
42
43 // Routes the response of GetFileInfo back to the IO thread with a type
44 // conversion.
45 void OnGetFileInfo(const storage::AsyncFileUtil::GetFileInfoCallback& callback,
46                    scoped_ptr<EntryMetadata> metadata,
47                    base::File::Error result) {
48   if (result != base::File::FILE_OK) {
49     BrowserThread::PostTask(BrowserThread::IO,
50                             FROM_HERE,
51                             base::Bind(callback, result, base::File::Info()));
52     return;
53   }
54
55   DCHECK(metadata.get());
56   base::File::Info file_info;
57
58   // TODO(mtomasz): Add support for last modified time and creation time.
59   // See: crbug.com/388540.
60   file_info.size = metadata->size;
61   file_info.is_directory = metadata->is_directory;
62   file_info.is_symbolic_link = false;  // Not supported.
63   file_info.last_modified = metadata->modification_time;
64   file_info.last_accessed = metadata->modification_time;  // Not supported.
65   file_info.creation_time = metadata->modification_time;  // Not supported.
66
67   BrowserThread::PostTask(BrowserThread::IO,
68                           FROM_HERE,
69                           base::Bind(callback, base::File::FILE_OK, file_info));
70 }
71
72 // Executes ReadDirectory on the UI thread.
73 void ReadDirectoryOnUIThread(
74     scoped_ptr<storage::FileSystemOperationContext> context,
75     const storage::FileSystemURL& url,
76     const storage::AsyncFileUtil::ReadDirectoryCallback& callback) {
77   util::FileSystemURLParser parser(url);
78   if (!parser.Parse()) {
79     callback.Run(base::File::FILE_ERROR_INVALID_OPERATION,
80                  storage::AsyncFileUtil::EntryList(),
81                  false /* has_more */);
82     return;
83   }
84
85   parser.file_system()->ReadDirectory(parser.file_path(), callback);
86 }
87
88 // Routes the response of ReadDirectory back to the IO thread.
89 void OnReadDirectory(
90     const storage::AsyncFileUtil::ReadDirectoryCallback& callback,
91     base::File::Error result,
92     const storage::AsyncFileUtil::EntryList& entry_list,
93     bool has_more) {
94   BrowserThread::PostTask(BrowserThread::IO,
95                           FROM_HERE,
96                           base::Bind(callback, result, entry_list, has_more));
97 }
98
99 // Executes CreateDirectory on the UI thread.
100 void CreateDirectoryOnUIThread(
101     scoped_ptr<storage::FileSystemOperationContext> context,
102     const storage::FileSystemURL& url,
103     bool exclusive,
104     bool recursive,
105     const storage::AsyncFileUtil::StatusCallback& callback) {
106   util::FileSystemURLParser parser(url);
107   if (!parser.Parse()) {
108     callback.Run(base::File::FILE_ERROR_INVALID_OPERATION);
109     return;
110   }
111
112   parser.file_system()->CreateDirectory(
113       parser.file_path(), recursive, callback);
114 }
115
116 // Routes the response of CreateDirectory back to the IO thread.
117 void OnCreateDirectory(bool exclusive,
118                        const storage::AsyncFileUtil::StatusCallback& callback,
119                        base::File::Error result) {
120   // If the directory already existed and the operation wasn't exclusive, then
121   // return success anyway, since it is not an error.
122   const base::File::Error error =
123       (result == base::File::FILE_ERROR_EXISTS && !exclusive)
124           ? base::File::FILE_OK
125           : result;
126
127   BrowserThread::PostTask(
128       BrowserThread::IO, FROM_HERE, base::Bind(callback, error));
129 }
130
131 // Executes DeleteEntry on the UI thread.
132 void DeleteEntryOnUIThread(
133     scoped_ptr<storage::FileSystemOperationContext> context,
134     const storage::FileSystemURL& url,
135     bool recursive,
136     const storage::AsyncFileUtil::StatusCallback& callback) {
137   util::FileSystemURLParser parser(url);
138   if (!parser.Parse()) {
139     callback.Run(base::File::FILE_ERROR_INVALID_OPERATION);
140     return;
141   }
142
143   parser.file_system()->DeleteEntry(parser.file_path(), recursive, callback);
144 }
145
146 // Routes the response of DeleteEntry back to the IO thread.
147 void OnDeleteEntry(const storage::AsyncFileUtil::StatusCallback& callback,
148                    base::File::Error result) {
149   BrowserThread::PostTask(
150       BrowserThread::IO, FROM_HERE, base::Bind(callback, result));
151 }
152
153 // Executes CreateFile on the UI thread.
154 void CreateFileOnUIThread(
155     scoped_ptr<storage::FileSystemOperationContext> context,
156     const storage::FileSystemURL& url,
157     const storage::AsyncFileUtil::StatusCallback& callback) {
158   util::FileSystemURLParser parser(url);
159   if (!parser.Parse()) {
160     callback.Run(base::File::FILE_ERROR_INVALID_OPERATION);
161     return;
162   }
163
164   parser.file_system()->CreateFile(parser.file_path(), callback);
165 }
166
167 // Routes the response of CreateFile to a callback of EnsureFileExists() on the
168 // IO thread.
169 void OnCreateFileForEnsureFileExists(
170     const storage::AsyncFileUtil::EnsureFileExistsCallback& callback,
171     base::File::Error result) {
172   const bool created = result == base::File::FILE_OK;
173
174   // If the file already existed, then return success anyway, since it is not
175   // an error.
176   const base::File::Error error =
177       result == base::File::FILE_ERROR_EXISTS ? base::File::FILE_OK : result;
178
179   BrowserThread::PostTask(
180       BrowserThread::IO, FROM_HERE, base::Bind(callback, error, created));
181 }
182
183 // Executes CopyEntry on the UI thread.
184 void CopyEntryOnUIThread(
185     scoped_ptr<storage::FileSystemOperationContext> context,
186     const storage::FileSystemURL& source_url,
187     const storage::FileSystemURL& target_url,
188     const storage::AsyncFileUtil::StatusCallback& callback) {
189   util::FileSystemURLParser source_parser(source_url);
190   util::FileSystemURLParser target_parser(target_url);
191
192   if (!source_parser.Parse() || !target_parser.Parse() ||
193       source_parser.file_system() != target_parser.file_system()) {
194     callback.Run(base::File::FILE_ERROR_INVALID_OPERATION);
195     return;
196   }
197
198   target_parser.file_system()->CopyEntry(
199       source_parser.file_path(), target_parser.file_path(), callback);
200 }
201
202 // Routes the response of CopyEntry to a callback of CopyLocalFile() on the
203 // IO thread.
204 void OnCopyEntry(const storage::AsyncFileUtil::StatusCallback& callback,
205                  base::File::Error result) {
206   BrowserThread::PostTask(
207       BrowserThread::IO, FROM_HERE, base::Bind(callback, result));
208 }
209
210 // Executes MoveEntry on the UI thread.
211 void MoveEntryOnUIThread(
212     scoped_ptr<storage::FileSystemOperationContext> context,
213     const storage::FileSystemURL& source_url,
214     const storage::FileSystemURL& target_url,
215     const storage::AsyncFileUtil::StatusCallback& callback) {
216   util::FileSystemURLParser source_parser(source_url);
217   util::FileSystemURLParser target_parser(target_url);
218
219   if (!source_parser.Parse() || !target_parser.Parse() ||
220       source_parser.file_system() != target_parser.file_system()) {
221     callback.Run(base::File::FILE_ERROR_INVALID_OPERATION);
222     return;
223   }
224
225   target_parser.file_system()->MoveEntry(
226       source_parser.file_path(), target_parser.file_path(), callback);
227 }
228
229 // Routes the response of CopyEntry to a callback of MoveLocalFile() on the
230 // IO thread.
231 void OnMoveEntry(const storage::AsyncFileUtil::StatusCallback& callback,
232                  base::File::Error result) {
233   BrowserThread::PostTask(
234       BrowserThread::IO, FROM_HERE, base::Bind(callback, result));
235 }
236
237 // Executes Truncate on the UI thread.
238 void TruncateOnUIThread(
239     scoped_ptr<storage::FileSystemOperationContext> context,
240     const storage::FileSystemURL& url,
241     int64 length,
242     const storage::AsyncFileUtil::StatusCallback& callback) {
243   util::FileSystemURLParser parser(url);
244   if (!parser.Parse()) {
245     callback.Run(base::File::FILE_ERROR_INVALID_OPERATION);
246     return;
247   }
248
249   parser.file_system()->Truncate(parser.file_path(), length, callback);
250 }
251
252 // Routes the response of Truncate back to the IO thread.
253 void OnTruncate(const storage::AsyncFileUtil::StatusCallback& callback,
254                 base::File::Error result) {
255   BrowserThread::PostTask(
256       BrowserThread::IO, FROM_HERE, base::Bind(callback, result));
257 }
258
259 }  // namespace
260
261 ProviderAsyncFileUtil::ProviderAsyncFileUtil() {}
262
263 ProviderAsyncFileUtil::~ProviderAsyncFileUtil() {}
264
265 void ProviderAsyncFileUtil::CreateOrOpen(
266     scoped_ptr<storage::FileSystemOperationContext> context,
267     const storage::FileSystemURL& url,
268     int file_flags,
269     const CreateOrOpenCallback& callback) {
270   DCHECK_CURRENTLY_ON(BrowserThread::IO);
271   if ((file_flags & base::File::FLAG_CREATE) ||
272       (file_flags & base::File::FLAG_OPEN_ALWAYS) ||
273       (file_flags & base::File::FLAG_CREATE_ALWAYS) ||
274       (file_flags & base::File::FLAG_OPEN_TRUNCATED)) {
275     callback.Run(base::File(base::File::FILE_ERROR_ACCESS_DENIED),
276                  base::Closure());
277     return;
278   }
279
280   NOTIMPLEMENTED();
281   callback.Run(base::File(base::File::FILE_ERROR_INVALID_OPERATION),
282                base::Closure());
283 }
284
285 void ProviderAsyncFileUtil::EnsureFileExists(
286     scoped_ptr<storage::FileSystemOperationContext> context,
287     const storage::FileSystemURL& url,
288     const EnsureFileExistsCallback& callback) {
289   DCHECK_CURRENTLY_ON(BrowserThread::IO);
290   BrowserThread::PostTask(
291       BrowserThread::UI,
292       FROM_HERE,
293       base::Bind(&CreateFileOnUIThread,
294                  base::Passed(&context),
295                  url,
296                  base::Bind(&OnCreateFileForEnsureFileExists, callback)));
297 }
298
299 void ProviderAsyncFileUtil::CreateDirectory(
300     scoped_ptr<storage::FileSystemOperationContext> context,
301     const storage::FileSystemURL& url,
302     bool exclusive,
303     bool recursive,
304     const StatusCallback& callback) {
305   DCHECK_CURRENTLY_ON(BrowserThread::IO);
306   BrowserThread::PostTask(
307       BrowserThread::UI,
308       FROM_HERE,
309       base::Bind(&CreateDirectoryOnUIThread,
310                  base::Passed(&context),
311                  url,
312                  exclusive,
313                  recursive,
314                  base::Bind(&OnCreateDirectory, exclusive, callback)));
315 }
316
317 void ProviderAsyncFileUtil::GetFileInfo(
318     scoped_ptr<storage::FileSystemOperationContext> context,
319     const storage::FileSystemURL& url,
320     const GetFileInfoCallback& callback) {
321   DCHECK_CURRENTLY_ON(BrowserThread::IO);
322   BrowserThread::PostTask(BrowserThread::UI,
323                           FROM_HERE,
324                           base::Bind(&GetFileInfoOnUIThread,
325                                      base::Passed(&context),
326                                      url,
327                                      base::Bind(&OnGetFileInfo, callback)));
328 }
329
330 void ProviderAsyncFileUtil::ReadDirectory(
331     scoped_ptr<storage::FileSystemOperationContext> context,
332     const storage::FileSystemURL& url,
333     const ReadDirectoryCallback& callback) {
334   DCHECK_CURRENTLY_ON(BrowserThread::IO);
335   BrowserThread::PostTask(BrowserThread::UI,
336                           FROM_HERE,
337                           base::Bind(&ReadDirectoryOnUIThread,
338                                      base::Passed(&context),
339                                      url,
340                                      base::Bind(&OnReadDirectory, callback)));
341 }
342
343 void ProviderAsyncFileUtil::Touch(
344     scoped_ptr<storage::FileSystemOperationContext> context,
345     const storage::FileSystemURL& url,
346     const base::Time& last_access_time,
347     const base::Time& last_modified_time,
348     const StatusCallback& callback) {
349   DCHECK_CURRENTLY_ON(BrowserThread::IO);
350   callback.Run(base::File::FILE_ERROR_ACCESS_DENIED);
351 }
352
353 void ProviderAsyncFileUtil::Truncate(
354     scoped_ptr<storage::FileSystemOperationContext> context,
355     const storage::FileSystemURL& url,
356     int64 length,
357     const StatusCallback& callback) {
358   DCHECK_CURRENTLY_ON(BrowserThread::IO);
359   BrowserThread::PostTask(BrowserThread::UI,
360                           FROM_HERE,
361                           base::Bind(&TruncateOnUIThread,
362                                      base::Passed(&context),
363                                      url,
364                                      length,
365                                      base::Bind(&OnTruncate, callback)));
366 }
367
368 void ProviderAsyncFileUtil::CopyFileLocal(
369     scoped_ptr<storage::FileSystemOperationContext> context,
370     const storage::FileSystemURL& src_url,
371     const storage::FileSystemURL& dest_url,
372     CopyOrMoveOption option,
373     const CopyFileProgressCallback& progress_callback,
374     const StatusCallback& callback) {
375   DCHECK_CURRENTLY_ON(BrowserThread::IO);
376   // TODO(mtomasz): Consier adding support for options (preserving last modified
377   // time) as well as the progress callback.
378   BrowserThread::PostTask(BrowserThread::UI,
379                           FROM_HERE,
380                           base::Bind(&CopyEntryOnUIThread,
381                                      base::Passed(&context),
382                                      src_url,
383                                      dest_url,
384                                      base::Bind(&OnCopyEntry, callback)));
385 }
386
387 void ProviderAsyncFileUtil::MoveFileLocal(
388     scoped_ptr<storage::FileSystemOperationContext> context,
389     const storage::FileSystemURL& src_url,
390     const storage::FileSystemURL& dest_url,
391     CopyOrMoveOption option,
392     const StatusCallback& callback) {
393   DCHECK_CURRENTLY_ON(BrowserThread::IO);
394   // TODO(mtomasz): Consier adding support for options (preserving last modified
395   // time) as well as the progress callback.
396   BrowserThread::PostTask(BrowserThread::UI,
397                           FROM_HERE,
398                           base::Bind(&MoveEntryOnUIThread,
399                                      base::Passed(&context),
400                                      src_url,
401                                      dest_url,
402                                      base::Bind(&OnMoveEntry, callback)));
403 }
404
405 void ProviderAsyncFileUtil::CopyInForeignFile(
406     scoped_ptr<storage::FileSystemOperationContext> context,
407     const base::FilePath& src_file_path,
408     const storage::FileSystemURL& dest_url,
409     const StatusCallback& callback) {
410   DCHECK_CURRENTLY_ON(BrowserThread::IO);
411   callback.Run(base::File::FILE_ERROR_ACCESS_DENIED);
412 }
413
414 void ProviderAsyncFileUtil::DeleteFile(
415     scoped_ptr<storage::FileSystemOperationContext> context,
416     const storage::FileSystemURL& url,
417     const StatusCallback& callback) {
418   DCHECK_CURRENTLY_ON(BrowserThread::IO);
419   BrowserThread::PostTask(BrowserThread::UI,
420                           FROM_HERE,
421                           base::Bind(&DeleteEntryOnUIThread,
422                                      base::Passed(&context),
423                                      url,
424                                      false,  // recursive
425                                      base::Bind(&OnDeleteEntry, callback)));
426 }
427
428 void ProviderAsyncFileUtil::DeleteDirectory(
429     scoped_ptr<storage::FileSystemOperationContext> context,
430     const storage::FileSystemURL& url,
431     const StatusCallback& callback) {
432   DCHECK_CURRENTLY_ON(BrowserThread::IO);
433   BrowserThread::PostTask(BrowserThread::UI,
434                           FROM_HERE,
435                           base::Bind(&DeleteEntryOnUIThread,
436                                      base::Passed(&context),
437                                      url,
438                                      false,  // recursive
439                                      base::Bind(&OnDeleteEntry, callback)));
440 }
441
442 void ProviderAsyncFileUtil::DeleteRecursively(
443     scoped_ptr<storage::FileSystemOperationContext> context,
444     const storage::FileSystemURL& url,
445     const StatusCallback& callback) {
446   DCHECK_CURRENTLY_ON(BrowserThread::IO);
447   BrowserThread::PostTask(BrowserThread::UI,
448                           FROM_HERE,
449                           base::Bind(&DeleteEntryOnUIThread,
450                                      base::Passed(&context),
451                                      url,
452                                      true,  // recursive
453                                      base::Bind(&OnDeleteEntry, callback)));
454 }
455
456 void ProviderAsyncFileUtil::CreateSnapshotFile(
457     scoped_ptr<storage::FileSystemOperationContext> context,
458     const storage::FileSystemURL& url,
459     const CreateSnapshotFileCallback& callback) {
460   DCHECK_CURRENTLY_ON(BrowserThread::IO);
461   NOTIMPLEMENTED();
462   callback.Run(base::File::FILE_ERROR_INVALID_OPERATION,
463                base::File::Info(),
464                base::FilePath(),
465                scoped_refptr<storage::ShareableFileReference>());
466 }
467
468 }  // namespace internal
469 }  // namespace file_system_provider
470 }  // namespace chromeos