[Storage] Blob Storage Refactoring pt 1:
[chromium-blink-merge.git] / storage / browser / fileapi / async_file_util_adapter.cc
blob7d324c006f8abb74bf22373ca7464a7202bf56f1
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 "storage/browser/fileapi/async_file_util_adapter.h"
7 #include <vector>
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 "storage/browser/blob/shareable_file_reference.h"
14 #include "storage/browser/fileapi/file_system_context.h"
15 #include "storage/browser/fileapi/file_system_file_util.h"
16 #include "storage/browser/fileapi/file_system_operation_context.h"
17 #include "storage/browser/fileapi/file_system_url.h"
18 #include "storage/common/fileapi/file_system_util.h"
20 using base::Bind;
21 using base::Callback;
22 using base::Owned;
23 using base::Unretained;
24 using storage::ShareableFileReference;
26 namespace storage {
28 namespace {
30 class EnsureFileExistsHelper {
31 public:
32 EnsureFileExistsHelper() : error_(base::File::FILE_OK), created_(false) {}
34 void RunWork(FileSystemFileUtil* file_util,
35 FileSystemOperationContext* context,
36 const FileSystemURL& url) {
37 error_ = file_util->EnsureFileExists(context, url, &created_);
40 void Reply(const AsyncFileUtil::EnsureFileExistsCallback& callback) {
41 callback.Run(error_, created_);
44 private:
45 base::File::Error error_;
46 bool created_;
47 DISALLOW_COPY_AND_ASSIGN(EnsureFileExistsHelper);
50 class GetFileInfoHelper {
51 public:
52 GetFileInfoHelper()
53 : error_(base::File::FILE_OK) {}
55 void GetFileInfo(FileSystemFileUtil* file_util,
56 FileSystemOperationContext* context,
57 const FileSystemURL& url) {
58 error_ = file_util->GetFileInfo(context, url, &file_info_, &platform_path_);
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_);
68 void ReplyFileInfo(const AsyncFileUtil::GetFileInfoCallback& callback) {
69 callback.Run(error_, file_info_);
72 void ReplySnapshotFile(
73 const AsyncFileUtil::CreateSnapshotFileCallback& callback) {
74 callback.Run(error_, file_info_, platform_path_,
75 ShareableFileReference::GetOrCreate(scoped_file_.Pass()));
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);
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);
96 if (error == base::File::FILE_OK && !file_info.is_directory)
97 error = base::File::FILE_ERROR_NOT_A_DIRECTORY;
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;
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;
111 scoped_ptr<FileSystemFileUtil::AbstractFileEnumerator> file_enum(
112 file_util->CreateFileEnumerator(context, url));
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);
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();
130 origin_loop->PostTask(
131 FROM_HERE, base::Bind(callback, base::File::FILE_OK, entries,
132 false /* has_more */));
135 void RunCreateOrOpenCallback(
136 FileSystemOperationContext* context,
137 const AsyncFileUtil::CreateOrOpenCallback& callback,
138 base::File file) {
139 callback.Run(file.Pass(), base::Closure());
142 } // namespace
144 AsyncFileUtilAdapter::AsyncFileUtilAdapter(
145 FileSystemFileUtil* sync_file_util)
146 : sync_file_util_(sync_file_util) {
147 DCHECK(sync_file_util_.get());
150 AsyncFileUtilAdapter::~AsyncFileUtilAdapter() {
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));
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
352 } // namespace storage