Chromium Code Reviews| 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), 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 |
| OLD | NEW |