| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "base/file_util_proxy.h" | |
| 6 | |
| 7 #include "base/bind.h" | |
| 8 #include "base/bind_helpers.h" | |
| 9 #include "base/file_util.h" | |
| 10 #include "base/location.h" | |
| 11 #include "base/message_loop_proxy.h" | |
| 12 #include "base/task_runner.h" | |
| 13 #include "base/task_runner_util.h" | |
| 14 | |
| 15 namespace base { | |
| 16 | |
| 17 namespace { | |
| 18 | |
| 19 void CallWithTranslatedParameter(const FileUtilProxy::StatusCallback& callback, | |
| 20 bool value) { | |
| 21 DCHECK(!callback.is_null()); | |
| 22 callback.Run(value ? PLATFORM_FILE_OK : PLATFORM_FILE_ERROR_FAILED); | |
| 23 } | |
| 24 | |
| 25 // Helper classes or routines for individual methods. | |
| 26 class CreateOrOpenHelper { | |
| 27 public: | |
| 28 CreateOrOpenHelper(TaskRunner* task_runner, | |
| 29 const FileUtilProxy::CloseTask& close_task) | |
| 30 : task_runner_(task_runner), | |
| 31 close_task_(close_task), | |
| 32 file_handle_(kInvalidPlatformFileValue), | |
| 33 created_(false), | |
| 34 error_(PLATFORM_FILE_OK) {} | |
| 35 | |
| 36 ~CreateOrOpenHelper() { | |
| 37 if (file_handle_ != kInvalidPlatformFileValue) { | |
| 38 task_runner_->PostTask( | |
| 39 FROM_HERE, | |
| 40 base::Bind(base::IgnoreResult(close_task_), file_handle_)); | |
| 41 } | |
| 42 } | |
| 43 | |
| 44 void RunWork(const FileUtilProxy::CreateOrOpenTask& task) { | |
| 45 error_ = task.Run(&file_handle_, &created_); | |
| 46 } | |
| 47 | |
| 48 void Reply(const FileUtilProxy::CreateOrOpenCallback& callback) { | |
| 49 DCHECK(!callback.is_null()); | |
| 50 callback.Run(error_, PassPlatformFile(&file_handle_), created_); | |
| 51 } | |
| 52 | |
| 53 private: | |
| 54 scoped_refptr<TaskRunner> task_runner_; | |
| 55 FileUtilProxy::CloseTask close_task_; | |
| 56 PlatformFile file_handle_; | |
| 57 bool created_; | |
| 58 PlatformFileError error_; | |
| 59 DISALLOW_COPY_AND_ASSIGN(CreateOrOpenHelper); | |
| 60 }; | |
| 61 | |
| 62 class CreateTemporaryHelper { | |
| 63 public: | |
| 64 explicit CreateTemporaryHelper(TaskRunner* task_runner) | |
| 65 : task_runner_(task_runner), | |
| 66 file_handle_(kInvalidPlatformFileValue), | |
| 67 error_(PLATFORM_FILE_OK) {} | |
| 68 | |
| 69 ~CreateTemporaryHelper() { | |
| 70 if (file_handle_ != kInvalidPlatformFileValue) { | |
| 71 FileUtilProxy::Close(task_runner_, file_handle_, | |
| 72 FileUtilProxy::StatusCallback()); | |
| 73 } | |
| 74 } | |
| 75 | |
| 76 void RunWork(int additional_file_flags) { | |
| 77 // TODO(darin): file_util should have a variant of CreateTemporaryFile | |
| 78 // that returns a FilePath and a PlatformFile. | |
| 79 file_util::CreateTemporaryFile(&file_path_); | |
| 80 | |
| 81 int file_flags = | |
| 82 PLATFORM_FILE_WRITE | | |
| 83 PLATFORM_FILE_TEMPORARY | | |
| 84 PLATFORM_FILE_CREATE_ALWAYS | | |
| 85 additional_file_flags; | |
| 86 | |
| 87 error_ = PLATFORM_FILE_OK; | |
| 88 file_handle_ = CreatePlatformFile(file_path_, file_flags, NULL, &error_); | |
| 89 } | |
| 90 | |
| 91 void Reply(const FileUtilProxy::CreateTemporaryCallback& callback) { | |
| 92 DCHECK(!callback.is_null()); | |
| 93 callback.Run(error_, PassPlatformFile(&file_handle_), file_path_); | |
| 94 } | |
| 95 | |
| 96 private: | |
| 97 scoped_refptr<TaskRunner> task_runner_; | |
| 98 PlatformFile file_handle_; | |
| 99 FilePath file_path_; | |
| 100 PlatformFileError error_; | |
| 101 DISALLOW_COPY_AND_ASSIGN(CreateTemporaryHelper); | |
| 102 }; | |
| 103 | |
| 104 class GetFileInfoHelper { | |
| 105 public: | |
| 106 GetFileInfoHelper() | |
| 107 : error_(PLATFORM_FILE_OK) {} | |
| 108 | |
| 109 void RunWorkForFilePath(const FilePath& file_path) { | |
| 110 if (!file_util::PathExists(file_path)) { | |
| 111 error_ = PLATFORM_FILE_ERROR_NOT_FOUND; | |
| 112 return; | |
| 113 } | |
| 114 if (!file_util::GetFileInfo(file_path, &file_info_)) | |
| 115 error_ = PLATFORM_FILE_ERROR_FAILED; | |
| 116 } | |
| 117 | |
| 118 void RunWorkForPlatformFile(PlatformFile file) { | |
| 119 if (!GetPlatformFileInfo(file, &file_info_)) | |
| 120 error_ = PLATFORM_FILE_ERROR_FAILED; | |
| 121 } | |
| 122 | |
| 123 void Reply(const FileUtilProxy::GetFileInfoCallback& callback) { | |
| 124 if (!callback.is_null()) { | |
| 125 callback.Run(error_, file_info_); | |
| 126 } | |
| 127 } | |
| 128 | |
| 129 private: | |
| 130 PlatformFileError error_; | |
| 131 PlatformFileInfo file_info_; | |
| 132 DISALLOW_COPY_AND_ASSIGN(GetFileInfoHelper); | |
| 133 }; | |
| 134 | |
| 135 class ReadHelper { | |
| 136 public: | |
| 137 explicit ReadHelper(int bytes_to_read) | |
| 138 : buffer_(new char[bytes_to_read]), | |
| 139 bytes_to_read_(bytes_to_read), | |
| 140 bytes_read_(0) {} | |
| 141 | |
| 142 void RunWork(PlatformFile file, int64 offset) { | |
| 143 bytes_read_ = ReadPlatformFile(file, offset, buffer_.get(), bytes_to_read_); | |
| 144 } | |
| 145 | |
| 146 void Reply(const FileUtilProxy::ReadCallback& callback) { | |
| 147 if (!callback.is_null()) { | |
| 148 PlatformFileError error = | |
| 149 (bytes_read_ < 0) ? PLATFORM_FILE_ERROR_FAILED : PLATFORM_FILE_OK; | |
| 150 callback.Run(error, buffer_.get(), bytes_read_); | |
| 151 } | |
| 152 } | |
| 153 | |
| 154 private: | |
| 155 scoped_ptr<char[]> buffer_; | |
| 156 int bytes_to_read_; | |
| 157 int bytes_read_; | |
| 158 DISALLOW_COPY_AND_ASSIGN(ReadHelper); | |
| 159 }; | |
| 160 | |
| 161 class WriteHelper { | |
| 162 public: | |
| 163 WriteHelper(const char* buffer, int bytes_to_write) | |
| 164 : buffer_(new char[bytes_to_write]), | |
| 165 bytes_to_write_(bytes_to_write), | |
| 166 bytes_written_(0) { | |
| 167 memcpy(buffer_.get(), buffer, bytes_to_write); | |
| 168 } | |
| 169 | |
| 170 void RunWork(PlatformFile file, int64 offset) { | |
| 171 bytes_written_ = WritePlatformFile(file, offset, buffer_.get(), | |
| 172 bytes_to_write_); | |
| 173 } | |
| 174 | |
| 175 void Reply(const FileUtilProxy::WriteCallback& callback) { | |
| 176 if (!callback.is_null()) { | |
| 177 PlatformFileError error = | |
| 178 (bytes_written_ < 0) ? PLATFORM_FILE_ERROR_FAILED : PLATFORM_FILE_OK; | |
| 179 callback.Run(error, bytes_written_); | |
| 180 } | |
| 181 } | |
| 182 | |
| 183 private: | |
| 184 scoped_ptr<char[]> buffer_; | |
| 185 int bytes_to_write_; | |
| 186 int bytes_written_; | |
| 187 DISALLOW_COPY_AND_ASSIGN(WriteHelper); | |
| 188 }; | |
| 189 | |
| 190 | |
| 191 PlatformFileError CreateOrOpenAdapter( | |
| 192 const FilePath& file_path, int file_flags, | |
| 193 PlatformFile* file_handle, bool* created) { | |
| 194 DCHECK(file_handle); | |
| 195 DCHECK(created); | |
| 196 if (!file_util::DirectoryExists(file_path.DirName())) { | |
| 197 // If its parent does not exist, should return NOT_FOUND error. | |
| 198 return PLATFORM_FILE_ERROR_NOT_FOUND; | |
| 199 } | |
| 200 PlatformFileError error = PLATFORM_FILE_OK; | |
| 201 *file_handle = CreatePlatformFile(file_path, file_flags, created, &error); | |
| 202 return error; | |
| 203 } | |
| 204 | |
| 205 PlatformFileError CloseAdapter(PlatformFile file_handle) { | |
| 206 if (!ClosePlatformFile(file_handle)) { | |
| 207 return PLATFORM_FILE_ERROR_FAILED; | |
| 208 } | |
| 209 return PLATFORM_FILE_OK; | |
| 210 } | |
| 211 | |
| 212 PlatformFileError DeleteAdapter(const FilePath& file_path, bool recursive) { | |
| 213 if (!file_util::PathExists(file_path)) { | |
| 214 return PLATFORM_FILE_ERROR_NOT_FOUND; | |
| 215 } | |
| 216 if (!file_util::Delete(file_path, recursive)) { | |
| 217 if (!recursive && !file_util::IsDirectoryEmpty(file_path)) { | |
| 218 return PLATFORM_FILE_ERROR_NOT_EMPTY; | |
| 219 } | |
| 220 return PLATFORM_FILE_ERROR_FAILED; | |
| 221 } | |
| 222 return PLATFORM_FILE_OK; | |
| 223 } | |
| 224 | |
| 225 } // namespace | |
| 226 | |
| 227 // static | |
| 228 bool FileUtilProxy::CreateOrOpen( | |
| 229 TaskRunner* task_runner, | |
| 230 const FilePath& file_path, int file_flags, | |
| 231 const CreateOrOpenCallback& callback) { | |
| 232 return RelayCreateOrOpen( | |
| 233 task_runner, | |
| 234 base::Bind(&CreateOrOpenAdapter, file_path, file_flags), | |
| 235 base::Bind(&CloseAdapter), | |
| 236 callback); | |
| 237 } | |
| 238 | |
| 239 // static | |
| 240 bool FileUtilProxy::CreateTemporary( | |
| 241 TaskRunner* task_runner, | |
| 242 int additional_file_flags, | |
| 243 const CreateTemporaryCallback& callback) { | |
| 244 CreateTemporaryHelper* helper = new CreateTemporaryHelper(task_runner); | |
| 245 return task_runner->PostTaskAndReply( | |
| 246 FROM_HERE, | |
| 247 Bind(&CreateTemporaryHelper::RunWork, Unretained(helper), | |
| 248 additional_file_flags), | |
| 249 Bind(&CreateTemporaryHelper::Reply, Owned(helper), callback)); | |
| 250 } | |
| 251 | |
| 252 // static | |
| 253 bool FileUtilProxy::Close( | |
| 254 TaskRunner* task_runner, | |
| 255 base::PlatformFile file_handle, | |
| 256 const StatusCallback& callback) { | |
| 257 return RelayClose( | |
| 258 task_runner, | |
| 259 base::Bind(&CloseAdapter), | |
| 260 file_handle, callback); | |
| 261 } | |
| 262 | |
| 263 // Retrieves the information about a file. It is invalid to pass NULL for the | |
| 264 // callback. | |
| 265 bool FileUtilProxy::GetFileInfo( | |
| 266 TaskRunner* task_runner, | |
| 267 const FilePath& file_path, | |
| 268 const GetFileInfoCallback& callback) { | |
| 269 GetFileInfoHelper* helper = new GetFileInfoHelper; | |
| 270 return task_runner->PostTaskAndReply( | |
| 271 FROM_HERE, | |
| 272 Bind(&GetFileInfoHelper::RunWorkForFilePath, | |
| 273 Unretained(helper), file_path), | |
| 274 Bind(&GetFileInfoHelper::Reply, Owned(helper), callback)); | |
| 275 } | |
| 276 | |
| 277 // static | |
| 278 bool FileUtilProxy::GetFileInfoFromPlatformFile( | |
| 279 TaskRunner* task_runner, | |
| 280 PlatformFile file, | |
| 281 const GetFileInfoCallback& callback) { | |
| 282 GetFileInfoHelper* helper = new GetFileInfoHelper; | |
| 283 return task_runner->PostTaskAndReply( | |
| 284 FROM_HERE, | |
| 285 Bind(&GetFileInfoHelper::RunWorkForPlatformFile, | |
| 286 Unretained(helper), file), | |
| 287 Bind(&GetFileInfoHelper::Reply, Owned(helper), callback)); | |
| 288 } | |
| 289 | |
| 290 // static | |
| 291 bool FileUtilProxy::Delete(TaskRunner* task_runner, | |
| 292 const FilePath& file_path, | |
| 293 bool recursive, | |
| 294 const StatusCallback& callback) { | |
| 295 return base::PostTaskAndReplyWithResult( | |
| 296 task_runner, FROM_HERE, | |
| 297 Bind(&DeleteAdapter, file_path, recursive), | |
| 298 callback); | |
| 299 } | |
| 300 | |
| 301 // static | |
| 302 bool FileUtilProxy::RecursiveDelete( | |
| 303 TaskRunner* task_runner, | |
| 304 const FilePath& file_path, | |
| 305 const StatusCallback& callback) { | |
| 306 return base::PostTaskAndReplyWithResult( | |
| 307 task_runner, FROM_HERE, | |
| 308 Bind(&DeleteAdapter, file_path, true /* recursive */), | |
| 309 callback); | |
| 310 } | |
| 311 | |
| 312 // static | |
| 313 bool FileUtilProxy::Read( | |
| 314 TaskRunner* task_runner, | |
| 315 PlatformFile file, | |
| 316 int64 offset, | |
| 317 int bytes_to_read, | |
| 318 const ReadCallback& callback) { | |
| 319 if (bytes_to_read < 0) { | |
| 320 return false; | |
| 321 } | |
| 322 ReadHelper* helper = new ReadHelper(bytes_to_read); | |
| 323 return task_runner->PostTaskAndReply( | |
| 324 FROM_HERE, | |
| 325 Bind(&ReadHelper::RunWork, Unretained(helper), file, offset), | |
| 326 Bind(&ReadHelper::Reply, Owned(helper), callback)); | |
| 327 } | |
| 328 | |
| 329 // static | |
| 330 bool FileUtilProxy::Write( | |
| 331 TaskRunner* task_runner, | |
| 332 PlatformFile file, | |
| 333 int64 offset, | |
| 334 const char* buffer, | |
| 335 int bytes_to_write, | |
| 336 const WriteCallback& callback) { | |
| 337 if (bytes_to_write <= 0 || buffer == NULL) { | |
| 338 return false; | |
| 339 } | |
| 340 WriteHelper* helper = new WriteHelper(buffer, bytes_to_write); | |
| 341 return task_runner->PostTaskAndReply( | |
| 342 FROM_HERE, | |
| 343 Bind(&WriteHelper::RunWork, Unretained(helper), file, offset), | |
| 344 Bind(&WriteHelper::Reply, Owned(helper), callback)); | |
| 345 } | |
| 346 | |
| 347 // static | |
| 348 bool FileUtilProxy::Touch( | |
| 349 TaskRunner* task_runner, | |
| 350 PlatformFile file, | |
| 351 const Time& last_access_time, | |
| 352 const Time& last_modified_time, | |
| 353 const StatusCallback& callback) { | |
| 354 return base::PostTaskAndReplyWithResult( | |
| 355 task_runner, | |
| 356 FROM_HERE, | |
| 357 Bind(&TouchPlatformFile, file, | |
| 358 last_access_time, last_modified_time), | |
| 359 Bind(&CallWithTranslatedParameter, callback)); | |
| 360 } | |
| 361 | |
| 362 // static | |
| 363 bool FileUtilProxy::Touch( | |
| 364 TaskRunner* task_runner, | |
| 365 const FilePath& file_path, | |
| 366 const Time& last_access_time, | |
| 367 const Time& last_modified_time, | |
| 368 const StatusCallback& callback) { | |
| 369 return base::PostTaskAndReplyWithResult( | |
| 370 task_runner, | |
| 371 FROM_HERE, | |
| 372 Bind(&file_util::TouchFile, file_path, | |
| 373 last_access_time, last_modified_time), | |
| 374 Bind(&CallWithTranslatedParameter, callback)); | |
| 375 } | |
| 376 | |
| 377 // static | |
| 378 bool FileUtilProxy::Truncate( | |
| 379 TaskRunner* task_runner, | |
| 380 PlatformFile file, | |
| 381 int64 length, | |
| 382 const StatusCallback& callback) { | |
| 383 return base::PostTaskAndReplyWithResult( | |
| 384 task_runner, | |
| 385 FROM_HERE, | |
| 386 Bind(&TruncatePlatformFile, file, length), | |
| 387 Bind(&CallWithTranslatedParameter, callback)); | |
| 388 } | |
| 389 | |
| 390 // static | |
| 391 bool FileUtilProxy::Flush( | |
| 392 TaskRunner* task_runner, | |
| 393 PlatformFile file, | |
| 394 const StatusCallback& callback) { | |
| 395 return base::PostTaskAndReplyWithResult( | |
| 396 task_runner, | |
| 397 FROM_HERE, | |
| 398 Bind(&FlushPlatformFile, file), | |
| 399 Bind(&CallWithTranslatedParameter, callback)); | |
| 400 } | |
| 401 | |
| 402 // static | |
| 403 bool FileUtilProxy::RelayCreateOrOpen( | |
| 404 TaskRunner* task_runner, | |
| 405 const CreateOrOpenTask& open_task, | |
| 406 const CloseTask& close_task, | |
| 407 const CreateOrOpenCallback& callback) { | |
| 408 CreateOrOpenHelper* helper = new CreateOrOpenHelper( | |
| 409 task_runner, close_task); | |
| 410 return task_runner->PostTaskAndReply( | |
| 411 FROM_HERE, | |
| 412 Bind(&CreateOrOpenHelper::RunWork, Unretained(helper), open_task), | |
| 413 Bind(&CreateOrOpenHelper::Reply, Owned(helper), callback)); | |
| 414 } | |
| 415 | |
| 416 // static | |
| 417 bool FileUtilProxy::RelayClose( | |
| 418 TaskRunner* task_runner, | |
| 419 const CloseTask& close_task, | |
| 420 PlatformFile file_handle, | |
| 421 const StatusCallback& callback) { | |
| 422 return base::PostTaskAndReplyWithResult( | |
| 423 task_runner, FROM_HERE, Bind(close_task, file_handle), callback); | |
| 424 } | |
| 425 | |
| 426 } // namespace base | |
| OLD | NEW |