• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "webkit/browser/fileapi/async_file_util_adapter.h"
6 
7 #include <vector>
8 
9 #include "base/bind.h"
10 #include "base/sequenced_task_runner.h"
11 #include "base/task_runner_util.h"
12 #include "webkit/browser/fileapi/file_system_context.h"
13 #include "webkit/browser/fileapi/file_system_file_util.h"
14 #include "webkit/browser/fileapi/file_system_operation_context.h"
15 #include "webkit/browser/fileapi/file_system_url.h"
16 #include "webkit/common/blob/shareable_file_reference.h"
17 #include "webkit/common/fileapi/file_system_util.h"
18 
19 using base::Bind;
20 using base::Callback;
21 using base::Owned;
22 using base::PlatformFileError;
23 using base::Unretained;
24 using webkit_blob::ShareableFileReference;
25 
26 namespace fileapi {
27 
28 namespace {
29 
30 class EnsureFileExistsHelper {
31  public:
EnsureFileExistsHelper()32   EnsureFileExistsHelper() : error_(base::PLATFORM_FILE_OK), created_(false) {}
33 
RunWork(FileSystemFileUtil * file_util,FileSystemOperationContext * context,const FileSystemURL & url)34   void RunWork(FileSystemFileUtil* file_util,
35                FileSystemOperationContext* context,
36                const FileSystemURL& url) {
37     error_ = file_util->EnsureFileExists(context, url, &created_);
38   }
39 
Reply(const AsyncFileUtil::EnsureFileExistsCallback & callback)40   void Reply(const AsyncFileUtil::EnsureFileExistsCallback& callback) {
41     callback.Run(error_, created_);
42   }
43 
44  private:
45   base::PlatformFileError error_;
46   bool created_;
47   DISALLOW_COPY_AND_ASSIGN(EnsureFileExistsHelper);
48 };
49 
50 class GetFileInfoHelper {
51  public:
GetFileInfoHelper()52   GetFileInfoHelper()
53       : error_(base::PLATFORM_FILE_OK) {}
54 
GetFileInfo(FileSystemFileUtil * file_util,FileSystemOperationContext * context,const FileSystemURL & url)55   void GetFileInfo(FileSystemFileUtil* file_util,
56                    FileSystemOperationContext* context,
57                    const FileSystemURL& url) {
58     error_ = file_util->GetFileInfo(context, url, &file_info_, &platform_path_);
59   }
60 
CreateSnapshotFile(FileSystemFileUtil * file_util,FileSystemOperationContext * context,const FileSystemURL & url)61   void CreateSnapshotFile(FileSystemFileUtil* file_util,
62                           FileSystemOperationContext* context,
63                           const FileSystemURL& url) {
64     scoped_file_ = file_util->CreateSnapshotFile(
65         context, url, &error_, &file_info_, &platform_path_);
66   }
67 
ReplyFileInfo(const AsyncFileUtil::GetFileInfoCallback & callback)68   void ReplyFileInfo(const AsyncFileUtil::GetFileInfoCallback& callback) {
69     callback.Run(error_, file_info_);
70   }
71 
ReplySnapshotFile(const AsyncFileUtil::CreateSnapshotFileCallback & callback)72   void ReplySnapshotFile(
73       const AsyncFileUtil::CreateSnapshotFileCallback& callback) {
74     callback.Run(error_, file_info_, platform_path_,
75                   ShareableFileReference::GetOrCreate(scoped_file_.Pass()));
76   }
77 
78  private:
79   base::PlatformFileError error_;
80   base::PlatformFileInfo file_info_;
81   base::FilePath platform_path_;
82   webkit_blob::ScopedFile scoped_file_;
83   DISALLOW_COPY_AND_ASSIGN(GetFileInfoHelper);
84 };
85 
86 class ReadDirectoryHelper {
87  public:
ReadDirectoryHelper()88   ReadDirectoryHelper() : error_(base::PLATFORM_FILE_OK) {}
89 
RunWork(FileSystemFileUtil * file_util,FileSystemOperationContext * context,const FileSystemURL & url)90   void RunWork(FileSystemFileUtil* file_util,
91                FileSystemOperationContext* context,
92                const FileSystemURL& url) {
93     base::PlatformFileInfo file_info;
94     base::FilePath platform_path;
95     PlatformFileError error = file_util->GetFileInfo(
96         context, url, &file_info, &platform_path);
97     if (error != base::PLATFORM_FILE_OK) {
98       error_ = error;
99       return;
100     }
101     if (!file_info.is_directory) {
102       error_ = base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY;
103       return;
104     }
105 
106     scoped_ptr<FileSystemFileUtil::AbstractFileEnumerator> file_enum(
107         file_util->CreateFileEnumerator(context, url));
108 
109     base::FilePath current;
110     while (!(current = file_enum->Next()).empty()) {
111       DirectoryEntry entry;
112       entry.is_directory = file_enum->IsDirectory();
113       entry.name = VirtualPath::BaseName(current).value();
114       entry.size = file_enum->Size();
115       entry.last_modified_time = file_enum->LastModifiedTime();
116       entries_.push_back(entry);
117     }
118     error_ = base::PLATFORM_FILE_OK;
119   }
120 
Reply(const AsyncFileUtil::ReadDirectoryCallback & callback)121   void Reply(const AsyncFileUtil::ReadDirectoryCallback& callback) {
122     callback.Run(error_, entries_, false /* has_more */);
123   }
124 
125  private:
126   base::PlatformFileError error_;
127   std::vector<DirectoryEntry> entries_;
128   DISALLOW_COPY_AND_ASSIGN(ReadDirectoryHelper);
129 };
130 
RunCreateOrOpenCallback(const AsyncFileUtil::CreateOrOpenCallback & callback,base::PlatformFileError result,base::PassPlatformFile file,bool created)131 void RunCreateOrOpenCallback(
132     const AsyncFileUtil::CreateOrOpenCallback& callback,
133     base::PlatformFileError result,
134     base::PassPlatformFile file,
135     bool created) {
136   callback.Run(result, file, base::Closure());
137 }
138 
139 }  // namespace
140 
AsyncFileUtilAdapter(FileSystemFileUtil * sync_file_util)141 AsyncFileUtilAdapter::AsyncFileUtilAdapter(
142     FileSystemFileUtil* sync_file_util)
143     : sync_file_util_(sync_file_util) {
144   DCHECK(sync_file_util_.get());
145 }
146 
~AsyncFileUtilAdapter()147 AsyncFileUtilAdapter::~AsyncFileUtilAdapter() {
148 }
149 
CreateOrOpen(scoped_ptr<FileSystemOperationContext> context,const FileSystemURL & url,int file_flags,const CreateOrOpenCallback & callback)150 void AsyncFileUtilAdapter::CreateOrOpen(
151     scoped_ptr<FileSystemOperationContext> context,
152     const FileSystemURL& url,
153     int file_flags,
154     const CreateOrOpenCallback& callback) {
155   FileSystemOperationContext* context_ptr = context.release();
156   const bool success = base::FileUtilProxy::RelayCreateOrOpen(
157       context_ptr->task_runner(),
158       Bind(&FileSystemFileUtil::CreateOrOpen, Unretained(sync_file_util_.get()),
159            context_ptr, url, file_flags),
160       Bind(&FileSystemFileUtil::Close, Unretained(sync_file_util_.get()),
161            base::Owned(context_ptr)),
162       Bind(&RunCreateOrOpenCallback, callback));
163   DCHECK(success);
164 }
165 
EnsureFileExists(scoped_ptr<FileSystemOperationContext> context,const FileSystemURL & url,const EnsureFileExistsCallback & callback)166 void AsyncFileUtilAdapter::EnsureFileExists(
167     scoped_ptr<FileSystemOperationContext> context,
168     const FileSystemURL& url,
169     const EnsureFileExistsCallback& callback) {
170   EnsureFileExistsHelper* helper = new EnsureFileExistsHelper;
171   FileSystemOperationContext* context_ptr = context.release();
172   const bool success = context_ptr->task_runner()->PostTaskAndReply(
173       FROM_HERE,
174       Bind(&EnsureFileExistsHelper::RunWork, Unretained(helper),
175            sync_file_util_.get(), base::Owned(context_ptr), url),
176       Bind(&EnsureFileExistsHelper::Reply, Owned(helper), callback));
177   DCHECK(success);
178 }
179 
CreateDirectory(scoped_ptr<FileSystemOperationContext> context,const FileSystemURL & url,bool exclusive,bool recursive,const StatusCallback & callback)180 void AsyncFileUtilAdapter::CreateDirectory(
181     scoped_ptr<FileSystemOperationContext> context,
182     const FileSystemURL& url,
183     bool exclusive,
184     bool recursive,
185     const StatusCallback& callback) {
186   FileSystemOperationContext* context_ptr = context.release();
187   const bool success = base::PostTaskAndReplyWithResult(
188       context_ptr->task_runner(), FROM_HERE,
189       Bind(&FileSystemFileUtil::CreateDirectory,
190            Unretained(sync_file_util_.get()),
191            base::Owned(context_ptr), url, exclusive, recursive),
192       callback);
193   DCHECK(success);
194 }
195 
GetFileInfo(scoped_ptr<FileSystemOperationContext> context,const FileSystemURL & url,const GetFileInfoCallback & callback)196 void AsyncFileUtilAdapter::GetFileInfo(
197     scoped_ptr<FileSystemOperationContext> context,
198     const FileSystemURL& url,
199     const GetFileInfoCallback& callback) {
200   FileSystemOperationContext* context_ptr = context.release();
201   GetFileInfoHelper* helper = new GetFileInfoHelper;
202   const bool success = context_ptr->task_runner()->PostTaskAndReply(
203       FROM_HERE,
204       Bind(&GetFileInfoHelper::GetFileInfo, Unretained(helper),
205            sync_file_util_.get(), base::Owned(context_ptr), url),
206       Bind(&GetFileInfoHelper::ReplyFileInfo, Owned(helper), callback));
207   DCHECK(success);
208 }
209 
ReadDirectory(scoped_ptr<FileSystemOperationContext> context,const FileSystemURL & url,const ReadDirectoryCallback & callback)210 void AsyncFileUtilAdapter::ReadDirectory(
211     scoped_ptr<FileSystemOperationContext> context,
212     const FileSystemURL& url,
213     const ReadDirectoryCallback& callback) {
214   FileSystemOperationContext* context_ptr = context.release();
215   ReadDirectoryHelper* helper = new ReadDirectoryHelper;
216   const bool success = context_ptr->task_runner()->PostTaskAndReply(
217       FROM_HERE,
218       Bind(&ReadDirectoryHelper::RunWork, Unretained(helper),
219            sync_file_util_.get(), base::Owned(context_ptr), url),
220       Bind(&ReadDirectoryHelper::Reply, Owned(helper), callback));
221   DCHECK(success);
222 }
223 
Touch(scoped_ptr<FileSystemOperationContext> context,const FileSystemURL & url,const base::Time & last_access_time,const base::Time & last_modified_time,const StatusCallback & callback)224 void AsyncFileUtilAdapter::Touch(
225     scoped_ptr<FileSystemOperationContext> context,
226     const FileSystemURL& url,
227     const base::Time& last_access_time,
228     const base::Time& last_modified_time,
229     const StatusCallback& callback) {
230   FileSystemOperationContext* context_ptr = context.release();
231   const bool success = base::PostTaskAndReplyWithResult(
232       context_ptr->task_runner(), FROM_HERE,
233       Bind(&FileSystemFileUtil::Touch, Unretained(sync_file_util_.get()),
234            base::Owned(context_ptr), url,
235            last_access_time, last_modified_time),
236       callback);
237   DCHECK(success);
238 }
239 
Truncate(scoped_ptr<FileSystemOperationContext> context,const FileSystemURL & url,int64 length,const StatusCallback & callback)240 void AsyncFileUtilAdapter::Truncate(
241     scoped_ptr<FileSystemOperationContext> context,
242     const FileSystemURL& url,
243     int64 length,
244     const StatusCallback& callback) {
245   FileSystemOperationContext* context_ptr = context.release();
246   const bool success = base::PostTaskAndReplyWithResult(
247       context_ptr->task_runner(), FROM_HERE,
248       Bind(&FileSystemFileUtil::Truncate, Unretained(sync_file_util_.get()),
249            base::Owned(context_ptr), url, length),
250       callback);
251   DCHECK(success);
252 }
253 
CopyFileLocal(scoped_ptr<FileSystemOperationContext> context,const FileSystemURL & src_url,const FileSystemURL & dest_url,CopyOrMoveOption option,const CopyFileProgressCallback & progress_callback,const StatusCallback & callback)254 void AsyncFileUtilAdapter::CopyFileLocal(
255     scoped_ptr<FileSystemOperationContext> context,
256     const FileSystemURL& src_url,
257     const FileSystemURL& dest_url,
258     CopyOrMoveOption option,
259     const CopyFileProgressCallback& progress_callback,
260     const StatusCallback& callback) {
261   // TODO(hidehiko): Support progress_callback.
262   FileSystemOperationContext* context_ptr = context.release();
263   const bool success = base::PostTaskAndReplyWithResult(
264       context_ptr->task_runner(), FROM_HERE,
265       Bind(&FileSystemFileUtil::CopyOrMoveFile,
266            Unretained(sync_file_util_.get()), base::Owned(context_ptr),
267            src_url, dest_url, option, true /* copy */),
268       callback);
269   DCHECK(success);
270 }
271 
MoveFileLocal(scoped_ptr<FileSystemOperationContext> context,const FileSystemURL & src_url,const FileSystemURL & dest_url,CopyOrMoveOption option,const StatusCallback & callback)272 void AsyncFileUtilAdapter::MoveFileLocal(
273     scoped_ptr<FileSystemOperationContext> context,
274     const FileSystemURL& src_url,
275     const FileSystemURL& dest_url,
276     CopyOrMoveOption option,
277     const StatusCallback& callback) {
278   FileSystemOperationContext* context_ptr = context.release();
279   const bool success = base::PostTaskAndReplyWithResult(
280       context_ptr->task_runner(), FROM_HERE,
281       Bind(&FileSystemFileUtil::CopyOrMoveFile,
282            Unretained(sync_file_util_.get()), base::Owned(context_ptr),
283            src_url, dest_url, option, false /* copy */),
284       callback);
285   DCHECK(success);
286 }
287 
CopyInForeignFile(scoped_ptr<FileSystemOperationContext> context,const base::FilePath & src_file_path,const FileSystemURL & dest_url,const StatusCallback & callback)288 void AsyncFileUtilAdapter::CopyInForeignFile(
289       scoped_ptr<FileSystemOperationContext> context,
290       const base::FilePath& src_file_path,
291       const FileSystemURL& dest_url,
292       const StatusCallback& callback) {
293   FileSystemOperationContext* context_ptr = context.release();
294   const bool success = base::PostTaskAndReplyWithResult(
295       context_ptr->task_runner(), FROM_HERE,
296       Bind(&FileSystemFileUtil::CopyInForeignFile,
297            Unretained(sync_file_util_.get()),
298            base::Owned(context_ptr), src_file_path, dest_url),
299       callback);
300   DCHECK(success);
301 }
302 
DeleteFile(scoped_ptr<FileSystemOperationContext> context,const FileSystemURL & url,const StatusCallback & callback)303 void AsyncFileUtilAdapter::DeleteFile(
304     scoped_ptr<FileSystemOperationContext> context,
305     const FileSystemURL& url,
306     const StatusCallback& callback) {
307   FileSystemOperationContext* context_ptr = context.release();
308   const bool success = base::PostTaskAndReplyWithResult(
309       context_ptr->task_runner(), FROM_HERE,
310       Bind(&FileSystemFileUtil::DeleteFile,
311            Unretained(sync_file_util_.get()),
312            base::Owned(context_ptr), url),
313       callback);
314   DCHECK(success);
315 }
316 
DeleteDirectory(scoped_ptr<FileSystemOperationContext> context,const FileSystemURL & url,const StatusCallback & callback)317 void AsyncFileUtilAdapter::DeleteDirectory(
318     scoped_ptr<FileSystemOperationContext> context,
319     const FileSystemURL& url,
320     const StatusCallback& callback) {
321   FileSystemOperationContext* context_ptr = context.release();
322   const bool success = base::PostTaskAndReplyWithResult(
323       context_ptr->task_runner(), FROM_HERE,
324       Bind(&FileSystemFileUtil::DeleteDirectory,
325            Unretained(sync_file_util_.get()),
326            base::Owned(context_ptr), url),
327       callback);
328   DCHECK(success);
329 }
330 
DeleteRecursively(scoped_ptr<FileSystemOperationContext> context,const FileSystemURL & url,const StatusCallback & callback)331 void AsyncFileUtilAdapter::DeleteRecursively(
332     scoped_ptr<FileSystemOperationContext> context,
333     const FileSystemURL& url,
334     const StatusCallback& callback) {
335   callback.Run(base::PLATFORM_FILE_ERROR_INVALID_OPERATION);
336 }
337 
CreateSnapshotFile(scoped_ptr<FileSystemOperationContext> context,const FileSystemURL & url,const CreateSnapshotFileCallback & callback)338 void AsyncFileUtilAdapter::CreateSnapshotFile(
339     scoped_ptr<FileSystemOperationContext> context,
340     const FileSystemURL& url,
341     const CreateSnapshotFileCallback& callback) {
342   FileSystemOperationContext* context_ptr = context.release();
343   GetFileInfoHelper* helper = new GetFileInfoHelper;
344   const bool success = context_ptr->task_runner()->PostTaskAndReply(
345       FROM_HERE,
346       Bind(&GetFileInfoHelper::CreateSnapshotFile, Unretained(helper),
347            sync_file_util_.get(), base::Owned(context_ptr), url),
348       Bind(&GetFileInfoHelper::ReplySnapshotFile, Owned(helper), callback));
349   DCHECK(success);
350 }
351 
352 }  // namespace fileapi
353