OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012 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 "base/file_util_proxy.h" | |
6 | |
7 #include "base/bind.h" | |
8 #include "base/bind_helpers.h" | |
9 #include "base/file_util.h" | |
10 #include "base/location.h" | |
11 #include "base/message_loop_proxy.h" | |
12 #include "base/task_runner.h" | |
13 #include "base/task_runner_util.h" | |
14 | |
15 namespace base { | |
16 | |
17 namespace { | |
18 | |
19 void CallWithTranslatedParameter(const FileUtilProxy::StatusCallback& callback, | |
20 bool value) { | |
21 DCHECK(!callback.is_null()); | |
22 callback.Run(value ? PLATFORM_FILE_OK : PLATFORM_FILE_ERROR_FAILED); | |
23 } | |
24 | |
25 // Helper classes or routines for individual methods. | |
26 class CreateOrOpenHelper { | |
27 public: | |
28 CreateOrOpenHelper(TaskRunner* task_runner, | |
29 const FileUtilProxy::CloseTask& close_task) | |
30 : task_runner_(task_runner), | |
31 close_task_(close_task), | |
32 file_handle_(kInvalidPlatformFileValue), | |
33 created_(false), | |
34 error_(PLATFORM_FILE_OK) {} | |
35 | |
36 ~CreateOrOpenHelper() { | |
37 if (file_handle_ != kInvalidPlatformFileValue) { | |
38 task_runner_->PostTask( | |
39 FROM_HERE, | |
40 base::Bind(base::IgnoreResult(close_task_), file_handle_)); | |
41 } | |
42 } | |
43 | |
44 void RunWork(const FileUtilProxy::CreateOrOpenTask& task) { | |
45 error_ = task.Run(&file_handle_, &created_); | |
46 } | |
47 | |
48 void Reply(const FileUtilProxy::CreateOrOpenCallback& callback) { | |
49 DCHECK(!callback.is_null()); | |
50 callback.Run(error_, PassPlatformFile(&file_handle_), created_); | |
51 } | |
52 | |
53 private: | |
54 scoped_refptr<TaskRunner> task_runner_; | |
55 FileUtilProxy::CloseTask close_task_; | |
56 PlatformFile file_handle_; | |
57 bool created_; | |
58 PlatformFileError error_; | |
59 DISALLOW_COPY_AND_ASSIGN(CreateOrOpenHelper); | |
60 }; | |
61 | |
62 class CreateTemporaryHelper { | |
63 public: | |
64 explicit CreateTemporaryHelper(TaskRunner* task_runner) | |
65 : task_runner_(task_runner), | |
66 file_handle_(kInvalidPlatformFileValue), | |
67 error_(PLATFORM_FILE_OK) {} | |
68 | |
69 ~CreateTemporaryHelper() { | |
70 if (file_handle_ != kInvalidPlatformFileValue) { | |
71 FileUtilProxy::Close(task_runner_, file_handle_, | |
72 FileUtilProxy::StatusCallback()); | |
73 } | |
74 } | |
75 | |
76 void RunWork(int additional_file_flags) { | |
77 // TODO(darin): file_util should have a variant of CreateTemporaryFile | |
78 // that returns a FilePath and a PlatformFile. | |
79 file_util::CreateTemporaryFile(&file_path_); | |
80 | |
81 int file_flags = | |
82 PLATFORM_FILE_WRITE | | |
83 PLATFORM_FILE_TEMPORARY | | |
84 PLATFORM_FILE_CREATE_ALWAYS | | |
85 additional_file_flags; | |
86 | |
87 error_ = PLATFORM_FILE_OK; | |
88 file_handle_ = CreatePlatformFile(file_path_, file_flags, NULL, &error_); | |
89 } | |
90 | |
91 void Reply(const FileUtilProxy::CreateTemporaryCallback& callback) { | |
92 DCHECK(!callback.is_null()); | |
93 callback.Run(error_, PassPlatformFile(&file_handle_), file_path_); | |
94 } | |
95 | |
96 private: | |
97 scoped_refptr<TaskRunner> task_runner_; | |
98 PlatformFile file_handle_; | |
99 FilePath file_path_; | |
100 PlatformFileError error_; | |
101 DISALLOW_COPY_AND_ASSIGN(CreateTemporaryHelper); | |
102 }; | |
103 | |
104 class GetFileInfoHelper { | |
105 public: | |
106 GetFileInfoHelper() | |
107 : error_(PLATFORM_FILE_OK) {} | |
108 | |
109 void RunWorkForFilePath(const FilePath& file_path) { | |
110 if (!file_util::PathExists(file_path)) { | |
111 error_ = PLATFORM_FILE_ERROR_NOT_FOUND; | |
112 return; | |
113 } | |
114 if (!file_util::GetFileInfo(file_path, &file_info_)) | |
115 error_ = PLATFORM_FILE_ERROR_FAILED; | |
116 } | |
117 | |
118 void RunWorkForPlatformFile(PlatformFile file) { | |
119 if (!GetPlatformFileInfo(file, &file_info_)) | |
120 error_ = PLATFORM_FILE_ERROR_FAILED; | |
121 } | |
122 | |
123 void Reply(const FileUtilProxy::GetFileInfoCallback& callback) { | |
124 if (!callback.is_null()) { | |
125 callback.Run(error_, file_info_); | |
126 } | |
127 } | |
128 | |
129 private: | |
130 PlatformFileError error_; | |
131 PlatformFileInfo file_info_; | |
132 DISALLOW_COPY_AND_ASSIGN(GetFileInfoHelper); | |
133 }; | |
134 | |
135 class ReadHelper { | |
136 public: | |
137 explicit ReadHelper(int bytes_to_read) | |
138 : buffer_(new char[bytes_to_read]), | |
139 bytes_to_read_(bytes_to_read), | |
140 bytes_read_(0) {} | |
141 | |
142 void RunWork(PlatformFile file, int64 offset) { | |
143 bytes_read_ = ReadPlatformFile(file, offset, buffer_.get(), bytes_to_read_); | |
144 } | |
145 | |
146 void Reply(const FileUtilProxy::ReadCallback& callback) { | |
147 if (!callback.is_null()) { | |
148 PlatformFileError error = | |
149 (bytes_read_ < 0) ? PLATFORM_FILE_ERROR_FAILED : PLATFORM_FILE_OK; | |
150 callback.Run(error, buffer_.get(), bytes_read_); | |
151 } | |
152 } | |
153 | |
154 private: | |
155 scoped_ptr<char[]> buffer_; | |
156 int bytes_to_read_; | |
157 int bytes_read_; | |
158 DISALLOW_COPY_AND_ASSIGN(ReadHelper); | |
159 }; | |
160 | |
161 class WriteHelper { | |
162 public: | |
163 WriteHelper(const char* buffer, int bytes_to_write) | |
164 : buffer_(new char[bytes_to_write]), | |
165 bytes_to_write_(bytes_to_write), | |
166 bytes_written_(0) { | |
167 memcpy(buffer_.get(), buffer, bytes_to_write); | |
168 } | |
169 | |
170 void RunWork(PlatformFile file, int64 offset) { | |
171 bytes_written_ = WritePlatformFile(file, offset, buffer_.get(), | |
172 bytes_to_write_); | |
173 } | |
174 | |
175 void Reply(const FileUtilProxy::WriteCallback& callback) { | |
176 if (!callback.is_null()) { | |
177 PlatformFileError error = | |
178 (bytes_written_ < 0) ? PLATFORM_FILE_ERROR_FAILED : PLATFORM_FILE_OK; | |
179 callback.Run(error, bytes_written_); | |
180 } | |
181 } | |
182 | |
183 private: | |
184 scoped_ptr<char[]> buffer_; | |
185 int bytes_to_write_; | |
186 int bytes_written_; | |
187 DISALLOW_COPY_AND_ASSIGN(WriteHelper); | |
188 }; | |
189 | |
190 | |
191 PlatformFileError CreateOrOpenAdapter( | |
192 const FilePath& file_path, int file_flags, | |
193 PlatformFile* file_handle, bool* created) { | |
194 DCHECK(file_handle); | |
195 DCHECK(created); | |
196 if (!file_util::DirectoryExists(file_path.DirName())) { | |
197 // If its parent does not exist, should return NOT_FOUND error. | |
198 return PLATFORM_FILE_ERROR_NOT_FOUND; | |
199 } | |
200 PlatformFileError error = PLATFORM_FILE_OK; | |
201 *file_handle = CreatePlatformFile(file_path, file_flags, created, &error); | |
202 return error; | |
203 } | |
204 | |
205 PlatformFileError CloseAdapter(PlatformFile file_handle) { | |
206 if (!ClosePlatformFile(file_handle)) { | |
207 return PLATFORM_FILE_ERROR_FAILED; | |
208 } | |
209 return PLATFORM_FILE_OK; | |
210 } | |
211 | |
212 PlatformFileError DeleteAdapter(const FilePath& file_path, bool recursive) { | |
213 if (!file_util::PathExists(file_path)) { | |
214 return PLATFORM_FILE_ERROR_NOT_FOUND; | |
215 } | |
216 if (!file_util::Delete(file_path, recursive)) { | |
217 if (!recursive && !file_util::IsDirectoryEmpty(file_path)) { | |
218 return PLATFORM_FILE_ERROR_NOT_EMPTY; | |
219 } | |
220 return PLATFORM_FILE_ERROR_FAILED; | |
221 } | |
222 return PLATFORM_FILE_OK; | |
223 } | |
224 | |
225 } // namespace | |
226 | |
227 // static | |
228 bool FileUtilProxy::CreateOrOpen( | |
229 TaskRunner* task_runner, | |
230 const FilePath& file_path, int file_flags, | |
231 const CreateOrOpenCallback& callback) { | |
232 return RelayCreateOrOpen( | |
233 task_runner, | |
234 base::Bind(&CreateOrOpenAdapter, file_path, file_flags), | |
235 base::Bind(&CloseAdapter), | |
236 callback); | |
237 } | |
238 | |
239 // static | |
240 bool FileUtilProxy::CreateTemporary( | |
241 TaskRunner* task_runner, | |
242 int additional_file_flags, | |
243 const CreateTemporaryCallback& callback) { | |
244 CreateTemporaryHelper* helper = new CreateTemporaryHelper(task_runner); | |
245 return task_runner->PostTaskAndReply( | |
246 FROM_HERE, | |
247 Bind(&CreateTemporaryHelper::RunWork, Unretained(helper), | |
248 additional_file_flags), | |
249 Bind(&CreateTemporaryHelper::Reply, Owned(helper), callback)); | |
250 } | |
251 | |
252 // static | |
253 bool FileUtilProxy::Close( | |
254 TaskRunner* task_runner, | |
255 base::PlatformFile file_handle, | |
256 const StatusCallback& callback) { | |
257 return RelayClose( | |
258 task_runner, | |
259 base::Bind(&CloseAdapter), | |
260 file_handle, callback); | |
261 } | |
262 | |
263 // Retrieves the information about a file. It is invalid to pass NULL for the | |
264 // callback. | |
265 bool FileUtilProxy::GetFileInfo( | |
266 TaskRunner* task_runner, | |
267 const FilePath& file_path, | |
268 const GetFileInfoCallback& callback) { | |
269 GetFileInfoHelper* helper = new GetFileInfoHelper; | |
270 return task_runner->PostTaskAndReply( | |
271 FROM_HERE, | |
272 Bind(&GetFileInfoHelper::RunWorkForFilePath, | |
273 Unretained(helper), file_path), | |
274 Bind(&GetFileInfoHelper::Reply, Owned(helper), callback)); | |
275 } | |
276 | |
277 // static | |
278 bool FileUtilProxy::GetFileInfoFromPlatformFile( | |
279 TaskRunner* task_runner, | |
280 PlatformFile file, | |
281 const GetFileInfoCallback& callback) { | |
282 GetFileInfoHelper* helper = new GetFileInfoHelper; | |
283 return task_runner->PostTaskAndReply( | |
284 FROM_HERE, | |
285 Bind(&GetFileInfoHelper::RunWorkForPlatformFile, | |
286 Unretained(helper), file), | |
287 Bind(&GetFileInfoHelper::Reply, Owned(helper), callback)); | |
288 } | |
289 | |
290 // static | |
291 bool FileUtilProxy::Delete(TaskRunner* task_runner, | |
292 const FilePath& file_path, | |
293 bool recursive, | |
294 const StatusCallback& callback) { | |
295 return base::PostTaskAndReplyWithResult( | |
296 task_runner, FROM_HERE, | |
297 Bind(&DeleteAdapter, file_path, recursive), | |
298 callback); | |
299 } | |
300 | |
301 // static | |
302 bool FileUtilProxy::RecursiveDelete( | |
303 TaskRunner* task_runner, | |
304 const FilePath& file_path, | |
305 const StatusCallback& callback) { | |
306 return base::PostTaskAndReplyWithResult( | |
307 task_runner, FROM_HERE, | |
308 Bind(&DeleteAdapter, file_path, true /* recursive */), | |
309 callback); | |
310 } | |
311 | |
312 // static | |
313 bool FileUtilProxy::Read( | |
314 TaskRunner* task_runner, | |
315 PlatformFile file, | |
316 int64 offset, | |
317 int bytes_to_read, | |
318 const ReadCallback& callback) { | |
319 if (bytes_to_read < 0) { | |
320 return false; | |
321 } | |
322 ReadHelper* helper = new ReadHelper(bytes_to_read); | |
323 return task_runner->PostTaskAndReply( | |
324 FROM_HERE, | |
325 Bind(&ReadHelper::RunWork, Unretained(helper), file, offset), | |
326 Bind(&ReadHelper::Reply, Owned(helper), callback)); | |
327 } | |
328 | |
329 // static | |
330 bool FileUtilProxy::Write( | |
331 TaskRunner* task_runner, | |
332 PlatformFile file, | |
333 int64 offset, | |
334 const char* buffer, | |
335 int bytes_to_write, | |
336 const WriteCallback& callback) { | |
337 if (bytes_to_write <= 0 || buffer == NULL) { | |
338 return false; | |
339 } | |
340 WriteHelper* helper = new WriteHelper(buffer, bytes_to_write); | |
341 return task_runner->PostTaskAndReply( | |
342 FROM_HERE, | |
343 Bind(&WriteHelper::RunWork, Unretained(helper), file, offset), | |
344 Bind(&WriteHelper::Reply, Owned(helper), callback)); | |
345 } | |
346 | |
347 // static | |
348 bool FileUtilProxy::Touch( | |
349 TaskRunner* task_runner, | |
350 PlatformFile file, | |
351 const Time& last_access_time, | |
352 const Time& last_modified_time, | |
353 const StatusCallback& callback) { | |
354 return base::PostTaskAndReplyWithResult( | |
355 task_runner, | |
356 FROM_HERE, | |
357 Bind(&TouchPlatformFile, file, | |
358 last_access_time, last_modified_time), | |
359 Bind(&CallWithTranslatedParameter, callback)); | |
360 } | |
361 | |
362 // static | |
363 bool FileUtilProxy::Touch( | |
364 TaskRunner* task_runner, | |
365 const FilePath& file_path, | |
366 const Time& last_access_time, | |
367 const Time& last_modified_time, | |
368 const StatusCallback& callback) { | |
369 return base::PostTaskAndReplyWithResult( | |
370 task_runner, | |
371 FROM_HERE, | |
372 Bind(&file_util::TouchFile, file_path, | |
373 last_access_time, last_modified_time), | |
374 Bind(&CallWithTranslatedParameter, callback)); | |
375 } | |
376 | |
377 // static | |
378 bool FileUtilProxy::Truncate( | |
379 TaskRunner* task_runner, | |
380 PlatformFile file, | |
381 int64 length, | |
382 const StatusCallback& callback) { | |
383 return base::PostTaskAndReplyWithResult( | |
384 task_runner, | |
385 FROM_HERE, | |
386 Bind(&TruncatePlatformFile, file, length), | |
387 Bind(&CallWithTranslatedParameter, callback)); | |
388 } | |
389 | |
390 // static | |
391 bool FileUtilProxy::Flush( | |
392 TaskRunner* task_runner, | |
393 PlatformFile file, | |
394 const StatusCallback& callback) { | |
395 return base::PostTaskAndReplyWithResult( | |
396 task_runner, | |
397 FROM_HERE, | |
398 Bind(&FlushPlatformFile, file), | |
399 Bind(&CallWithTranslatedParameter, callback)); | |
400 } | |
401 | |
402 // static | |
403 bool FileUtilProxy::RelayCreateOrOpen( | |
404 TaskRunner* task_runner, | |
405 const CreateOrOpenTask& open_task, | |
406 const CloseTask& close_task, | |
407 const CreateOrOpenCallback& callback) { | |
408 CreateOrOpenHelper* helper = new CreateOrOpenHelper( | |
409 task_runner, close_task); | |
410 return task_runner->PostTaskAndReply( | |
411 FROM_HERE, | |
412 Bind(&CreateOrOpenHelper::RunWork, Unretained(helper), open_task), | |
413 Bind(&CreateOrOpenHelper::Reply, Owned(helper), callback)); | |
414 } | |
415 | |
416 // static | |
417 bool FileUtilProxy::RelayClose( | |
418 TaskRunner* task_runner, | |
419 const CloseTask& close_task, | |
420 PlatformFile file_handle, | |
421 const StatusCallback& callback) { | |
422 return base::PostTaskAndReplyWithResult( | |
423 task_runner, FROM_HERE, Bind(close_task, file_handle), callback); | |
424 } | |
425 | |
426 } // namespace base | |
OLD | NEW |