OLD | NEW |
| (Empty) |
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 "base/thread_task_runner_handle.h" | |
13 #include "webkit/browser/fileapi/file_system_context.h" | |
14 #include "webkit/browser/fileapi/file_system_file_util.h" | |
15 #include "webkit/browser/fileapi/file_system_operation_context.h" | |
16 #include "webkit/browser/fileapi/file_system_url.h" | |
17 #include "webkit/common/blob/shareable_file_reference.h" | |
18 #include "webkit/common/fileapi/file_system_util.h" | |
19 | |
20 using base::Bind; | |
21 using base::Callback; | |
22 using base::Owned; | |
23 using base::Unretained; | |
24 using storage::ShareableFileReference; | |
25 | |
26 namespace storage { | |
27 | |
28 namespace { | |
29 | |
30 class EnsureFileExistsHelper { | |
31 public: | |
32 EnsureFileExistsHelper() : error_(base::File::FILE_OK), created_(false) {} | |
33 | |
34 void RunWork(FileSystemFileUtil* file_util, | |
35 FileSystemOperationContext* context, | |
36 const FileSystemURL& url) { | |
37 error_ = file_util->EnsureFileExists(context, url, &created_); | |
38 } | |
39 | |
40 void Reply(const AsyncFileUtil::EnsureFileExistsCallback& callback) { | |
41 callback.Run(error_, created_); | |
42 } | |
43 | |
44 private: | |
45 base::File::Error error_; | |
46 bool created_; | |
47 DISALLOW_COPY_AND_ASSIGN(EnsureFileExistsHelper); | |
48 }; | |
49 | |
50 class GetFileInfoHelper { | |
51 public: | |
52 GetFileInfoHelper() | |
53 : error_(base::File::FILE_OK) {} | |
54 | |
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 | |
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 | |
68 void ReplyFileInfo(const AsyncFileUtil::GetFileInfoCallback& callback) { | |
69 callback.Run(error_, file_info_); | |
70 } | |
71 | |
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::File::Error error_; | |
80 base::File::Info file_info_; | |
81 base::FilePath platform_path_; | |
82 storage::ScopedFile scoped_file_; | |
83 DISALLOW_COPY_AND_ASSIGN(GetFileInfoHelper); | |
84 }; | |
85 | |
86 void ReadDirectoryHelper(FileSystemFileUtil* file_util, | |
87 FileSystemOperationContext* context, | |
88 const FileSystemURL& url, | |
89 base::SingleThreadTaskRunner* origin_loop, | |
90 const AsyncFileUtil::ReadDirectoryCallback& callback) { | |
91 base::File::Info file_info; | |
92 base::FilePath platform_path; | |
93 base::File::Error error = file_util->GetFileInfo( | |
94 context, url, &file_info, &platform_path); | |
95 | |
96 if (error == base::File::FILE_OK && !file_info.is_directory) | |
97 error = base::File::FILE_ERROR_NOT_A_DIRECTORY; | |
98 | |
99 std::vector<DirectoryEntry> entries; | |
100 if (error != base::File::FILE_OK) { | |
101 origin_loop->PostTask( | |
102 FROM_HERE, base::Bind(callback, error, entries, false /* has_more */)); | |
103 return; | |
104 } | |
105 | |
106 // Note: Increasing this value may make some tests in LayoutTests meaningless. | |
107 // (Namely, read-directory-many.html and read-directory-sync-many.html are | |
108 // assuming that they are reading much more entries than this constant.) | |
109 const size_t kResultChunkSize = 100; | |
110 | |
111 scoped_ptr<FileSystemFileUtil::AbstractFileEnumerator> file_enum( | |
112 file_util->CreateFileEnumerator(context, url)); | |
113 | |
114 base::FilePath current; | |
115 while (!(current = file_enum->Next()).empty()) { | |
116 DirectoryEntry entry; | |
117 entry.is_directory = file_enum->IsDirectory(); | |
118 entry.name = VirtualPath::BaseName(current).value(); | |
119 entry.size = file_enum->Size(); | |
120 entry.last_modified_time = file_enum->LastModifiedTime(); | |
121 entries.push_back(entry); | |
122 | |
123 if (entries.size() == kResultChunkSize) { | |
124 origin_loop->PostTask( | |
125 FROM_HERE, base::Bind(callback, base::File::FILE_OK, entries, | |
126 true /* has_more */)); | |
127 entries.clear(); | |
128 } | |
129 } | |
130 origin_loop->PostTask( | |
131 FROM_HERE, base::Bind(callback, base::File::FILE_OK, entries, | |
132 false /* has_more */)); | |
133 } | |
134 | |
135 void RunCreateOrOpenCallback( | |
136 FileSystemOperationContext* context, | |
137 const AsyncFileUtil::CreateOrOpenCallback& callback, | |
138 base::File file) { | |
139 callback.Run(file.Pass(), base::Closure()); | |
140 } | |
141 | |
142 } // namespace | |
143 | |
144 AsyncFileUtilAdapter::AsyncFileUtilAdapter( | |
145 FileSystemFileUtil* sync_file_util) | |
146 : sync_file_util_(sync_file_util) { | |
147 DCHECK(sync_file_util_.get()); | |
148 } | |
149 | |
150 AsyncFileUtilAdapter::~AsyncFileUtilAdapter() { | |
151 } | |
152 | |
153 void AsyncFileUtilAdapter::CreateOrOpen( | |
154 scoped_ptr<FileSystemOperationContext> context, | |
155 const FileSystemURL& url, | |
156 int file_flags, | |
157 const CreateOrOpenCallback& callback) { | |
158 FileSystemOperationContext* context_ptr = context.release(); | |
159 base::PostTaskAndReplyWithResult( | |
160 context_ptr->task_runner(), | |
161 FROM_HERE, | |
162 Bind(&FileSystemFileUtil::CreateOrOpen, Unretained(sync_file_util_.get()), | |
163 context_ptr, url, file_flags), | |
164 Bind(&RunCreateOrOpenCallback, base::Owned(context_ptr), callback)); | |
165 } | |
166 | |
167 void AsyncFileUtilAdapter::EnsureFileExists( | |
168 scoped_ptr<FileSystemOperationContext> context, | |
169 const FileSystemURL& url, | |
170 const EnsureFileExistsCallback& callback) { | |
171 EnsureFileExistsHelper* helper = new EnsureFileExistsHelper; | |
172 FileSystemOperationContext* context_ptr = context.release(); | |
173 const bool success = context_ptr->task_runner()->PostTaskAndReply( | |
174 FROM_HERE, | |
175 Bind(&EnsureFileExistsHelper::RunWork, Unretained(helper), | |
176 sync_file_util_.get(), base::Owned(context_ptr), url), | |
177 Bind(&EnsureFileExistsHelper::Reply, Owned(helper), callback)); | |
178 DCHECK(success); | |
179 } | |
180 | |
181 void AsyncFileUtilAdapter::CreateDirectory( | |
182 scoped_ptr<FileSystemOperationContext> context, | |
183 const FileSystemURL& url, | |
184 bool exclusive, | |
185 bool recursive, | |
186 const StatusCallback& callback) { | |
187 FileSystemOperationContext* context_ptr = context.release(); | |
188 const bool success = base::PostTaskAndReplyWithResult( | |
189 context_ptr->task_runner(), FROM_HERE, | |
190 Bind(&FileSystemFileUtil::CreateDirectory, | |
191 Unretained(sync_file_util_.get()), | |
192 base::Owned(context_ptr), url, exclusive, recursive), | |
193 callback); | |
194 DCHECK(success); | |
195 } | |
196 | |
197 void AsyncFileUtilAdapter::GetFileInfo( | |
198 scoped_ptr<FileSystemOperationContext> context, | |
199 const FileSystemURL& url, | |
200 const GetFileInfoCallback& callback) { | |
201 FileSystemOperationContext* context_ptr = context.release(); | |
202 GetFileInfoHelper* helper = new GetFileInfoHelper; | |
203 const bool success = context_ptr->task_runner()->PostTaskAndReply( | |
204 FROM_HERE, | |
205 Bind(&GetFileInfoHelper::GetFileInfo, Unretained(helper), | |
206 sync_file_util_.get(), base::Owned(context_ptr), url), | |
207 Bind(&GetFileInfoHelper::ReplyFileInfo, Owned(helper), callback)); | |
208 DCHECK(success); | |
209 } | |
210 | |
211 void AsyncFileUtilAdapter::ReadDirectory( | |
212 scoped_ptr<FileSystemOperationContext> context, | |
213 const FileSystemURL& url, | |
214 const ReadDirectoryCallback& callback) { | |
215 FileSystemOperationContext* context_ptr = context.release(); | |
216 const bool success = context_ptr->task_runner()->PostTask( | |
217 FROM_HERE, | |
218 Bind(&ReadDirectoryHelper, | |
219 sync_file_util_.get(), base::Owned(context_ptr), url, | |
220 base::ThreadTaskRunnerHandle::Get(), callback)); | |
221 DCHECK(success); | |
222 } | |
223 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
331 void AsyncFileUtilAdapter::DeleteRecursively( | |
332 scoped_ptr<FileSystemOperationContext> context, | |
333 const FileSystemURL& url, | |
334 const StatusCallback& callback) { | |
335 callback.Run(base::File::FILE_ERROR_INVALID_OPERATION); | |
336 } | |
337 | |
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 storage | |
OLD | NEW |