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