OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/file_util_proxy.h" | 5 #include "base/file_util_proxy.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/bind_helpers.h" | 8 #include "base/bind_helpers.h" |
9 #include "base/file_util.h" | 9 #include "base/file_util.h" |
10 #include "base/message_loop_proxy.h" | 10 #include "base/message_loop_proxy.h" |
11 | 11 |
12 namespace base { | 12 namespace base { |
13 | 13 |
14 namespace { | 14 namespace { |
15 | 15 |
16 // Helper templates to call file_util or base::PlatformFile methods | 16 // Helper templates to call file_util or base::PlatformFile methods |
17 // and reply with the returned value. | 17 // and reply with the returned value. |
18 // | 18 // |
19 // Typically when you have these methods: | 19 // Typically when you have these methods: |
20 // R DoWorkAndReturn(); | 20 // R DoWorkAndReturn(); |
21 // void Callback(R& result); | 21 // void Callback(R& result); |
22 // | 22 // |
23 // You can pass the result of DoWorkAndReturn to the Callback by: | 23 // You can pass the result of DoWorkAndReturn to the Callback by: |
24 // | 24 // |
25 // R* result = new R; | 25 // R* result = new R; |
26 // message_loop_proxy->PostTaskAndReply( | 26 // message_loop_proxy->PostTaskAndReply( |
27 // from_here, | 27 // from_here, |
28 // ReturnAsParam<R>(Bind(&DoWorkAndReturn), result), | 28 // ReturnAsParam<R>(Bind(&DoWorkAndReturn), result), |
29 // CallbackWithReturn(Bind(&Callback), Owned(result))); | 29 // RelayHelper(Bind(&Callback), Owned(result))); |
30 // | 30 // |
31 // Or just use PostTaskAndReplyWithStatus helper template (see the code below). | 31 // Or just use PostTaskAndReplyWithStatus helper template (see the code below). |
32 template <typename R1, typename R2> | 32 template <typename R1, typename R2> |
33 struct ReturnValueTranslator { | 33 struct ReturnValueTranslator { |
34 static R2 Value(const R1& value); | 34 static R2 Value(const R1& value); |
35 }; | 35 }; |
36 | 36 |
37 template <typename R> | 37 template <typename R> |
38 struct ReturnValueTranslator<R, R> { | 38 struct ReturnValueTranslator<R, R> { |
39 static R Value(const R& value) { return value; } | 39 static R Value(const R& value) { return value; } |
(...skipping 13 matching lines...) Expand all Loading... | |
53 if (!func.is_null()) | 53 if (!func.is_null()) |
54 *result = ReturnValueTranslator<R1, R2>::Value(func.Run()); | 54 *result = ReturnValueTranslator<R1, R2>::Value(func.Run()); |
55 } | 55 } |
56 | 56 |
57 template <typename R1, typename R2> | 57 template <typename R1, typename R2> |
58 Closure ReturnAsParam(const Callback<R1(void)>& func, R2* result) { | 58 Closure ReturnAsParam(const Callback<R1(void)>& func, R2* result) { |
59 DCHECK(result); | 59 DCHECK(result); |
60 return Bind(&ReturnAsParamAdapter<R1, R2>, func, result); | 60 return Bind(&ReturnAsParamAdapter<R1, R2>, func, result); |
61 } | 61 } |
62 | 62 |
63 template <typename R, typename A1> | |
64 void ReturnAsParamAdapter1(const Callback<R(A1)>& func, A1 a1, R* result) { | |
65 if (!func.is_null()) | |
66 *result = func.Run(a1); | |
67 } | |
68 | |
69 template <typename R, typename A1> | |
70 Closure ReturnAsParam(const Callback<R(A1)>& func, A1 a1, R* result) { | |
71 DCHECK(result); | |
72 return Bind(&ReturnAsParamAdapter1<R, A1>, func, a1, result); | |
73 } | |
74 | |
63 template <typename R> | 75 template <typename R> |
64 void ReplyAdapter(const Callback<void(R)>& callback, R* result) { | 76 void ReplyAdapter(const Callback<void(R)>& callback, R* result) { |
65 DCHECK(result); | 77 DCHECK(result); |
66 if (!callback.is_null()) | 78 if (!callback.is_null()) |
67 callback.Run(*result); | 79 callback.Run(*result); |
68 } | 80 } |
69 | 81 |
70 template <typename R, typename OWNED> | 82 template <typename R, typename OWNED> |
71 Closure ReplyHelper(const Callback<void(R)>& callback, OWNED result) { | 83 Closure ReplyHelper(const Callback<void(R)>& callback, OWNED result) { |
72 return Bind(&ReplyAdapter<R>, callback, result); | 84 return Bind(&ReplyAdapter<R>, callback, result); |
73 } | 85 } |
74 | 86 |
75 // Putting everything together. | 87 // Putting everything together. |
76 template <typename R1, typename R2> | 88 template <typename R1, typename R2> |
77 bool PostTaskAndReplyWithStatus( | 89 bool PostTaskAndReplyWithStatus( |
78 const scoped_refptr<MessageLoopProxy>& message_loop_proxy, | 90 const scoped_refptr<MessageLoopProxy>& message_loop_proxy, |
79 const tracked_objects::Location& from_here, | 91 const tracked_objects::Location& from_here, |
80 const Callback<R1(void)>& file_util_work, | 92 const Callback<R1(void)>& file_util_work, |
81 const Callback<void(R2)>& callback, | 93 const Callback<void(R2)>& callback, |
82 R2* result) { | 94 R2* result) { |
83 return message_loop_proxy->PostTaskAndReply( | 95 return message_loop_proxy->PostTaskAndReply( |
84 from_here, | 96 from_here, |
85 ReturnAsParam<R1>(file_util_work, result), | 97 ReturnAsParam<R1>(file_util_work, result), |
86 ReplyHelper(callback, Owned(result))); | 98 ReplyHelper(callback, Owned(result))); |
87 } | 99 } |
88 | 100 |
89 // Helper classes or routines for individual methods. | 101 // Helper classes or routines for individual methods. |
90 class CreateOrOpenHelper { | 102 class CreateOrOpenHelper { |
91 public: | 103 public: |
92 CreateOrOpenHelper(MessageLoopProxy* message_loop_proxy) | 104 CreateOrOpenHelper(MessageLoopProxy* message_loop_proxy, |
105 const FileUtilProxy::CloseTask& close_task) | |
93 : message_loop_proxy_(message_loop_proxy), | 106 : message_loop_proxy_(message_loop_proxy), |
107 close_task_(close_task), | |
94 file_handle_(kInvalidPlatformFileValue), | 108 file_handle_(kInvalidPlatformFileValue), |
95 created_(false), | 109 created_(false), |
96 error_(PLATFORM_FILE_OK) {} | 110 error_(PLATFORM_FILE_OK) {} |
97 | 111 |
98 ~CreateOrOpenHelper() { | 112 ~CreateOrOpenHelper() { |
99 if (file_handle_ != kInvalidPlatformFileValue) { | 113 if (file_handle_ != kInvalidPlatformFileValue) { |
100 FileUtilProxy::Close(message_loop_proxy_, file_handle_, | 114 FileUtilProxy::RelayClose(message_loop_proxy_, |
101 FileUtilProxy::StatusCallback()); | 115 close_task_, file_handle_, |
116 FileUtilProxy::StatusCallback()); | |
willchan no longer on Chromium
2011/11/01 22:57:37
Why do we use FileUtilProxy here? Shouldn't we jus
kinuko
2011/11/02 05:48:22
Good point... I think simple PostTask will be enou
| |
102 } | 117 } |
103 } | 118 } |
104 | 119 |
105 void RunWork(const FilePath& file_path, int file_flags) { | 120 void RunWork(const FileUtilProxy::CreateOrOpenTask& task) { |
106 if (!file_util::DirectoryExists(file_path.DirName())) { | 121 error_ = task.Run(&file_handle_, &created_); |
107 // If its parent does not exist, should return NOT_FOUND error. | |
108 error_ = PLATFORM_FILE_ERROR_NOT_FOUND; | |
109 return; | |
110 } | |
111 error_ = PLATFORM_FILE_OK; | |
112 file_handle_ = CreatePlatformFile(file_path, file_flags, | |
113 &created_, &error_); | |
114 } | 122 } |
115 | 123 |
116 void Reply(const FileUtilProxy::CreateOrOpenCallback& callback) { | 124 void Reply(const FileUtilProxy::CreateOrOpenCallback& callback) { |
117 DCHECK(!callback.is_null()); | 125 DCHECK(!callback.is_null()); |
118 callback.Run(error_, PassPlatformFile(&file_handle_), created_); | 126 callback.Run(error_, PassPlatformFile(&file_handle_), created_); |
119 } | 127 } |
120 | 128 |
121 private: | 129 private: |
122 scoped_refptr<MessageLoopProxy> message_loop_proxy_; | 130 scoped_refptr<MessageLoopProxy> message_loop_proxy_; |
131 FileUtilProxy::CloseTask close_task_; | |
123 PlatformFile file_handle_; | 132 PlatformFile file_handle_; |
124 bool created_; | 133 bool created_; |
125 PlatformFileError error_; | 134 PlatformFileError error_; |
126 DISALLOW_COPY_AND_ASSIGN(CreateOrOpenHelper); | 135 DISALLOW_COPY_AND_ASSIGN(CreateOrOpenHelper); |
127 }; | 136 }; |
128 | 137 |
129 class CreateTemporaryHelper { | 138 class CreateTemporaryHelper { |
130 public: | 139 public: |
131 CreateTemporaryHelper(MessageLoopProxy* message_loop_proxy) | 140 CreateTemporaryHelper(MessageLoopProxy* message_loop_proxy) |
132 : message_loop_proxy_(message_loop_proxy), | 141 : message_loop_proxy_(message_loop_proxy), |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
260 } | 269 } |
261 } | 270 } |
262 | 271 |
263 private: | 272 private: |
264 scoped_array<char> buffer_; | 273 scoped_array<char> buffer_; |
265 int bytes_to_write_; | 274 int bytes_to_write_; |
266 int bytes_written_; | 275 int bytes_written_; |
267 DISALLOW_COPY_AND_ASSIGN(WriteHelper); | 276 DISALLOW_COPY_AND_ASSIGN(WriteHelper); |
268 }; | 277 }; |
269 | 278 |
279 | |
280 PlatformFileError CreateOrOpenAdapter( | |
281 const FilePath& file_path, int file_flags, | |
282 PlatformFile* file_handle, bool* created) { | |
283 DCHECK(file_handle); | |
284 DCHECK(created); | |
285 if (!file_util::DirectoryExists(file_path.DirName())) { | |
286 // If its parent does not exist, should return NOT_FOUND error. | |
287 return PLATFORM_FILE_ERROR_NOT_FOUND; | |
288 } | |
289 PlatformFileError error = PLATFORM_FILE_OK; | |
290 *file_handle = CreatePlatformFile(file_path, file_flags, created, &error); | |
291 return error; | |
292 } | |
293 | |
294 PlatformFileError CloseAdapter(PlatformFile file_handle) { | |
295 if (!ClosePlatformFile(file_handle)) { | |
296 return PLATFORM_FILE_ERROR_FAILED; | |
297 } | |
298 return PLATFORM_FILE_OK; | |
299 } | |
300 | |
270 } // namespace | 301 } // namespace |
271 | 302 |
272 // static | 303 // static |
273 bool FileUtilProxy::CreateOrOpen( | 304 bool FileUtilProxy::CreateOrOpen( |
274 scoped_refptr<MessageLoopProxy> message_loop_proxy, | 305 scoped_refptr<MessageLoopProxy> message_loop_proxy, |
275 const FilePath& file_path, int file_flags, | 306 const FilePath& file_path, int file_flags, |
276 const CreateOrOpenCallback& callback) { | 307 const CreateOrOpenCallback& callback) { |
277 CreateOrOpenHelper* helper = new CreateOrOpenHelper(message_loop_proxy); | 308 return RelayCreateOrOpen( |
278 return message_loop_proxy->PostTaskAndReply( | 309 message_loop_proxy, |
279 FROM_HERE, | 310 base::Bind(&CreateOrOpenAdapter, file_path, file_flags), |
280 Bind(&CreateOrOpenHelper::RunWork, Unretained(helper), | 311 base::Bind(&CloseAdapter), |
281 file_path, file_flags), | 312 callback); |
282 Bind(&CreateOrOpenHelper::Reply, Owned(helper), callback)); | |
283 } | 313 } |
284 | 314 |
285 // static | 315 // static |
286 bool FileUtilProxy::CreateTemporary( | 316 bool FileUtilProxy::CreateTemporary( |
287 scoped_refptr<MessageLoopProxy> message_loop_proxy, | 317 scoped_refptr<MessageLoopProxy> message_loop_proxy, |
288 int additional_file_flags, | 318 int additional_file_flags, |
289 const CreateTemporaryCallback& callback) { | 319 const CreateTemporaryCallback& callback) { |
290 CreateTemporaryHelper* helper = new CreateTemporaryHelper(message_loop_proxy); | 320 CreateTemporaryHelper* helper = new CreateTemporaryHelper(message_loop_proxy); |
291 return message_loop_proxy->PostTaskAndReply( | 321 return message_loop_proxy->PostTaskAndReply( |
292 FROM_HERE, | 322 FROM_HERE, |
293 Bind(&CreateTemporaryHelper::RunWork, Unretained(helper), | 323 Bind(&CreateTemporaryHelper::RunWork, Unretained(helper), |
294 additional_file_flags), | 324 additional_file_flags), |
295 Bind(&CreateTemporaryHelper::Reply, Owned(helper), callback)); | 325 Bind(&CreateTemporaryHelper::Reply, Owned(helper), callback)); |
296 } | 326 } |
297 | 327 |
298 // static | 328 // static |
299 bool FileUtilProxy::Close(scoped_refptr<MessageLoopProxy> message_loop_proxy, | 329 bool FileUtilProxy::Close( |
300 PlatformFile file_handle, | 330 scoped_refptr<MessageLoopProxy> message_loop_proxy, |
301 const StatusCallback& callback) { | 331 base::PlatformFile file_handle, |
302 return PostTaskAndReplyWithStatus<bool>( | 332 const StatusCallback& callback) { |
303 message_loop_proxy, FROM_HERE, | 333 return RelayClose( |
304 Bind(&ClosePlatformFile, file_handle), callback, | 334 message_loop_proxy, |
305 new PlatformFileError); | 335 base::Bind(&CloseAdapter), |
336 file_handle, callback); | |
306 } | 337 } |
307 | 338 |
308 // Retrieves the information about a file. It is invalid to pass NULL for the | 339 // Retrieves the information about a file. It is invalid to pass NULL for the |
309 // callback. | 340 // callback. |
310 bool FileUtilProxy::GetFileInfo( | 341 bool FileUtilProxy::GetFileInfo( |
311 scoped_refptr<MessageLoopProxy> message_loop_proxy, | 342 scoped_refptr<MessageLoopProxy> message_loop_proxy, |
312 const FilePath& file_path, | 343 const FilePath& file_path, |
313 const GetFileInfoCallback& callback) { | 344 const GetFileInfoCallback& callback) { |
314 GetFileInfoHelper* helper = new GetFileInfoHelper; | 345 GetFileInfoHelper* helper = new GetFileInfoHelper; |
315 return message_loop_proxy->PostTaskAndReply( | 346 return message_loop_proxy->PostTaskAndReply( |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
434 bool FileUtilProxy::Flush( | 465 bool FileUtilProxy::Flush( |
435 scoped_refptr<MessageLoopProxy> message_loop_proxy, | 466 scoped_refptr<MessageLoopProxy> message_loop_proxy, |
436 PlatformFile file, | 467 PlatformFile file, |
437 const StatusCallback& callback) { | 468 const StatusCallback& callback) { |
438 return PostTaskAndReplyWithStatus<bool>( | 469 return PostTaskAndReplyWithStatus<bool>( |
439 message_loop_proxy, FROM_HERE, | 470 message_loop_proxy, FROM_HERE, |
440 Bind(&FlushPlatformFile, file), callback, | 471 Bind(&FlushPlatformFile, file), callback, |
441 new PlatformFileError); | 472 new PlatformFileError); |
442 } | 473 } |
443 | 474 |
475 // static | |
476 bool FileUtilProxy::RelayCreateOrOpen( | |
477 scoped_refptr<MessageLoopProxy> message_loop_proxy, | |
478 const CreateOrOpenTask& open_task, | |
479 const CloseTask& close_task, | |
480 const CreateOrOpenCallback& callback) { | |
481 CreateOrOpenHelper* helper = new CreateOrOpenHelper( | |
482 message_loop_proxy, close_task); | |
483 return message_loop_proxy->PostTaskAndReply( | |
484 FROM_HERE, | |
485 Bind(&CreateOrOpenHelper::RunWork, Unretained(helper), open_task), | |
486 Bind(&CreateOrOpenHelper::Reply, Owned(helper), callback)); | |
487 } | |
488 | |
489 // static | |
490 bool FileUtilProxy::RelayClose( | |
491 scoped_refptr<MessageLoopProxy> message_loop_proxy, | |
492 const CloseTask& close_task, | |
493 PlatformFile file_handle, | |
494 const StatusCallback& callback) { | |
495 PlatformFileError* result = new PlatformFileError; | |
496 return message_loop_proxy->PostTaskAndReply( | |
497 FROM_HERE, | |
498 ReturnAsParam(close_task, file_handle, result), | |
499 ReplyHelper(callback, Owned(result))); | |
500 } | |
501 | |
444 } // namespace base | 502 } // namespace base |
OLD | NEW |