blob: ab7903e45fd13533ffaef15f0c5c9faa56e60bbd [file] [log] [blame]
dumi@chromium.orgc980e402010-08-21 07:42:50 +09001// Copyright (c) 2010 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
dumi@chromium.orgc980e402010-08-21 07:42:50 +09007#include "base/message_loop_proxy.h"
8
jianli@chromium.org9ed1f9d2010-08-31 11:42:36 +09009// TODO(jianli): Move the code from anonymous namespace to base namespace so
10// that all of the base:: prefixes would be unnecessary.
dumi@chromium.orgc980e402010-08-21 07:42:50 +090011namespace {
12
kinuko@chromium.org1a078042010-10-07 17:35:09 +090013namespace {
14
15// Performs common checks for move and copy.
16// This also removes the destination directory if it's non-empty and all other
17// checks are passed (so that the copy/move correctly overwrites the destination).
18static base::PlatformFileError PerformCommonCheckAndPreparationForMoveAndCopy(
19 const FilePath& src_file_path,
20 const FilePath& dest_file_path) {
21 // Exits earlier if the source path does not exist.
22 if (!file_util::PathExists(src_file_path))
23 return base::PLATFORM_FILE_ERROR_NOT_FOUND;
24
25 // The parent of the |dest_file_path| does not exist.
26 if (!file_util::DirectoryExists(dest_file_path.DirName()))
27 return base::PLATFORM_FILE_ERROR_NOT_FOUND;
28
29 // It is an error to try to copy/move an entry into its child.
30 if (src_file_path.IsParent(dest_file_path))
31 return base::PLATFORM_FILE_ERROR_INVALID_OPERATION;
32
33 // Now it is ok to return if the |dest_file_path| does not exist.
34 if (!file_util::PathExists(dest_file_path))
35 return base::PLATFORM_FILE_OK;
36
37 // |src_file_path| exists and is a directory.
38 // |dest_file_path| exists and is a file.
39 bool src_is_directory = file_util::DirectoryExists(src_file_path);
40 bool dest_is_directory = file_util::DirectoryExists(dest_file_path);
41 if (src_is_directory && !dest_is_directory)
42 return base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY;
43
44 // |src_file_path| exists and is a file.
45 // |dest_file_path| exists and is a directory.
46 if (!src_is_directory && dest_is_directory)
47 return base::PLATFORM_FILE_ERROR_NOT_A_FILE;
48
49 // It is an error to copy/move an entry into the same path.
50 if (src_file_path.value() == dest_file_path.value())
51 return base::PLATFORM_FILE_ERROR_EXISTS;
52
53 if (dest_is_directory) {
54 // It is an error to copy/move an entry to a non-empty directory.
55 // Otherwise the copy/move attempt must overwrite the destination, but
56 // the file_util's Copy or Move method doesn't perform overwrite
57 // on all platforms, so we delete the destination directory here.
58 // TODO(kinuko): may be better to change the file_util::{Copy,Move}.
59 if (!file_util::Delete(dest_file_path, false /* recursive */)) {
60 if (!file_util::IsDirectoryEmpty(dest_file_path))
61 return base::PLATFORM_FILE_ERROR_NOT_EMPTY;
62 return base::PLATFORM_FILE_ERROR_FAILED;
63 }
64 }
65 return base::PLATFORM_FILE_OK;
66}
67
68} // anonymous namespace
69
dumi@chromium.orgc980e402010-08-21 07:42:50 +090070class MessageLoopRelay
71 : public base::RefCountedThreadSafe<MessageLoopRelay> {
72 public:
73 MessageLoopRelay()
74 : origin_message_loop_proxy_(
kkanetkar@chromium.org3a3bdea2010-09-02 12:43:36 +090075 base::MessageLoopProxy::CreateForCurrentThread()),
dumi@chromium.org6dedd6d2010-08-25 05:26:23 +090076 error_code_(base::PLATFORM_FILE_OK) {
dumi@chromium.orgc980e402010-08-21 07:42:50 +090077 }
78
dumi@chromium.org6dedd6d2010-08-25 05:26:23 +090079 bool Start(scoped_refptr<base::MessageLoopProxy> message_loop_proxy,
dumi@chromium.orgc980e402010-08-21 07:42:50 +090080 const tracked_objects::Location& from_here) {
dumi@chromium.org6dedd6d2010-08-25 05:26:23 +090081 return message_loop_proxy->PostTask(
dumi@chromium.orgc980e402010-08-21 07:42:50 +090082 from_here,
83 NewRunnableMethod(this, &MessageLoopRelay::ProcessOnTargetThread));
84 }
85
86 protected:
87 friend class base::RefCountedThreadSafe<MessageLoopRelay>;
88 virtual ~MessageLoopRelay() {}
89
90 // Called to perform work on the FILE thread.
91 virtual void RunWork() = 0;
92
93 // Called to notify the callback on the origin thread.
94 virtual void RunCallback() = 0;
95
dumi@chromium.org50f197d2010-09-01 04:30:27 +090096 void set_error_code(base::PlatformFileError error_code) {
dumi@chromium.org6dedd6d2010-08-25 05:26:23 +090097 error_code_ = error_code;
98 }
99
dumi@chromium.org50f197d2010-09-01 04:30:27 +0900100 base::PlatformFileError error_code() const {
dumi@chromium.org6dedd6d2010-08-25 05:26:23 +0900101 return error_code_;
102 }
103
dumi@chromium.orgc980e402010-08-21 07:42:50 +0900104 private:
105 void ProcessOnTargetThread() {
106 RunWork();
107 origin_message_loop_proxy_->PostTask(
108 FROM_HERE,
109 NewRunnableMethod(this, &MessageLoopRelay::RunCallback));
110 }
111
112 scoped_refptr<base::MessageLoopProxy> origin_message_loop_proxy_;
dumi@chromium.org50f197d2010-09-01 04:30:27 +0900113 base::PlatformFileError error_code_;
dumi@chromium.orgc980e402010-08-21 07:42:50 +0900114};
115
116class RelayCreateOrOpen : public MessageLoopRelay {
117 public:
118 RelayCreateOrOpen(
119 scoped_refptr<base::MessageLoopProxy> message_loop_proxy,
120 const FilePath& file_path,
121 int file_flags,
kinuko@chromium.orga122bcf2010-10-12 07:00:55 +0900122 bool return_no_handle,
dumi@chromium.orgc980e402010-08-21 07:42:50 +0900123 base::FileUtilProxy::CreateOrOpenCallback* callback)
124 : message_loop_proxy_(message_loop_proxy),
125 file_path_(file_path),
126 file_flags_(file_flags),
127 callback_(callback),
128 file_handle_(base::kInvalidPlatformFileValue),
kinuko@chromium.orga122bcf2010-10-12 07:00:55 +0900129 return_no_handle_(return_no_handle),
dumi@chromium.orgc980e402010-08-21 07:42:50 +0900130 created_(false) {
131 DCHECK(callback);
132 }
133
134 protected:
135 virtual ~RelayCreateOrOpen() {
136 if (file_handle_ != base::kInvalidPlatformFileValue)
137 base::FileUtilProxy::Close(message_loop_proxy_, file_handle_, NULL);
138 }
139
140 virtual void RunWork() {
kinuko@chromium.orgaf334b22010-10-12 11:17:14 +0900141 if (!file_util::DirectoryExists(file_path_.DirName())) {
142 // If its parent does not exist, should return NOT_FOUND error.
143 set_error_code(base::PLATFORM_FILE_ERROR_NOT_FOUND);
144 return;
145 }
dumi@chromium.org50f197d2010-09-01 04:30:27 +0900146 base::PlatformFileError error_code = base::PLATFORM_FILE_OK;
147 file_handle_ = base::CreatePlatformFile(file_path_, file_flags_,
148 &created_, &error_code);
kinuko@chromium.orga122bcf2010-10-12 07:00:55 +0900149 // If the return_no_handle is true the caller is not interested
150 // in the file_handle_. Close it right now.
151 if (return_no_handle_ && file_handle_ != base::kInvalidPlatformFileValue) {
152 // We don't check the return value here.
153 base::ClosePlatformFile(file_handle_);
154 file_handle_ = base::kInvalidPlatformFileValue;
155 }
dumi@chromium.org50f197d2010-09-01 04:30:27 +0900156 set_error_code(error_code);
dumi@chromium.orgc980e402010-08-21 07:42:50 +0900157 }
158
159 virtual void RunCallback() {
dumi@chromium.org6dedd6d2010-08-25 05:26:23 +0900160 callback_->Run(error_code(), base::PassPlatformFile(&file_handle_),
161 created_);
dumi@chromium.orgc980e402010-08-21 07:42:50 +0900162 delete callback_;
163 }
164
165 private:
166 scoped_refptr<base::MessageLoopProxy> message_loop_proxy_;
167 FilePath file_path_;
168 int file_flags_;
169 base::FileUtilProxy::CreateOrOpenCallback* callback_;
170 base::PlatformFile file_handle_;
kinuko@chromium.orga122bcf2010-10-12 07:00:55 +0900171 bool return_no_handle_;
dumi@chromium.orgc980e402010-08-21 07:42:50 +0900172 bool created_;
173};
174
175class RelayCreateTemporary : public MessageLoopRelay {
176 public:
177 RelayCreateTemporary(
178 scoped_refptr<base::MessageLoopProxy> message_loop_proxy,
179 base::FileUtilProxy::CreateTemporaryCallback* callback)
180 : message_loop_proxy_(message_loop_proxy),
181 callback_(callback),
182 file_handle_(base::kInvalidPlatformFileValue) {
183 DCHECK(callback);
184 }
185
186 protected:
187 virtual ~RelayCreateTemporary() {
188 if (file_handle_ != base::kInvalidPlatformFileValue)
189 base::FileUtilProxy::Close(message_loop_proxy_, file_handle_, NULL);
190 }
191
192 virtual void RunWork() {
193 // TODO(darin): file_util should have a variant of CreateTemporaryFile
194 // that returns a FilePath and a PlatformFile.
195 file_util::CreateTemporaryFile(&file_path_);
196
197 // Use a fixed set of flags that are appropriate for writing to a temporary
198 // file from the IO thread using a net::FileStream.
199 int file_flags =
200 base::PLATFORM_FILE_CREATE_ALWAYS |
201 base::PLATFORM_FILE_WRITE |
202 base::PLATFORM_FILE_ASYNC |
203 base::PLATFORM_FILE_TEMPORARY;
dumi@chromium.org50f197d2010-09-01 04:30:27 +0900204 base::PlatformFileError error_code = base::PLATFORM_FILE_OK;
205 file_handle_ = base::CreatePlatformFile(file_path_, file_flags,
206 NULL, &error_code);
207 set_error_code(error_code);
dumi@chromium.orgc980e402010-08-21 07:42:50 +0900208 }
209
210 virtual void RunCallback() {
dumi@chromium.org6dedd6d2010-08-25 05:26:23 +0900211 callback_->Run(error_code(), base::PassPlatformFile(&file_handle_),
212 file_path_);
dumi@chromium.orgc980e402010-08-21 07:42:50 +0900213 delete callback_;
214 }
215
216 private:
217 scoped_refptr<base::MessageLoopProxy> message_loop_proxy_;
218 base::FileUtilProxy::CreateTemporaryCallback* callback_;
219 base::PlatformFile file_handle_;
220 FilePath file_path_;
221};
222
223class RelayWithStatusCallback : public MessageLoopRelay {
224 public:
225 explicit RelayWithStatusCallback(
226 base::FileUtilProxy::StatusCallback* callback)
dumi@chromium.org6dedd6d2010-08-25 05:26:23 +0900227 : callback_(callback) {
dumi@chromium.orgc980e402010-08-21 07:42:50 +0900228 // It is OK for callback to be NULL.
229 }
230
231 protected:
232 virtual void RunCallback() {
233 // The caller may not have been interested in the result.
234 if (callback_) {
dumi@chromium.org6dedd6d2010-08-25 05:26:23 +0900235 callback_->Run(error_code());
dumi@chromium.orgc980e402010-08-21 07:42:50 +0900236 delete callback_;
237 }
238 }
239
dumi@chromium.orgc980e402010-08-21 07:42:50 +0900240 private:
241 base::FileUtilProxy::StatusCallback* callback_;
dumi@chromium.orgc980e402010-08-21 07:42:50 +0900242};
243
244class RelayClose : public RelayWithStatusCallback {
245 public:
246 RelayClose(base::PlatformFile file_handle,
247 base::FileUtilProxy::StatusCallback* callback)
248 : RelayWithStatusCallback(callback),
249 file_handle_(file_handle) {
250 }
251
252 protected:
253 virtual void RunWork() {
dumi@chromium.org6dedd6d2010-08-25 05:26:23 +0900254 if (!base::ClosePlatformFile(file_handle_))
dumi@chromium.org50f197d2010-09-01 04:30:27 +0900255 set_error_code(base::PLATFORM_FILE_ERROR_FAILED);
dumi@chromium.orgc980e402010-08-21 07:42:50 +0900256 }
257
258 private:
259 base::PlatformFile file_handle_;
260};
261
262class RelayDelete : public RelayWithStatusCallback {
263 public:
264 RelayDelete(const FilePath& file_path,
265 bool recursive,
266 base::FileUtilProxy::StatusCallback* callback)
267 : RelayWithStatusCallback(callback),
268 file_path_(file_path),
269 recursive_(recursive) {
270 }
271
272 protected:
273 virtual void RunWork() {
kkanetkar@chromium.org3a3bdea2010-09-02 12:43:36 +0900274 if (!file_util::PathExists(file_path_)) {
275 set_error_code(base::PLATFORM_FILE_ERROR_NOT_FOUND);
276 return;
277 }
278 if (!file_util::Delete(file_path_, recursive_)) {
279 if (!recursive_ && !file_util::IsDirectoryEmpty(file_path_)) {
kinuko@chromium.org1a078042010-10-07 17:35:09 +0900280 set_error_code(base::PLATFORM_FILE_ERROR_NOT_EMPTY);
kkanetkar@chromium.org3a3bdea2010-09-02 12:43:36 +0900281 return;
282 }
dumi@chromium.org50f197d2010-09-01 04:30:27 +0900283 set_error_code(base::PLATFORM_FILE_ERROR_FAILED);
kkanetkar@chromium.org3a3bdea2010-09-02 12:43:36 +0900284 }
dumi@chromium.orgc980e402010-08-21 07:42:50 +0900285 }
286
287 private:
288 FilePath file_path_;
289 bool recursive_;
290};
291
kkanetkar@chromium.org3a3bdea2010-09-02 12:43:36 +0900292class RelayCopy : public RelayWithStatusCallback {
293 public:
294 RelayCopy(const FilePath& src_file_path,
295 const FilePath& dest_file_path,
296 base::FileUtilProxy::StatusCallback* callback)
297 : RelayWithStatusCallback(callback),
298 src_file_path_(src_file_path),
299 dest_file_path_(dest_file_path) {
300 }
301
302 protected:
303 virtual void RunWork() {
kinuko@chromium.org1a078042010-10-07 17:35:09 +0900304 set_error_code(PerformCommonCheckAndPreparationForMoveAndCopy(
305 src_file_path_, dest_file_path_));
306 if (error_code() != base::PLATFORM_FILE_OK)
kkanetkar@chromium.org3a3bdea2010-09-02 12:43:36 +0900307 return;
kinuko@chromium.org31583c32010-10-07 06:44:35 +0900308 if (!file_util::CopyDirectory(src_file_path_, dest_file_path_,
kinuko@chromium.org1a078042010-10-07 17:35:09 +0900309 true /* recursive */))
kinuko@chromium.org31583c32010-10-07 06:44:35 +0900310 set_error_code(base::PLATFORM_FILE_ERROR_FAILED);
kkanetkar@chromium.org3a3bdea2010-09-02 12:43:36 +0900311 }
312
313 private:
314 FilePath src_file_path_;
315 FilePath dest_file_path_;
316};
317
318class RelayMove : public RelayWithStatusCallback {
319 public:
320 RelayMove(const FilePath& src_file_path,
321 const FilePath& dest_file_path,
322 base::FileUtilProxy::StatusCallback* callback)
323 : RelayWithStatusCallback(callback),
324 src_file_path_(src_file_path),
325 dest_file_path_(dest_file_path) {
326 }
327
328 protected:
329 virtual void RunWork() {
kinuko@chromium.org1a078042010-10-07 17:35:09 +0900330 set_error_code(PerformCommonCheckAndPreparationForMoveAndCopy(
331 src_file_path_, dest_file_path_));
332 if (error_code() != base::PLATFORM_FILE_OK)
kkanetkar@chromium.org3a3bdea2010-09-02 12:43:36 +0900333 return;
kinuko@chromium.org1a078042010-10-07 17:35:09 +0900334 if (!file_util::Move(src_file_path_, dest_file_path_))
kkanetkar@chromium.org3a3bdea2010-09-02 12:43:36 +0900335 set_error_code(base::PLATFORM_FILE_ERROR_FAILED);
kkanetkar@chromium.org3a3bdea2010-09-02 12:43:36 +0900336 }
337
338 private:
339 FilePath src_file_path_;
340 FilePath dest_file_path_;
341};
342
343class RelayCreateDirectory : public RelayWithStatusCallback {
344 public:
345 RelayCreateDirectory(
346 const FilePath& file_path,
347 bool exclusive,
kinuko@chromium.orgc483d792010-09-08 09:50:41 +0900348 bool recursive,
kkanetkar@chromium.org3a3bdea2010-09-02 12:43:36 +0900349 base::FileUtilProxy::StatusCallback* callback)
350 : RelayWithStatusCallback(callback),
351 file_path_(file_path),
kinuko@chromium.orgc483d792010-09-08 09:50:41 +0900352 exclusive_(exclusive),
353 recursive_(recursive) {
kkanetkar@chromium.org3a3bdea2010-09-02 12:43:36 +0900354 }
355
356 protected:
357 virtual void RunWork() {
358 bool path_exists = file_util::PathExists(file_path_);
359 // If parent dir of file doesn't exist.
kinuko@chromium.orgc483d792010-09-08 09:50:41 +0900360 if (!recursive_ && !file_util::PathExists(file_path_.DirName())) {
kkanetkar@chromium.org3a3bdea2010-09-02 12:43:36 +0900361 set_error_code(base::PLATFORM_FILE_ERROR_NOT_FOUND);
362 return;
363 }
364 if (exclusive_ && path_exists) {
365 set_error_code(base::PLATFORM_FILE_ERROR_EXISTS);
366 return;
367 }
368 // If file exists at the path.
369 if (path_exists && !file_util::DirectoryExists(file_path_)) {
370 set_error_code(base::PLATFORM_FILE_ERROR_EXISTS);
371 return;
372 }
373 if (!file_util::CreateDirectory(file_path_))
374 set_error_code(base::PLATFORM_FILE_ERROR_FAILED);
375 }
376
377 private:
378 FilePath file_path_;
379 bool exclusive_;
kinuko@chromium.orgc483d792010-09-08 09:50:41 +0900380 bool recursive_;
kkanetkar@chromium.org3a3bdea2010-09-02 12:43:36 +0900381};
382
383class RelayReadDirectory : public MessageLoopRelay {
384 public:
385 RelayReadDirectory(const FilePath& file_path,
386 base::FileUtilProxy::ReadDirectoryCallback* callback)
387 : callback_(callback), file_path_(file_path) {
388 DCHECK(callback);
389 }
390
391 protected:
392 virtual void RunWork() {
393 // TODO(kkanetkar): Implement directory read in multiple chunks.
394 if (!file_util::DirectoryExists(file_path_)) {
395 set_error_code(base::PLATFORM_FILE_ERROR_NOT_FOUND);
396 return;
397 }
398
399 file_util::FileEnumerator file_enum(
400 file_path_, false, static_cast<file_util::FileEnumerator::FILE_TYPE>(
401 file_util::FileEnumerator::FILES |
402 file_util::FileEnumerator::DIRECTORIES));
403 FilePath current;
404 while (!(current = file_enum.Next()).empty()) {
405 base::file_util_proxy::Entry entry;
406 file_util::FileEnumerator::FindInfo info;
407 file_enum.GetFindInfo(&info);
kinuko@chromium.org83604d12010-09-03 07:28:49 +0900408 entry.is_directory = file_enum.IsDirectory(info);
kkanetkar@chromium.org3a3bdea2010-09-02 12:43:36 +0900409 // This will just give the entry's name instead of entire path
410 // if we use current.value().
411 entry.name = file_util::FileEnumerator::GetFilename(info).value();
412 entries_.push_back(entry);
413 }
414 }
415
416 virtual void RunCallback() {
417 callback_->Run(error_code(), entries_);
418 delete callback_;
419 }
420
421 private:
422 base::FileUtilProxy::ReadDirectoryCallback* callback_;
423 FilePath file_path_;
424 std::vector<base::file_util_proxy::Entry> entries_;
425};
426
jianli@chromium.org9ed1f9d2010-08-31 11:42:36 +0900427class RelayGetFileInfo : public MessageLoopRelay {
428 public:
429 RelayGetFileInfo(const FilePath& file_path,
430 base::FileUtilProxy::GetFileInfoCallback* callback)
431 : callback_(callback),
dumi@chromium.org50f197d2010-09-01 04:30:27 +0900432 file_path_(file_path) {
jianli@chromium.org9ed1f9d2010-08-31 11:42:36 +0900433 DCHECK(callback);
434 }
435
436 protected:
437 virtual void RunWork() {
kkanetkar@chromium.org3a3bdea2010-09-02 12:43:36 +0900438 if (!file_util::PathExists(file_path_)) {
439 set_error_code(base::PLATFORM_FILE_ERROR_NOT_FOUND);
440 return;
441 }
dumi@chromium.org50f197d2010-09-01 04:30:27 +0900442 if (!file_util::GetFileInfo(file_path_, &file_info_))
443 set_error_code(base::PLATFORM_FILE_ERROR_FAILED);
jianli@chromium.org9ed1f9d2010-08-31 11:42:36 +0900444 }
445
446 virtual void RunCallback() {
dumi@chromium.org50f197d2010-09-01 04:30:27 +0900447 callback_->Run(error_code(), file_info_);
jianli@chromium.org9ed1f9d2010-08-31 11:42:36 +0900448 delete callback_;
449 }
450
451 private:
452 base::FileUtilProxy::GetFileInfoCallback* callback_;
453 FilePath file_path_;
dumi@chromium.org97ae2612010-09-03 11:28:37 +0900454 base::PlatformFileInfo file_info_;
jianli@chromium.org9ed1f9d2010-08-31 11:42:36 +0900455};
456
dumi@chromium.org23915982010-09-10 12:01:14 +0900457class RelayGetFileInfoFromPlatformFile : public MessageLoopRelay {
458 public:
459 RelayGetFileInfoFromPlatformFile(
460 base::PlatformFile file,
461 base::FileUtilProxy::GetFileInfoCallback* callback)
462 : callback_(callback),
463 file_(file) {
464 DCHECK(callback);
465 }
466
467 protected:
468 virtual void RunWork() {
469 if (!base::GetPlatformFileInfo(file_, &file_info_))
470 set_error_code(base::PLATFORM_FILE_ERROR_FAILED);
471 }
472
473 virtual void RunCallback() {
474 callback_->Run(error_code(), file_info_);
475 delete callback_;
476 }
477
478 private:
479 base::FileUtilProxy::GetFileInfoCallback* callback_;
480 base::PlatformFile file_;
481 base::PlatformFileInfo file_info_;
482};
483
484class RelayRead : public MessageLoopRelay {
485 public:
486 RelayRead(base::PlatformFile file,
487 int64 offset,
488 char* buffer,
489 int bytes_to_read,
490 base::FileUtilProxy::ReadWriteCallback* callback)
491 : file_(file),
492 offset_(offset),
493 buffer_(buffer),
494 bytes_to_read_(bytes_to_read),
495 callback_(callback),
496 bytes_read_(0) {
497 }
498
499 protected:
500 virtual void RunWork() {
501 bytes_read_ = base::ReadPlatformFile(file_, offset_, buffer_,
502 bytes_to_read_);
503 if (bytes_read_ < 0)
504 set_error_code(base::PLATFORM_FILE_ERROR_FAILED);
505 }
506
507 virtual void RunCallback() {
508 if (callback_) {
509 callback_->Run(error_code(), bytes_read_);
510 delete callback_;
511 }
512 }
513
514 private:
515 base::PlatformFile file_;
516 int64 offset_;
517 char* buffer_;
518 int bytes_to_read_;
519 base::FileUtilProxy::ReadWriteCallback* callback_;
520 int bytes_read_;
521};
522
523class RelayWrite : public MessageLoopRelay {
524 public:
525 RelayWrite(base::PlatformFile file,
ericu@google.com6a652222010-10-05 11:26:47 +0900526 int64 offset,
dumi@chromium.org23915982010-09-10 12:01:14 +0900527 const char* buffer,
528 int bytes_to_write,
529 base::FileUtilProxy::ReadWriteCallback* callback)
530 : file_(file),
531 offset_(offset),
532 buffer_(buffer),
533 bytes_to_write_(bytes_to_write),
534 callback_(callback) {
535 }
536
537 protected:
538 virtual void RunWork() {
539 bytes_written_ = base::WritePlatformFile(file_, offset_, buffer_,
540 bytes_to_write_);
541 if (bytes_written_ < 0)
542 set_error_code(base::PLATFORM_FILE_ERROR_FAILED);
543 }
544
545 virtual void RunCallback() {
546 if (callback_) {
547 callback_->Run(error_code(), bytes_written_);
548 delete callback_;
549 }
550 }
551
552 private:
553 base::PlatformFile file_;
554 int64 offset_;
555 const char* buffer_;
556 int bytes_to_write_;
557 base::FileUtilProxy::ReadWriteCallback* callback_;
558 int bytes_written_;
559};
560
561class RelayTouch : public RelayWithStatusCallback {
562 public:
563 RelayTouch(base::PlatformFile file,
564 const base::Time& last_access_time,
565 const base::Time& last_modified_time,
566 base::FileUtilProxy::StatusCallback* callback)
567 : RelayWithStatusCallback(callback),
568 file_(file),
569 last_access_time_(last_access_time),
570 last_modified_time_(last_modified_time) {
571 }
572
573 protected:
574 virtual void RunWork() {
575 if (!base::TouchPlatformFile(file_, last_access_time_, last_modified_time_))
576 set_error_code(base::PLATFORM_FILE_ERROR_FAILED);
577 }
578
579 private:
580 base::PlatformFile file_;
581 base::Time last_access_time_;
582 base::Time last_modified_time_;
583};
584
dumi@chromium.org12c2e2b2010-09-24 10:09:32 +0900585class RelayTouchFilePath : public RelayWithStatusCallback {
586 public:
587 RelayTouchFilePath(const FilePath& file_path,
588 const base::Time& last_access_time,
589 const base::Time& last_modified_time,
590 base::FileUtilProxy::StatusCallback* callback)
591 : RelayWithStatusCallback(callback),
evan@chromium.orgd719ede2010-09-25 05:07:41 +0900592 file_path_(file_path),
dumi@chromium.org12c2e2b2010-09-24 10:09:32 +0900593 last_access_time_(last_access_time),
594 last_modified_time_(last_modified_time) {
595 }
596
597 protected:
598 virtual void RunWork() {
599 if (!file_util::TouchFile(
600 file_path_, last_access_time_, last_modified_time_))
601 set_error_code(base::PLATFORM_FILE_ERROR_FAILED);
602 }
603
604 private:
605 FilePath file_path_;
606 base::Time last_access_time_;
607 base::Time last_modified_time_;
608};
609
ericu@google.com6a652222010-10-05 11:26:47 +0900610class RelayTruncatePlatformFile : public RelayWithStatusCallback {
dumi@chromium.org23915982010-09-10 12:01:14 +0900611 public:
ericu@google.com6a652222010-10-05 11:26:47 +0900612 RelayTruncatePlatformFile(base::PlatformFile file,
613 int64 length,
614 base::FileUtilProxy::StatusCallback* callback)
dumi@chromium.org23915982010-09-10 12:01:14 +0900615 : RelayWithStatusCallback(callback),
616 file_(file),
617 length_(length) {
618 }
619
620 protected:
621 virtual void RunWork() {
622 if (!base::TruncatePlatformFile(file_, length_))
623 set_error_code(base::PLATFORM_FILE_ERROR_FAILED);
624 }
625
626 private:
627 base::PlatformFile file_;
628 int64 length_;
629};
630
ericu@google.com6a652222010-10-05 11:26:47 +0900631class RelayTruncate : public RelayWithStatusCallback {
632 public:
633 RelayTruncate(const FilePath& path,
634 int64 length,
635 base::FileUtilProxy::StatusCallback* callback)
636 : RelayWithStatusCallback(callback),
637 path_(path),
638 length_(length) {
639 }
640
641 protected:
642 virtual void RunWork() {
643 base::PlatformFileError error_code(base::PLATFORM_FILE_ERROR_FAILED);
644 base::PlatformFile file =
645 base::CreatePlatformFile(
646 path_,
647 base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_WRITE,
648 NULL,
649 &error_code);
650 if (error_code != base::PLATFORM_FILE_OK) {
651 set_error_code(error_code);
652 return;
653 }
654 if (!base::TruncatePlatformFile(file, length_))
655 set_error_code(base::PLATFORM_FILE_ERROR_FAILED);
656 base::ClosePlatformFile(file);
657 }
658
659 private:
660 FilePath path_;
661 int64 length_;
662};
663
dumi@chromium.org23915982010-09-10 12:01:14 +0900664class RelayFlush : public RelayWithStatusCallback {
665 public:
666 RelayFlush(base::PlatformFile file,
667 base::FileUtilProxy::StatusCallback* callback)
668 : RelayWithStatusCallback(callback),
669 file_(file) {
670 }
671
672 protected:
673 virtual void RunWork() {
674 if (!base::FlushPlatformFile(file_))
675 set_error_code(base::PLATFORM_FILE_ERROR_FAILED);
676 }
677
678 private:
679 base::PlatformFile file_;
680};
681
dumi@chromium.org6dedd6d2010-08-25 05:26:23 +0900682bool Start(const tracked_objects::Location& from_here,
dumi@chromium.orgc980e402010-08-21 07:42:50 +0900683 scoped_refptr<base::MessageLoopProxy> message_loop_proxy,
684 scoped_refptr<MessageLoopRelay> relay) {
dumi@chromium.org6dedd6d2010-08-25 05:26:23 +0900685 return relay->Start(message_loop_proxy, from_here);
dumi@chromium.orgc980e402010-08-21 07:42:50 +0900686}
687
688} // namespace
689
690namespace base {
691
692// static
dumi@chromium.org6dedd6d2010-08-25 05:26:23 +0900693bool FileUtilProxy::CreateOrOpen(
dumi@chromium.orgc980e402010-08-21 07:42:50 +0900694 scoped_refptr<MessageLoopProxy> message_loop_proxy,
695 const FilePath& file_path, int file_flags,
696 CreateOrOpenCallback* callback) {
dumi@chromium.org6dedd6d2010-08-25 05:26:23 +0900697 return Start(FROM_HERE, message_loop_proxy, new RelayCreateOrOpen(
kinuko@chromium.orga122bcf2010-10-12 07:00:55 +0900698 message_loop_proxy, file_path, file_flags, false /* return_no_handle */,
699 callback));
700}
701
702// static
703bool FileUtilProxy::Create(
704 scoped_refptr<MessageLoopProxy> message_loop_proxy,
705 const FilePath& file_path, int file_flags,
706 CreateOrOpenCallback* callback) {
707 return Start(FROM_HERE, message_loop_proxy, new RelayCreateOrOpen(
708 message_loop_proxy, file_path, file_flags, true /* return_no_handle */,
709 callback));
dumi@chromium.orgc980e402010-08-21 07:42:50 +0900710}
711
712// static
dumi@chromium.org6dedd6d2010-08-25 05:26:23 +0900713bool FileUtilProxy::CreateTemporary(
dumi@chromium.orgc980e402010-08-21 07:42:50 +0900714 scoped_refptr<MessageLoopProxy> message_loop_proxy,
715 CreateTemporaryCallback* callback) {
dumi@chromium.org6dedd6d2010-08-25 05:26:23 +0900716 return Start(FROM_HERE, message_loop_proxy,
717 new RelayCreateTemporary(message_loop_proxy, callback));
dumi@chromium.orgc980e402010-08-21 07:42:50 +0900718}
719
720// static
kkanetkar@chromium.org3a3bdea2010-09-02 12:43:36 +0900721bool FileUtilProxy::CreateDirectory(
722 scoped_refptr<MessageLoopProxy> message_loop_proxy,
723 const FilePath& file_path,
724 bool exclusive,
kinuko@chromium.orgc483d792010-09-08 09:50:41 +0900725 bool recursive,
kkanetkar@chromium.org3a3bdea2010-09-02 12:43:36 +0900726 StatusCallback* callback) {
727 return Start(FROM_HERE, message_loop_proxy, new RelayCreateDirectory(
kinuko@chromium.orgc483d792010-09-08 09:50:41 +0900728 file_path, exclusive, recursive, callback));
kkanetkar@chromium.org3a3bdea2010-09-02 12:43:36 +0900729}
730
731// static
dumi@chromium.org6dedd6d2010-08-25 05:26:23 +0900732bool FileUtilProxy::Close(scoped_refptr<MessageLoopProxy> message_loop_proxy,
dumi@chromium.orgc980e402010-08-21 07:42:50 +0900733 base::PlatformFile file_handle,
734 StatusCallback* callback) {
dumi@chromium.org6dedd6d2010-08-25 05:26:23 +0900735 return Start(FROM_HERE, message_loop_proxy,
736 new RelayClose(file_handle, callback));
dumi@chromium.orgc980e402010-08-21 07:42:50 +0900737}
738
739// static
dumi@chromium.org6dedd6d2010-08-25 05:26:23 +0900740bool FileUtilProxy::Delete(scoped_refptr<MessageLoopProxy> message_loop_proxy,
dumi@chromium.orgc980e402010-08-21 07:42:50 +0900741 const FilePath& file_path,
kinuko@chromium.org1a078042010-10-07 17:35:09 +0900742 bool recursive,
dumi@chromium.orgc980e402010-08-21 07:42:50 +0900743 StatusCallback* callback) {
dumi@chromium.org6dedd6d2010-08-25 05:26:23 +0900744 return Start(FROM_HERE, message_loop_proxy,
kinuko@chromium.org1a078042010-10-07 17:35:09 +0900745 new RelayDelete(file_path, recursive, callback));
dumi@chromium.orgc980e402010-08-21 07:42:50 +0900746}
747
748// static
kkanetkar@chromium.org3a3bdea2010-09-02 12:43:36 +0900749bool FileUtilProxy::Copy(scoped_refptr<MessageLoopProxy> message_loop_proxy,
750 const FilePath& src_file_path,
751 const FilePath& dest_file_path,
752 StatusCallback* callback) {
753 return Start(FROM_HERE, message_loop_proxy,
754 new RelayCopy(src_file_path, dest_file_path, callback));
755}
756
757// static
758bool FileUtilProxy::Move(scoped_refptr<MessageLoopProxy> message_loop_proxy,
759 const FilePath& src_file_path,
760 const FilePath& dest_file_path,
761 StatusCallback* callback) {
762 return Start(FROM_HERE, message_loop_proxy,
763 new RelayMove(src_file_path, dest_file_path, callback));
764}
765
766// static
767bool FileUtilProxy::ReadDirectory(
768 scoped_refptr<MessageLoopProxy> message_loop_proxy,
769 const FilePath& file_path,
770 ReadDirectoryCallback* callback) {
771 return Start(FROM_HERE, message_loop_proxy, new RelayReadDirectory(
772 file_path, callback));
773}
774
775// Retrieves the information about a file. It is invalid to pass NULL for the
776// callback.
777bool FileUtilProxy::GetFileInfo(
778 scoped_refptr<MessageLoopProxy> message_loop_proxy,
779 const FilePath& file_path,
780 GetFileInfoCallback* callback) {
781 return Start(FROM_HERE, message_loop_proxy, new RelayGetFileInfo(
782 file_path, callback));
783}
784
785// static
dumi@chromium.org6dedd6d2010-08-25 05:26:23 +0900786bool FileUtilProxy::RecursiveDelete(
dumi@chromium.orgc980e402010-08-21 07:42:50 +0900787 scoped_refptr<MessageLoopProxy> message_loop_proxy,
788 const FilePath& file_path,
789 StatusCallback* callback) {
dumi@chromium.org6dedd6d2010-08-25 05:26:23 +0900790 return Start(FROM_HERE, message_loop_proxy,
791 new RelayDelete(file_path, true, callback));
dumi@chromium.orgc980e402010-08-21 07:42:50 +0900792}
793
dumi@chromium.org23915982010-09-10 12:01:14 +0900794// static
795bool FileUtilProxy::GetFileInfoFromPlatformFile(
796 scoped_refptr<MessageLoopProxy> message_loop_proxy,
797 PlatformFile file,
798 GetFileInfoCallback* callback) {
799 return Start(FROM_HERE, message_loop_proxy,
800 new RelayGetFileInfoFromPlatformFile(file, callback));
801}
802
803// static
804bool FileUtilProxy::Read(
805 scoped_refptr<MessageLoopProxy> message_loop_proxy,
806 PlatformFile file,
807 int64 offset,
808 char* buffer,
809 int bytes_to_read,
810 ReadWriteCallback* callback) {
811 return Start(FROM_HERE, message_loop_proxy,
812 new RelayRead(file, offset, buffer, bytes_to_read, callback));
813}
814
815// static
816bool FileUtilProxy::Write(
817 scoped_refptr<MessageLoopProxy> message_loop_proxy,
818 PlatformFile file,
819 int64 offset,
820 const char* buffer,
821 int bytes_to_write,
822 ReadWriteCallback* callback) {
823 return Start(FROM_HERE, message_loop_proxy,
824 new RelayWrite(file, offset, buffer, bytes_to_write, callback));
825}
826
827// static
828bool FileUtilProxy::Touch(
829 scoped_refptr<MessageLoopProxy> message_loop_proxy,
830 PlatformFile file,
831 const base::Time& last_access_time,
832 const base::Time& last_modified_time,
833 StatusCallback* callback) {
834 return Start(FROM_HERE, message_loop_proxy,
835 new RelayTouch(file, last_access_time, last_modified_time,
836 callback));
837}
838
839// static
dumi@chromium.org12c2e2b2010-09-24 10:09:32 +0900840bool FileUtilProxy::Touch(
841 scoped_refptr<MessageLoopProxy> message_loop_proxy,
842 const FilePath& file_path,
843 const base::Time& last_access_time,
844 const base::Time& last_modified_time,
845 StatusCallback* callback) {
846 return Start(FROM_HERE, message_loop_proxy,
847 new RelayTouchFilePath(file_path, last_access_time,
848 last_modified_time, callback));
849}
850
851// static
dumi@chromium.org23915982010-09-10 12:01:14 +0900852bool FileUtilProxy::Truncate(
853 scoped_refptr<MessageLoopProxy> message_loop_proxy,
854 PlatformFile file,
ericu@google.com6a652222010-10-05 11:26:47 +0900855 int64 length,
dumi@chromium.org23915982010-09-10 12:01:14 +0900856 StatusCallback* callback) {
857 return Start(FROM_HERE, message_loop_proxy,
ericu@google.com6a652222010-10-05 11:26:47 +0900858 new RelayTruncatePlatformFile(file, length, callback));
859}
860
861// static
862bool FileUtilProxy::Truncate(
863 scoped_refptr<MessageLoopProxy> message_loop_proxy,
864 const FilePath& path,
865 int64 length,
866 StatusCallback* callback) {
867 return Start(FROM_HERE, message_loop_proxy,
868 new RelayTruncate(path, length, callback));
dumi@chromium.org23915982010-09-10 12:01:14 +0900869}
870
871// static
872bool FileUtilProxy::Flush(
873 scoped_refptr<MessageLoopProxy> message_loop_proxy,
874 PlatformFile file,
875 StatusCallback* callback) {
876 return Start(FROM_HERE, message_loop_proxy, new RelayFlush(file, callback));
877}
878
kkanetkar@chromium.org3a3bdea2010-09-02 12:43:36 +0900879} // namespace base