| 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 |