Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(224)

Side by Side Diff: base/file_util_proxy.cc

Issue 8339012: Reimplementing FileUtilProxy using PostTaskAndReply (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 9 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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"
9 #include "base/file_util.h"
8 #include "base/message_loop_proxy.h" 10 #include "base/message_loop_proxy.h"
9 11
10 namespace base { 12 namespace base {
11 13
12 namespace { 14 namespace {
13 15
14 class MessageLoopRelay 16 // Helper templates to call file_util or base::PlatformFile methods
15 : public RefCountedThreadSafe<MessageLoopRelay> { 17 // and reply with the returned value.
18 //
19 // Typically when you have these methods:
20 // R DoWorkAndReturn();
21 // void Callback(R& result);
22 //
23 // You can pass the result of DoWorkAndReturn to the Callback by:
24 //
25 // R* result = new R;
26 // message_loop_proxy->PostTaskAndReply(
27 // from_here,
28 // ReturnAsParam<R>(Bind(&DoWorkAndReturn), result),
29 // CallbackWithReturn(Bind(&Callback), result));
30 //
31 // Or just use PostTaskAndReplyWithStatus helper method for the combination of
32 // generic file_util methods (that return bool) and StatusCallback.
33 template <typename R1, typename R2>
34 struct ReturnValueTranslator {
35 static R2 Value(const R1& value);
36 };
37
38 template <typename R>
39 struct ReturnValueTranslator<R, R> {
40 static R Value(const R& value) { return value; }
41 };
42
43 template <>
44 struct ReturnValueTranslator<bool, PlatformFileError> {
45 static PlatformFileError Value(const bool& value) {
46 if (value)
47 return PLATFORM_FILE_OK;
48 return PLATFORM_FILE_ERROR_FAILED;
49 }
50 };
51
52 template <typename R1, typename R2>
53 void ReturnAsParamAdapter(const Callback<R1(void)>& func, R2* result) {
54 DCHECK(result);
willchan no longer on Chromium 2011/10/19 00:26:52 Why isn't this DCHECK done earlier, perhaps in Ret
kinuko 2011/10/19 08:42:05 Done. Indeed...
55 if (!func.is_null())
56 *result = ReturnValueTranslator<R1, R2>::Value(func.Run());
57 }
58
59 template <typename R1, typename R2>
60 Closure ReturnAsParam(const Callback<R1(void)>& func, R2* result) {
61 return Bind(&ReturnAsParamAdapter<R1, R2>, func, result);
62 }
63
64 template <typename R>
65 void ReplyAndCleanupAdapter(const Callback<void(R)>& callback, R* result) {
66 DCHECK(result);
67 if (!callback.is_null())
68 callback.Run(*result);
69 delete result;
70 }
71
72 template <typename R>
73 Closure ReplyAndCleanup(const Callback<void(R)>& callback, R* result) {
74 return Bind(&ReplyAndCleanupAdapter<R>, callback, result);
75 }
76
77 // Putting everything together.
78 template <typename R1, typename R2>
79 bool PostTaskAndReplyWithStatus(
80 scoped_refptr<MessageLoopProxy> message_loop_proxy,
81 const tracked_objects::Location& from_here,
82 const Callback<R1(void)>& file_util_work,
83 const Callback<void(R2)>& callback,
84 R2* result) {
85 if (!message_loop_proxy->PostTaskAndReply(
86 from_here,
87 ReturnAsParam<R1>(file_util_work, result),
88 ReplyAndCleanup(callback, result))) {
89 delete result;
90 return false;
91 }
92 return true;
93 }
94
95 // Helper classes or routines for individual methods.
96 class CreateOrOpenHelper {
16 public: 97 public:
17 MessageLoopRelay() 98 CreateOrOpenHelper()
18 : origin_message_loop_proxy_( 99 : file_handle_(kInvalidPlatformFileValue),
19 MessageLoopProxy::current()), 100 created_(false),
20 error_code_(PLATFORM_FILE_OK) { 101 error_(PLATFORM_FILE_OK) {}
102
103 void RunWork(const FilePath& file_path, int file_flags) {
104 if (!file_util::DirectoryExists(file_path.DirName())) {
105 // If its parent does not exist, should return NOT_FOUND error.
106 error_ = PLATFORM_FILE_ERROR_NOT_FOUND;
107 return;
108 }
109 error_ = PLATFORM_FILE_OK;
110 file_handle_ = CreatePlatformFile(file_path, file_flags,
111 &created_, &error_);
21 } 112 }
22 113
23 bool Start(scoped_refptr<MessageLoopProxy> message_loop_proxy, 114 void Reply(scoped_refptr<MessageLoopProxy> message_loop_proxy,
24 const tracked_objects::Location& from_here) { 115 const FileUtilProxy::CreateOrOpenCallback& callback) {
25 return message_loop_proxy->PostTask( 116 DCHECK(!callback.is_null());
26 from_here, Bind(&MessageLoopRelay::ProcessOnTargetThread, this)); 117 callback.Run(error_, PassPlatformFile(&file_handle_), created_);
27 } 118 if (file_handle_ != kInvalidPlatformFileValue) {
28 119 FileUtilProxy::Close(message_loop_proxy, file_handle_,
29 protected: 120 FileUtilProxy::StatusCallback());
30 friend class RefCountedThreadSafe<MessageLoopRelay>; 121 }
31 virtual ~MessageLoopRelay() {} 122 delete this;
willchan no longer on Chromium 2011/10/19 00:26:52 I think you should get rid of all these delete thi
kinuko 2011/10/19 08:42:05 Done. Cool.
32
33 // Called to perform work on the FILE thread.
34 virtual void RunWork() = 0;
35
36 // Called to notify the callback on the origin thread.
37 virtual void RunCallback() = 0;
38
39 void set_error_code(PlatformFileError error_code) {
40 error_code_ = error_code;
41 }
42
43 PlatformFileError error_code() const {
44 return error_code_;
45 } 123 }
46 124
47 private: 125 private:
48 void ProcessOnTargetThread() { 126 PlatformFile file_handle_;
49 RunWork(); 127 bool created_;
50 origin_message_loop_proxy_->PostTask( 128 PlatformFileError error_;
51 FROM_HERE, Bind(&MessageLoopRelay::RunCallback, this));
52 }
53
54 scoped_refptr<MessageLoopProxy> origin_message_loop_proxy_;
55 PlatformFileError error_code_;
56 }; 129 };
willchan no longer on Chromium 2011/10/19 00:26:52 DISALLOW_COPY_AND_ASSIGN
kinuko 2011/10/19 08:42:05 Done.
57 130
58 class RelayCreateOrOpen : public MessageLoopRelay { 131 class CreateTemporaryHelper {
59 public: 132 public:
60 RelayCreateOrOpen( 133 CreateTemporaryHelper()
61 scoped_refptr<MessageLoopProxy> message_loop_proxy, 134 : file_handle_(kInvalidPlatformFileValue),
62 const FilePath& file_path, 135 error_(PLATFORM_FILE_OK) {}
63 int file_flags,
64 const FileUtilProxy::CreateOrOpenCallback& callback)
65 : message_loop_proxy_(message_loop_proxy),
66 file_path_(file_path),
67 file_flags_(file_flags),
68 callback_(callback),
69 file_handle_(kInvalidPlatformFileValue),
70 created_(false) {
71 DCHECK_EQ(false, callback.is_null());
72 }
73 136
74 protected: 137 void RunWork(int additional_file_flags) {
75 virtual ~RelayCreateOrOpen() {
76 if (file_handle_ != kInvalidPlatformFileValue)
77 FileUtilProxy::Close(message_loop_proxy_, file_handle_,
78 FileUtilProxy::StatusCallback());
79 }
80
81 virtual void RunWork() {
82 if (!file_util::DirectoryExists(file_path_.DirName())) {
83 // If its parent does not exist, should return NOT_FOUND error.
84 set_error_code(PLATFORM_FILE_ERROR_NOT_FOUND);
85 return;
86 }
87 PlatformFileError error_code = PLATFORM_FILE_OK;
88 file_handle_ = CreatePlatformFile(file_path_, file_flags_,
89 &created_, &error_code);
90 set_error_code(error_code);
91 }
92
93 virtual void RunCallback() {
94 callback_.Run(error_code(), PassPlatformFile(&file_handle_),
95 created_);
96 }
97
98 private:
99 scoped_refptr<MessageLoopProxy> message_loop_proxy_;
100 FilePath file_path_;
101 int file_flags_;
102 FileUtilProxy::CreateOrOpenCallback callback_;
103 PlatformFile file_handle_;
104 bool created_;
105 };
106
107 class RelayCreateTemporary : public MessageLoopRelay {
108 public:
109 RelayCreateTemporary(
110 scoped_refptr<MessageLoopProxy> message_loop_proxy,
111 int additional_file_flags,
112 const FileUtilProxy::CreateTemporaryCallback& callback)
113 : message_loop_proxy_(message_loop_proxy),
114 additional_file_flags_(additional_file_flags),
115 callback_(callback),
116 file_handle_(kInvalidPlatformFileValue) {
117 DCHECK_EQ(false, callback.is_null());
118 }
119
120 protected:
121 virtual ~RelayCreateTemporary() {
122 if (file_handle_ != kInvalidPlatformFileValue)
123 FileUtilProxy::Close(message_loop_proxy_, file_handle_,
124 FileUtilProxy::StatusCallback());
125 }
126
127 virtual void RunWork() {
128 // TODO(darin): file_util should have a variant of CreateTemporaryFile 138 // TODO(darin): file_util should have a variant of CreateTemporaryFile
129 // that returns a FilePath and a PlatformFile. 139 // that returns a FilePath and a PlatformFile.
130 file_util::CreateTemporaryFile(&file_path_); 140 file_util::CreateTemporaryFile(&file_path_);
131 141
132 int file_flags = 142 int file_flags =
133 PLATFORM_FILE_WRITE | 143 PLATFORM_FILE_WRITE |
134 PLATFORM_FILE_TEMPORARY | 144 PLATFORM_FILE_TEMPORARY |
135 PLATFORM_FILE_CREATE_ALWAYS | 145 PLATFORM_FILE_CREATE_ALWAYS |
136 additional_file_flags_; 146 additional_file_flags;
137 147
138 PlatformFileError error_code = PLATFORM_FILE_OK; 148 error_ = PLATFORM_FILE_OK;
139 file_handle_ = CreatePlatformFile(file_path_, file_flags, 149 file_handle_ = CreatePlatformFile(file_path_, file_flags, NULL, &error_);
140 NULL, &error_code);
141 set_error_code(error_code);
142 } 150 }
143 151
144 virtual void RunCallback() { 152 void Reply(scoped_refptr<MessageLoopProxy> message_loop_proxy,
willchan no longer on Chromium 2011/10/19 00:26:52 MessageLoopProxy* instead. What's important is the
kinuko 2011/10/19 08:42:05 Done. Actually it seems the Close needs to be cal
145 callback_.Run(error_code(), PassPlatformFile(&file_handle_), 153 const FileUtilProxy::CreateTemporaryCallback& callback) {
146 file_path_); 154 DCHECK(!callback.is_null());
147 } 155 callback.Run(error_, PassPlatformFile(&file_handle_), file_path_);
148 156 if (file_handle_ != kInvalidPlatformFileValue) {
149 private: 157 FileUtilProxy::Close(message_loop_proxy, file_handle_,
150 scoped_refptr<MessageLoopProxy> message_loop_proxy_; 158 FileUtilProxy::StatusCallback());
151 int additional_file_flags_; 159 }
152 FileUtilProxy::CreateTemporaryCallback callback_; 160 delete this;
153 PlatformFile file_handle_;
154 FilePath file_path_;
155 };
156
157 class RelayWithStatusCallback : public MessageLoopRelay {
158 public:
159 explicit RelayWithStatusCallback(
160 const FileUtilProxy::StatusCallback& callback)
161 : callback_(callback) {
162 // It is OK for callback to be NULL.
163 }
164
165 protected:
166 virtual void RunCallback() {
167 // The caller may not have been interested in the result.
168 if (!callback_.is_null())
169 callback_.Run(error_code());
170 }
171
172 private:
173 FileUtilProxy::StatusCallback callback_;
174 };
175
176 class RelayClose : public RelayWithStatusCallback {
177 public:
178 RelayClose(PlatformFile file_handle,
179 const FileUtilProxy::StatusCallback& callback)
180 : RelayWithStatusCallback(callback),
181 file_handle_(file_handle) {
182 }
183
184 protected:
185 virtual void RunWork() {
186 if (!ClosePlatformFile(file_handle_))
187 set_error_code(PLATFORM_FILE_ERROR_FAILED);
188 } 161 }
189 162
190 private: 163 private:
191 PlatformFile file_handle_; 164 PlatformFile file_handle_;
165 FilePath file_path_;
166 PlatformFileError error_;
192 }; 167 };
193 168
194 class RelayDelete : public RelayWithStatusCallback { 169 PlatformFileError DeleteHelper(const FilePath& file_path, bool recursive) {
170 if (!file_util::PathExists(file_path)) {
171 return PLATFORM_FILE_ERROR_NOT_FOUND;
172 }
173 if (!file_util::Delete(file_path, recursive)) {
174 if (!recursive && !file_util::IsDirectoryEmpty(file_path)) {
175 return PLATFORM_FILE_ERROR_NOT_EMPTY;
176 }
177 return PLATFORM_FILE_ERROR_FAILED;
178 }
179 return PLATFORM_FILE_OK;
180 }
181
182 class GetFileInfoHelper {
195 public: 183 public:
196 RelayDelete(const FilePath& file_path, 184 GetFileInfoHelper()
197 bool recursive, 185 : error_(PLATFORM_FILE_OK) {}
198 const FileUtilProxy::StatusCallback& callback) 186
199 : RelayWithStatusCallback(callback), 187 void RunWorkForFilePath(const FilePath& file_path) {
200 file_path_(file_path), 188 if (!file_util::PathExists(file_path)) {
201 recursive_(recursive) { 189 error_ = PLATFORM_FILE_ERROR_NOT_FOUND;
190 return;
191 }
192 if (!file_util::GetFileInfo(file_path, &file_info_))
193 error_ = PLATFORM_FILE_ERROR_FAILED;
202 } 194 }
203 195
204 protected: 196 void RunWorkForPlatformFile(PlatformFile file) {
205 virtual void RunWork() { 197 if (!GetPlatformFileInfo(file, &file_info_))
206 if (!file_util::PathExists(file_path_)) { 198 error_ = PLATFORM_FILE_ERROR_FAILED;
207 set_error_code(PLATFORM_FILE_ERROR_NOT_FOUND); 199 }
208 return; 200
201 void Reply(const FileUtilProxy::GetFileInfoCallback& callback) {
202 if (!callback.is_null()) {
203 callback.Run(error_, file_info_);
209 } 204 }
210 if (!file_util::Delete(file_path_, recursive_)) { 205 delete this;
211 if (!recursive_ && !file_util::IsDirectoryEmpty(file_path_)) {
212 set_error_code(PLATFORM_FILE_ERROR_NOT_EMPTY);
213 return;
214 }
215 set_error_code(PLATFORM_FILE_ERROR_FAILED);
216 }
217 } 206 }
218 207
219 private: 208 private:
220 FilePath file_path_; 209 PlatformFileError error_;
221 bool recursive_; 210 PlatformFileInfo file_info_;
222 }; 211 };
223 212
224 class RelayGetFileInfo : public MessageLoopRelay { 213 class ReadHelper {
225 public: 214 public:
226 RelayGetFileInfo(const FilePath& file_path, 215 ReadHelper(int bytes_to_read)
227 const FileUtilProxy::GetFileInfoCallback& callback) 216 : buffer_(new char[bytes_to_read]),
228 : callback_(callback), 217 bytes_to_read_(bytes_to_read),
229 file_path_(file_path) { 218 bytes_read_(0) {}
230 DCHECK_EQ(false, callback.is_null()); 219
220 void RunWork(PlatformFile file, int64 offset) {
221 bytes_read_ = ReadPlatformFile(file, offset, buffer_.get(), bytes_to_read_);
231 } 222 }
232 223
233 protected: 224 void Reply(const FileUtilProxy::ReadCallback& callback) {
234 virtual void RunWork() { 225 if (!callback.is_null()) {
235 if (!file_util::PathExists(file_path_)) { 226 PlatformFileError error =
236 set_error_code(PLATFORM_FILE_ERROR_NOT_FOUND); 227 (bytes_read_ < 0) ? PLATFORM_FILE_ERROR_FAILED : PLATFORM_FILE_OK;
237 return; 228 callback.Run(error, buffer_.get(), bytes_read_);
238 } 229 }
239 if (!file_util::GetFileInfo(file_path_, &file_info_)) 230 delete this;
240 set_error_code(PLATFORM_FILE_ERROR_FAILED);
241 }
242
243 virtual void RunCallback() {
244 callback_.Run(error_code(), file_info_);
245 } 231 }
246 232
247 private: 233 private:
248 FileUtilProxy::GetFileInfoCallback callback_;
249 FilePath file_path_;
250 PlatformFileInfo file_info_;
251 };
252
253 class RelayGetFileInfoFromPlatformFile : public MessageLoopRelay {
254 public:
255 RelayGetFileInfoFromPlatformFile(
256 PlatformFile file,
257 const FileUtilProxy::GetFileInfoCallback& callback)
258 : callback_(callback),
259 file_(file) {
260 DCHECK_EQ(false, callback.is_null());
261 }
262
263 protected:
264 virtual void RunWork() {
265 if (!GetPlatformFileInfo(file_, &file_info_))
266 set_error_code(PLATFORM_FILE_ERROR_FAILED);
267 }
268
269 virtual void RunCallback() {
270 callback_.Run(error_code(), file_info_);
271 }
272
273 private:
274 FileUtilProxy::GetFileInfoCallback callback_;
275 PlatformFile file_;
276 PlatformFileInfo file_info_;
277 };
278
279 class RelayRead : public MessageLoopRelay {
280 public:
281 RelayRead(PlatformFile file,
282 int64 offset,
283 int bytes_to_read,
284 const FileUtilProxy::ReadCallback& callback)
285 : file_(file),
286 offset_(offset),
287 buffer_(new char[bytes_to_read]),
288 bytes_to_read_(bytes_to_read),
289 callback_(callback),
290 bytes_read_(0) {
291 }
292
293 protected:
294 virtual void RunWork() {
295 bytes_read_ = ReadPlatformFile(file_, offset_, buffer_.get(),
296 bytes_to_read_);
297 if (bytes_read_ < 0)
298 set_error_code(PLATFORM_FILE_ERROR_FAILED);
299 }
300
301 virtual void RunCallback() {
302 if (!callback_.is_null())
303 callback_.Run(error_code(), buffer_.get(), bytes_read_);
304 }
305
306 private:
307 PlatformFile file_;
308 int64 offset_;
309 scoped_array<char> buffer_; 234 scoped_array<char> buffer_;
310 int bytes_to_read_; 235 int bytes_to_read_;
311 FileUtilProxy::ReadCallback callback_;
312 int bytes_read_; 236 int bytes_read_;
313 }; 237 };
314 238
315 class RelayWrite : public MessageLoopRelay { 239 class WriteHelper {
316 public: 240 public:
317 RelayWrite(PlatformFile file, 241 WriteHelper(const char* buffer, int bytes_to_write)
318 int64 offset, 242 : buffer_(new char[bytes_to_write]),
319 const char* buffer,
320 int bytes_to_write,
321 const FileUtilProxy::WriteCallback& callback)
322 : file_(file),
323 offset_(offset),
324 buffer_(new char[bytes_to_write]),
325 bytes_to_write_(bytes_to_write), 243 bytes_to_write_(bytes_to_write),
326 callback_(callback),
327 bytes_written_(0) { 244 bytes_written_(0) {
328 memcpy(buffer_.get(), buffer, bytes_to_write); 245 memcpy(buffer_.get(), buffer, bytes_to_write);
329 } 246 }
330 247
331 protected: 248 void RunWork(PlatformFile file, int64 offset) {
332 virtual void RunWork() { 249 bytes_written_ = WritePlatformFile(file, offset, buffer_.get(),
333 bytes_written_ = WritePlatformFile(file_, offset_, buffer_.get(), 250 bytes_to_write_);
334 bytes_to_write_);
335 if (bytes_written_ < 0)
336 set_error_code(PLATFORM_FILE_ERROR_FAILED);
337 } 251 }
338 252
339 virtual void RunCallback() { 253 void Reply(const FileUtilProxy::WriteCallback& callback) {
340 if (!callback_.is_null()) 254 if (!callback.is_null()) {
341 callback_.Run(error_code(), bytes_written_); 255 PlatformFileError error =
256 (bytes_written_ < 0) ? PLATFORM_FILE_ERROR_FAILED : PLATFORM_FILE_OK;
257 callback.Run(error, bytes_written_);
258 }
259 delete this;
342 } 260 }
343 261
344 private: 262 private:
345 PlatformFile file_;
346 int64 offset_;
347 scoped_array<char> buffer_; 263 scoped_array<char> buffer_;
348 int bytes_to_write_; 264 int bytes_to_write_;
349 FileUtilProxy::WriteCallback callback_;
350 int bytes_written_; 265 int bytes_written_;
351 }; 266 };
352 267
353 class RelayTouch : public RelayWithStatusCallback {
354 public:
355 RelayTouch(PlatformFile file,
356 const Time& last_access_time,
357 const Time& last_modified_time,
358 const FileUtilProxy::StatusCallback& callback)
359 : RelayWithStatusCallback(callback),
360 file_(file),
361 last_access_time_(last_access_time),
362 last_modified_time_(last_modified_time) {
363 }
364
365 protected:
366 virtual void RunWork() {
367 if (!TouchPlatformFile(file_, last_access_time_, last_modified_time_))
368 set_error_code(PLATFORM_FILE_ERROR_FAILED);
369 }
370
371 private:
372 PlatformFile file_;
373 Time last_access_time_;
374 Time last_modified_time_;
375 };
376
377 class RelayTouchFilePath : public RelayWithStatusCallback {
378 public:
379 RelayTouchFilePath(const FilePath& file_path,
380 const Time& last_access_time,
381 const Time& last_modified_time,
382 const FileUtilProxy::StatusCallback& callback)
383 : RelayWithStatusCallback(callback),
384 file_path_(file_path),
385 last_access_time_(last_access_time),
386 last_modified_time_(last_modified_time) {
387 }
388
389 protected:
390 virtual void RunWork() {
391 if (!file_util::TouchFile(
392 file_path_, last_access_time_, last_modified_time_))
393 set_error_code(PLATFORM_FILE_ERROR_FAILED);
394 }
395
396 private:
397 FilePath file_path_;
398 Time last_access_time_;
399 Time last_modified_time_;
400 };
401
402 class RelayTruncatePlatformFile : public RelayWithStatusCallback {
403 public:
404 RelayTruncatePlatformFile(PlatformFile file,
405 int64 length,
406 const FileUtilProxy::StatusCallback& callback)
407 : RelayWithStatusCallback(callback),
408 file_(file),
409 length_(length) {
410 }
411
412 protected:
413 virtual void RunWork() {
414 if (!TruncatePlatformFile(file_, length_))
415 set_error_code(PLATFORM_FILE_ERROR_FAILED);
416 }
417
418 private:
419 PlatformFile file_;
420 int64 length_;
421 };
422
423 class RelayTruncate : public RelayWithStatusCallback {
424 public:
425 RelayTruncate(const FilePath& path,
426 int64 length,
427 const FileUtilProxy::StatusCallback& callback)
428 : RelayWithStatusCallback(callback),
429 path_(path),
430 length_(length) {
431 }
432
433 protected:
434 virtual void RunWork() {
435 PlatformFileError error_code(PLATFORM_FILE_ERROR_FAILED);
436 PlatformFile file =
437 CreatePlatformFile(
438 path_,
439 PLATFORM_FILE_OPEN | PLATFORM_FILE_WRITE,
440 NULL,
441 &error_code);
442 if (error_code != PLATFORM_FILE_OK) {
443 set_error_code(error_code);
444 return;
445 }
446 if (!TruncatePlatformFile(file, length_))
447 set_error_code(PLATFORM_FILE_ERROR_FAILED);
448 ClosePlatformFile(file);
449 }
450
451 private:
452 FilePath path_;
453 int64 length_;
454 };
455
456 class RelayFlush : public RelayWithStatusCallback {
457 public:
458 RelayFlush(PlatformFile file,
459 const FileUtilProxy::StatusCallback& callback)
460 : RelayWithStatusCallback(callback),
461 file_(file) {
462 }
463
464 protected:
465 virtual void RunWork() {
466 if (!FlushPlatformFile(file_))
467 set_error_code(PLATFORM_FILE_ERROR_FAILED);
468 }
469
470 private:
471 PlatformFile file_;
472 };
473
474 bool Start(const tracked_objects::Location& from_here,
475 scoped_refptr<MessageLoopProxy> message_loop_proxy,
476 scoped_refptr<MessageLoopRelay> relay) {
477 return relay->Start(message_loop_proxy, from_here);
478 }
479
480 } // namespace 268 } // namespace
481 269
482 // static 270 // static
483 bool FileUtilProxy::CreateOrOpen( 271 bool FileUtilProxy::CreateOrOpen(
484 scoped_refptr<MessageLoopProxy> message_loop_proxy, 272 scoped_refptr<MessageLoopProxy> message_loop_proxy,
485 const FilePath& file_path, int file_flags, 273 const FilePath& file_path, int file_flags,
486 const CreateOrOpenCallback& callback) { 274 const CreateOrOpenCallback& callback) {
487 return Start(FROM_HERE, message_loop_proxy, new RelayCreateOrOpen( 275 CreateOrOpenHelper* helper = new CreateOrOpenHelper;
488 message_loop_proxy, file_path, file_flags, callback)); 276 if (!message_loop_proxy->PostTaskAndReply(
277 FROM_HERE,
278 Bind(&CreateOrOpenHelper::RunWork, base::Unretained(helper),
279 file_path, file_flags),
280 Bind(&CreateOrOpenHelper::Reply, base::Unretained(helper),
281 message_loop_proxy, callback))) {
282 delete helper;
283 return false;
284 }
285 return true;
489 } 286 }
490 287
491 // static 288 // static
492 bool FileUtilProxy::CreateTemporary( 289 bool FileUtilProxy::CreateTemporary(
493 scoped_refptr<MessageLoopProxy> message_loop_proxy, 290 scoped_refptr<MessageLoopProxy> message_loop_proxy,
494 int additional_file_flags, 291 int additional_file_flags,
495 const CreateTemporaryCallback& callback) { 292 const CreateTemporaryCallback& callback) {
496 return Start(FROM_HERE, message_loop_proxy, 293 CreateTemporaryHelper* helper = new CreateTemporaryHelper;
497 new RelayCreateTemporary(message_loop_proxy, 294 if (!message_loop_proxy->PostTaskAndReply(
498 additional_file_flags, 295 FROM_HERE,
499 callback)); 296 Bind(&CreateTemporaryHelper::RunWork, base::Unretained(helper),
297 additional_file_flags),
298 Bind(&CreateTemporaryHelper::Reply, base::Unretained(helper),
299 message_loop_proxy, callback))) {
300 delete helper;
301 return false;
302 }
303 return true;
500 } 304 }
501 305
502 // static 306 // static
503 bool FileUtilProxy::Close(scoped_refptr<MessageLoopProxy> message_loop_proxy, 307 bool FileUtilProxy::Close(scoped_refptr<MessageLoopProxy> message_loop_proxy,
504 PlatformFile file_handle, 308 PlatformFile file_handle,
505 const StatusCallback& callback) { 309 const StatusCallback& callback) {
506 return Start(FROM_HERE, message_loop_proxy, 310 return PostTaskAndReplyWithStatus<bool>(
507 new RelayClose(file_handle, callback)); 311 message_loop_proxy, FROM_HERE,
312 Bind(&ClosePlatformFile, file_handle), callback,
313 new PlatformFileError);
508 } 314 }
509 315
510 // Retrieves the information about a file. It is invalid to pass NULL for the 316 // Retrieves the information about a file. It is invalid to pass NULL for the
511 // callback. 317 // callback.
512 bool FileUtilProxy::GetFileInfo( 318 bool FileUtilProxy::GetFileInfo(
513 scoped_refptr<MessageLoopProxy> message_loop_proxy, 319 scoped_refptr<MessageLoopProxy> message_loop_proxy,
514 const FilePath& file_path, 320 const FilePath& file_path,
515 const GetFileInfoCallback& callback) { 321 const GetFileInfoCallback& callback) {
516 return Start(FROM_HERE, message_loop_proxy, new RelayGetFileInfo( 322 GetFileInfoHelper* helper = new GetFileInfoHelper;
517 file_path, callback)); 323 if (!message_loop_proxy->PostTaskAndReply(
324 FROM_HERE,
325 Bind(&GetFileInfoHelper::RunWorkForFilePath,
326 base::Unretained(helper), file_path),
327 Bind(&GetFileInfoHelper::Reply, base::Unretained(helper), callback))) {
328 delete helper;
329 return false;
330 }
331 return true;
518 } 332 }
519 333
520 // static 334 // static
521 bool FileUtilProxy::GetFileInfoFromPlatformFile( 335 bool FileUtilProxy::GetFileInfoFromPlatformFile(
522 scoped_refptr<MessageLoopProxy> message_loop_proxy, 336 scoped_refptr<MessageLoopProxy> message_loop_proxy,
523 PlatformFile file, 337 PlatformFile file,
524 const GetFileInfoCallback& callback) { 338 const GetFileInfoCallback& callback) {
525 return Start(FROM_HERE, message_loop_proxy, 339 GetFileInfoHelper* helper = new GetFileInfoHelper;
526 new RelayGetFileInfoFromPlatformFile(file, callback)); 340 if (!message_loop_proxy->PostTaskAndReply(
341 FROM_HERE,
342 Bind(&GetFileInfoHelper::RunWorkForPlatformFile,
343 base::Unretained(helper), file),
344 Bind(&GetFileInfoHelper::Reply, base::Unretained(helper), callback))) {
345 delete helper;
346 return false;
347 }
348 return true;
527 } 349 }
528 350
529 // static 351 // static
530 bool FileUtilProxy::Delete(scoped_refptr<MessageLoopProxy> message_loop_proxy, 352 bool FileUtilProxy::Delete(scoped_refptr<MessageLoopProxy> message_loop_proxy,
531 const FilePath& file_path, 353 const FilePath& file_path,
532 bool recursive, 354 bool recursive,
533 const StatusCallback& callback) { 355 const StatusCallback& callback) {
534 return Start(FROM_HERE, message_loop_proxy, 356 return PostTaskAndReplyWithStatus<PlatformFileError>(
535 new RelayDelete(file_path, recursive, callback)); 357 message_loop_proxy, FROM_HERE,
358 Bind(&DeleteHelper, file_path, recursive), callback,
359 new PlatformFileError);
536 } 360 }
537 361
538 // static 362 // static
539 bool FileUtilProxy::RecursiveDelete( 363 bool FileUtilProxy::RecursiveDelete(
540 scoped_refptr<MessageLoopProxy> message_loop_proxy, 364 scoped_refptr<MessageLoopProxy> message_loop_proxy,
541 const FilePath& file_path, 365 const FilePath& file_path,
542 const StatusCallback& callback) { 366 const StatusCallback& callback) {
543 return Start(FROM_HERE, message_loop_proxy, 367 return PostTaskAndReplyWithStatus<PlatformFileError>(
544 new RelayDelete(file_path, true, callback)); 368 message_loop_proxy, FROM_HERE,
369 Bind(&DeleteHelper, file_path, true /* recursive */), callback,
370 new PlatformFileError);
545 } 371 }
546 372
547 // static 373 // static
548 bool FileUtilProxy::Read( 374 bool FileUtilProxy::Read(
549 scoped_refptr<MessageLoopProxy> message_loop_proxy, 375 scoped_refptr<MessageLoopProxy> message_loop_proxy,
550 PlatformFile file, 376 PlatformFile file,
551 int64 offset, 377 int64 offset,
552 int bytes_to_read, 378 int bytes_to_read,
553 const ReadCallback& callback) { 379 const ReadCallback& callback) {
554 if (bytes_to_read < 0) 380 if (bytes_to_read < 0) {
555 return false; 381 return false;
556 382 }
557 return Start(FROM_HERE, message_loop_proxy, 383 ReadHelper* helper = new ReadHelper(bytes_to_read);
558 new RelayRead(file, offset, bytes_to_read, callback)); 384 if (!message_loop_proxy->PostTaskAndReply(
385 FROM_HERE,
386 Bind(&ReadHelper::RunWork, base::Unretained(helper), file, offset),
387 Bind(&ReadHelper::Reply, base::Unretained(helper), callback))) {
388 delete helper;
389 return false;
390 }
391 return true;
559 } 392 }
560 393
561 // static 394 // static
562 bool FileUtilProxy::Write( 395 bool FileUtilProxy::Write(
563 scoped_refptr<MessageLoopProxy> message_loop_proxy, 396 scoped_refptr<MessageLoopProxy> message_loop_proxy,
564 PlatformFile file, 397 PlatformFile file,
565 int64 offset, 398 int64 offset,
566 const char* buffer, 399 const char* buffer,
567 int bytes_to_write, 400 int bytes_to_write,
568 const WriteCallback& callback) { 401 const WriteCallback& callback) {
569 if (bytes_to_write <= 0) 402 if (bytes_to_write <= 0 || buffer == NULL) {
570 return false; 403 return false;
571 404 }
572 return Start(FROM_HERE, message_loop_proxy, 405 WriteHelper* helper = new WriteHelper(buffer, bytes_to_write);
573 new RelayWrite(file, offset, buffer, bytes_to_write, callback)); 406 if (!message_loop_proxy->PostTaskAndReply(
407 FROM_HERE,
408 Bind(&WriteHelper::RunWork, base::Unretained(helper), file, offset),
409 Bind(&WriteHelper::Reply, base::Unretained(helper), callback))) {
410 delete helper;
411 return false;
412 }
413 return true;
574 } 414 }
575 415
576 // static 416 // static
577 bool FileUtilProxy::Touch( 417 bool FileUtilProxy::Touch(
578 scoped_refptr<MessageLoopProxy> message_loop_proxy, 418 scoped_refptr<MessageLoopProxy> message_loop_proxy,
579 PlatformFile file, 419 PlatformFile file,
580 const Time& last_access_time, 420 const Time& last_access_time,
581 const Time& last_modified_time, 421 const Time& last_modified_time,
582 const StatusCallback& callback) { 422 const StatusCallback& callback) {
583 return Start(FROM_HERE, message_loop_proxy, 423 return PostTaskAndReplyWithStatus<bool>(
584 new RelayTouch(file, last_access_time, last_modified_time, 424 message_loop_proxy, FROM_HERE,
585 callback)); 425 Bind(&TouchPlatformFile, file,
426 last_access_time, last_modified_time), callback,
427 new PlatformFileError);
586 } 428 }
587 429
588 // static 430 // static
589 bool FileUtilProxy::Touch( 431 bool FileUtilProxy::Touch(
590 scoped_refptr<MessageLoopProxy> message_loop_proxy, 432 scoped_refptr<MessageLoopProxy> message_loop_proxy,
591 const FilePath& file_path, 433 const FilePath& file_path,
592 const Time& last_access_time, 434 const Time& last_access_time,
593 const Time& last_modified_time, 435 const Time& last_modified_time,
594 const StatusCallback& callback) { 436 const StatusCallback& callback) {
595 return Start(FROM_HERE, message_loop_proxy, 437 return PostTaskAndReplyWithStatus<bool>(
596 new RelayTouchFilePath(file_path, last_access_time, 438 message_loop_proxy, FROM_HERE,
597 last_modified_time, callback)); 439 Bind(&file_util::TouchFile, file_path,
440 last_access_time, last_modified_time),
441 callback,
442 new PlatformFileError);
598 } 443 }
599 444
600 // static 445 // static
601 bool FileUtilProxy::Truncate( 446 bool FileUtilProxy::Truncate(
602 scoped_refptr<MessageLoopProxy> message_loop_proxy, 447 scoped_refptr<MessageLoopProxy> message_loop_proxy,
603 PlatformFile file, 448 PlatformFile file,
604 int64 length, 449 int64 length,
605 const StatusCallback& callback) { 450 const StatusCallback& callback) {
606 return Start(FROM_HERE, message_loop_proxy, 451 return PostTaskAndReplyWithStatus<bool>(
607 new RelayTruncatePlatformFile(file, length, callback)); 452 message_loop_proxy, FROM_HERE,
453 Bind(&TruncatePlatformFile, file, length), callback,
454 new PlatformFileError);
608 } 455 }
609 456
610 // static 457 // static
611 bool FileUtilProxy::Truncate(
612 scoped_refptr<MessageLoopProxy> message_loop_proxy,
613 const FilePath& path,
614 int64 length,
615 const StatusCallback& callback) {
616 return Start(FROM_HERE, message_loop_proxy,
617 new RelayTruncate(path, length, callback));
618 }
619
620 // static
621 bool FileUtilProxy::Flush( 458 bool FileUtilProxy::Flush(
622 scoped_refptr<MessageLoopProxy> message_loop_proxy, 459 scoped_refptr<MessageLoopProxy> message_loop_proxy,
623 PlatformFile file, 460 PlatformFile file,
624 const StatusCallback& callback) { 461 const StatusCallback& callback) {
625 return Start(FROM_HERE, message_loop_proxy, new RelayFlush(file, callback)); 462 return PostTaskAndReplyWithStatus<bool>(
463 message_loop_proxy, FROM_HERE,
464 Bind(&FlushPlatformFile, file), callback,
465 new PlatformFileError);
626 } 466 }
627 467
628 } // namespace base 468 } // namespace base
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698