blob: b1652c4f3a96f29e98a1a28ee68c7a98306e2b6f [file] [log] [blame]
[email protected]32aa75b2011-03-15 09:56:271// Copyright (c) 2011 The Chromium Authors. All rights reserved.
[email protected]b90c93ff2010-08-20 22:42:502// 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
[email protected]b90c93ff2010-08-20 22:42:507#include "base/message_loop_proxy.h"
8
[email protected]81070042010-08-31 02:42:369// TODO(jianli): Move the code from anonymous namespace to base namespace so
10// that all of the base:: prefixes would be unnecessary.
[email protected]b90c93ff2010-08-20 22:42:5011namespace {
12
[email protected]81b18ca2010-10-07 08:35:0913namespace {
14
15// Performs common checks for move and copy.
16// This also removes the destination directory if it's non-empty and all other
[email protected]fd55c282010-10-15 00:37:3417// checks are passed (so that the copy/move correctly overwrites the
18// destination).
[email protected]81b18ca2010-10-07 08:35:0919static base::PlatformFileError PerformCommonCheckAndPreparationForMoveAndCopy(
20 const FilePath& src_file_path,
21 const FilePath& dest_file_path) {
22 // Exits earlier if the source path does not exist.
23 if (!file_util::PathExists(src_file_path))
24 return base::PLATFORM_FILE_ERROR_NOT_FOUND;
25
26 // The parent of the |dest_file_path| does not exist.
27 if (!file_util::DirectoryExists(dest_file_path.DirName()))
28 return base::PLATFORM_FILE_ERROR_NOT_FOUND;
29
30 // It is an error to try to copy/move an entry into its child.
31 if (src_file_path.IsParent(dest_file_path))
32 return base::PLATFORM_FILE_ERROR_INVALID_OPERATION;
33
34 // Now it is ok to return if the |dest_file_path| does not exist.
35 if (!file_util::PathExists(dest_file_path))
36 return base::PLATFORM_FILE_OK;
37
38 // |src_file_path| exists and is a directory.
39 // |dest_file_path| exists and is a file.
40 bool src_is_directory = file_util::DirectoryExists(src_file_path);
41 bool dest_is_directory = file_util::DirectoryExists(dest_file_path);
42 if (src_is_directory && !dest_is_directory)
43 return base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY;
44
45 // |src_file_path| exists and is a file.
46 // |dest_file_path| exists and is a directory.
47 if (!src_is_directory && dest_is_directory)
48 return base::PLATFORM_FILE_ERROR_NOT_A_FILE;
49
50 // It is an error to copy/move an entry into the same path.
51 if (src_file_path.value() == dest_file_path.value())
52 return base::PLATFORM_FILE_ERROR_EXISTS;
53
54 if (dest_is_directory) {
55 // It is an error to copy/move an entry to a non-empty directory.
56 // Otherwise the copy/move attempt must overwrite the destination, but
57 // the file_util's Copy or Move method doesn't perform overwrite
58 // on all platforms, so we delete the destination directory here.
59 // TODO(kinuko): may be better to change the file_util::{Copy,Move}.
60 if (!file_util::Delete(dest_file_path, false /* recursive */)) {
61 if (!file_util::IsDirectoryEmpty(dest_file_path))
62 return base::PLATFORM_FILE_ERROR_NOT_EMPTY;
63 return base::PLATFORM_FILE_ERROR_FAILED;
64 }
65 }
66 return base::PLATFORM_FILE_OK;
67}
68
[email protected]841daf1d2010-11-02 20:36:5269} // anonymous namespace
[email protected]81b18ca2010-10-07 08:35:0970
[email protected]b90c93ff2010-08-20 22:42:5071class MessageLoopRelay
72 : public base::RefCountedThreadSafe<MessageLoopRelay> {
73 public:
74 MessageLoopRelay()
75 : origin_message_loop_proxy_(
[email protected]edd685f2011-08-15 20:33:4676 base::MessageLoopProxy::current()),
[email protected]d480a3e2010-08-24 20:26:2377 error_code_(base::PLATFORM_FILE_OK) {
[email protected]b90c93ff2010-08-20 22:42:5078 }
79
[email protected]d480a3e2010-08-24 20:26:2380 bool Start(scoped_refptr<base::MessageLoopProxy> message_loop_proxy,
[email protected]b90c93ff2010-08-20 22:42:5081 const tracked_objects::Location& from_here) {
[email protected]d480a3e2010-08-24 20:26:2382 return message_loop_proxy->PostTask(
[email protected]b90c93ff2010-08-20 22:42:5083 from_here,
84 NewRunnableMethod(this, &MessageLoopRelay::ProcessOnTargetThread));
85 }
86
87 protected:
88 friend class base::RefCountedThreadSafe<MessageLoopRelay>;
89 virtual ~MessageLoopRelay() {}
90
91 // Called to perform work on the FILE thread.
92 virtual void RunWork() = 0;
93
94 // Called to notify the callback on the origin thread.
95 virtual void RunCallback() = 0;
96
[email protected]ed65fec2010-08-31 19:30:2797 void set_error_code(base::PlatformFileError error_code) {
[email protected]d480a3e2010-08-24 20:26:2398 error_code_ = error_code;
99 }
100
[email protected]ed65fec2010-08-31 19:30:27101 base::PlatformFileError error_code() const {
[email protected]d480a3e2010-08-24 20:26:23102 return error_code_;
103 }
104
[email protected]b90c93ff2010-08-20 22:42:50105 private:
106 void ProcessOnTargetThread() {
107 RunWork();
108 origin_message_loop_proxy_->PostTask(
109 FROM_HERE,
110 NewRunnableMethod(this, &MessageLoopRelay::RunCallback));
111 }
112
113 scoped_refptr<base::MessageLoopProxy> origin_message_loop_proxy_;
[email protected]ed65fec2010-08-31 19:30:27114 base::PlatformFileError error_code_;
[email protected]b90c93ff2010-08-20 22:42:50115};
116
117class RelayCreateOrOpen : public MessageLoopRelay {
118 public:
119 RelayCreateOrOpen(
120 scoped_refptr<base::MessageLoopProxy> message_loop_proxy,
121 const FilePath& file_path,
122 int file_flags,
[email protected]30c1eea2011-10-17 18:40:30123 const base::FileUtilProxy::CreateOrOpenCallback& callback)
[email protected]b90c93ff2010-08-20 22:42:50124 : message_loop_proxy_(message_loop_proxy),
125 file_path_(file_path),
126 file_flags_(file_flags),
127 callback_(callback),
128 file_handle_(base::kInvalidPlatformFileValue),
129 created_(false) {
[email protected]30c1eea2011-10-17 18:40:30130 DCHECK_EQ(false, callback.is_null());
[email protected]b90c93ff2010-08-20 22:42:50131 }
132
133 protected:
134 virtual ~RelayCreateOrOpen() {
135 if (file_handle_ != base::kInvalidPlatformFileValue)
136 base::FileUtilProxy::Close(message_loop_proxy_, file_handle_, NULL);
137 }
138
139 virtual void RunWork() {
[email protected]58c3a092010-10-12 02:17:14140 if (!file_util::DirectoryExists(file_path_.DirName())) {
141 // If its parent does not exist, should return NOT_FOUND error.
142 set_error_code(base::PLATFORM_FILE_ERROR_NOT_FOUND);
143 return;
144 }
[email protected]ed65fec2010-08-31 19:30:27145 base::PlatformFileError error_code = base::PLATFORM_FILE_OK;
146 file_handle_ = base::CreatePlatformFile(file_path_, file_flags_,
147 &created_, &error_code);
148 set_error_code(error_code);
[email protected]b90c93ff2010-08-20 22:42:50149 }
150
151 virtual void RunCallback() {
[email protected]30c1eea2011-10-17 18:40:30152 callback_.Run(error_code(), base::PassPlatformFile(&file_handle_),
153 created_);
[email protected]b90c93ff2010-08-20 22:42:50154 }
155
156 private:
157 scoped_refptr<base::MessageLoopProxy> message_loop_proxy_;
158 FilePath file_path_;
159 int file_flags_;
[email protected]30c1eea2011-10-17 18:40:30160 base::FileUtilProxy::CreateOrOpenCallback callback_;
[email protected]b90c93ff2010-08-20 22:42:50161 base::PlatformFile file_handle_;
162 bool created_;
163};
164
165class RelayCreateTemporary : public MessageLoopRelay {
166 public:
167 RelayCreateTemporary(
168 scoped_refptr<base::MessageLoopProxy> message_loop_proxy,
[email protected]86ecf512011-06-13 20:29:50169 int additional_file_flags,
[email protected]7bf4a8e2011-10-17 19:29:29170 const base::FileUtilProxy::CreateTemporaryCallback& callback)
[email protected]b90c93ff2010-08-20 22:42:50171 : message_loop_proxy_(message_loop_proxy),
[email protected]86ecf512011-06-13 20:29:50172 additional_file_flags_(additional_file_flags),
[email protected]b90c93ff2010-08-20 22:42:50173 callback_(callback),
174 file_handle_(base::kInvalidPlatformFileValue) {
[email protected]7bf4a8e2011-10-17 19:29:29175 DCHECK_EQ(false, callback.is_null());
[email protected]b90c93ff2010-08-20 22:42:50176 }
177
178 protected:
179 virtual ~RelayCreateTemporary() {
180 if (file_handle_ != base::kInvalidPlatformFileValue)
181 base::FileUtilProxy::Close(message_loop_proxy_, file_handle_, NULL);
182 }
183
184 virtual void RunWork() {
185 // TODO(darin): file_util should have a variant of CreateTemporaryFile
186 // that returns a FilePath and a PlatformFile.
187 file_util::CreateTemporaryFile(&file_path_);
188
[email protected]b90c93ff2010-08-20 22:42:50189 int file_flags =
[email protected]b90c93ff2010-08-20 22:42:50190 base::PLATFORM_FILE_WRITE |
[email protected]86ecf512011-06-13 20:29:50191 base::PLATFORM_FILE_TEMPORARY |
192 base::PLATFORM_FILE_CREATE_ALWAYS |
193 additional_file_flags_;
194
[email protected]ed65fec2010-08-31 19:30:27195 base::PlatformFileError error_code = base::PLATFORM_FILE_OK;
196 file_handle_ = base::CreatePlatformFile(file_path_, file_flags,
197 NULL, &error_code);
198 set_error_code(error_code);
[email protected]b90c93ff2010-08-20 22:42:50199 }
200
201 virtual void RunCallback() {
[email protected]7bf4a8e2011-10-17 19:29:29202 callback_.Run(error_code(), base::PassPlatformFile(&file_handle_),
203 file_path_);
[email protected]b90c93ff2010-08-20 22:42:50204 }
205
206 private:
207 scoped_refptr<base::MessageLoopProxy> message_loop_proxy_;
[email protected]86ecf512011-06-13 20:29:50208 int additional_file_flags_;
[email protected]7bf4a8e2011-10-17 19:29:29209 base::FileUtilProxy::CreateTemporaryCallback callback_;
[email protected]b90c93ff2010-08-20 22:42:50210 base::PlatformFile file_handle_;
211 FilePath file_path_;
212};
213
214class RelayWithStatusCallback : public MessageLoopRelay {
215 public:
216 explicit RelayWithStatusCallback(
217 base::FileUtilProxy::StatusCallback* callback)
[email protected]d480a3e2010-08-24 20:26:23218 : callback_(callback) {
[email protected]b90c93ff2010-08-20 22:42:50219 // It is OK for callback to be NULL.
220 }
221
222 protected:
223 virtual void RunCallback() {
224 // The caller may not have been interested in the result.
225 if (callback_) {
[email protected]d480a3e2010-08-24 20:26:23226 callback_->Run(error_code());
[email protected]b90c93ff2010-08-20 22:42:50227 delete callback_;
228 }
229 }
230
[email protected]b90c93ff2010-08-20 22:42:50231 private:
232 base::FileUtilProxy::StatusCallback* callback_;
[email protected]b90c93ff2010-08-20 22:42:50233};
234
235class RelayClose : public RelayWithStatusCallback {
236 public:
237 RelayClose(base::PlatformFile file_handle,
238 base::FileUtilProxy::StatusCallback* callback)
239 : RelayWithStatusCallback(callback),
240 file_handle_(file_handle) {
241 }
242
243 protected:
244 virtual void RunWork() {
[email protected]d480a3e2010-08-24 20:26:23245 if (!base::ClosePlatformFile(file_handle_))
[email protected]ed65fec2010-08-31 19:30:27246 set_error_code(base::PLATFORM_FILE_ERROR_FAILED);
[email protected]b90c93ff2010-08-20 22:42:50247 }
248
249 private:
250 base::PlatformFile file_handle_;
251};
252
[email protected]fd55c282010-10-15 00:37:34253class RelayEnsureFileExists : public MessageLoopRelay {
254 public:
255 RelayEnsureFileExists(
256 scoped_refptr<base::MessageLoopProxy> message_loop_proxy,
257 const FilePath& file_path,
[email protected]f1ef8d42011-10-17 19:39:59258 const base::FileUtilProxy::EnsureFileExistsCallback& callback)
[email protected]fd55c282010-10-15 00:37:34259 : message_loop_proxy_(message_loop_proxy),
260 file_path_(file_path),
261 callback_(callback),
262 created_(false) {
[email protected]f1ef8d42011-10-17 19:39:59263 DCHECK_EQ(false, callback.is_null());
[email protected]fd55c282010-10-15 00:37:34264 }
265
266 protected:
267 virtual void RunWork() {
268 if (!file_util::DirectoryExists(file_path_.DirName())) {
269 // If its parent does not exist, should return NOT_FOUND error.
270 set_error_code(base::PLATFORM_FILE_ERROR_NOT_FOUND);
271 return;
272 }
273 base::PlatformFileError error_code = base::PLATFORM_FILE_OK;
274 // Tries to create the |file_path_| exclusively. This should fail
275 // with PLATFORM_FILE_ERROR_EXISTS if the path already exists.
276 base::PlatformFile handle = base::CreatePlatformFile(
277 file_path_,
278 base::PLATFORM_FILE_CREATE | base::PLATFORM_FILE_READ,
279 &created_, &error_code);
280 if (error_code == base::PLATFORM_FILE_ERROR_EXISTS) {
281 // Make sure created_ is false.
282 created_ = false;
283 error_code = base::PLATFORM_FILE_OK;
284 }
285 if (handle != base::kInvalidPlatformFileValue)
286 base::ClosePlatformFile(handle);
287 set_error_code(error_code);
288 }
289
290 virtual void RunCallback() {
[email protected]f1ef8d42011-10-17 19:39:59291 callback_.Run(error_code(), created_);
[email protected]fd55c282010-10-15 00:37:34292 }
293
294 private:
295 scoped_refptr<base::MessageLoopProxy> message_loop_proxy_;
296 FilePath file_path_;
[email protected]f1ef8d42011-10-17 19:39:59297 base::FileUtilProxy::EnsureFileExistsCallback callback_;
[email protected]fd55c282010-10-15 00:37:34298 bool created_;
299};
300
[email protected]b90c93ff2010-08-20 22:42:50301class RelayDelete : public RelayWithStatusCallback {
302 public:
303 RelayDelete(const FilePath& file_path,
304 bool recursive,
305 base::FileUtilProxy::StatusCallback* callback)
306 : RelayWithStatusCallback(callback),
307 file_path_(file_path),
308 recursive_(recursive) {
309 }
310
311 protected:
312 virtual void RunWork() {
[email protected]61da1db2010-09-02 03:43:36313 if (!file_util::PathExists(file_path_)) {
314 set_error_code(base::PLATFORM_FILE_ERROR_NOT_FOUND);
315 return;
316 }
317 if (!file_util::Delete(file_path_, recursive_)) {
318 if (!recursive_ && !file_util::IsDirectoryEmpty(file_path_)) {
[email protected]81b18ca2010-10-07 08:35:09319 set_error_code(base::PLATFORM_FILE_ERROR_NOT_EMPTY);
[email protected]61da1db2010-09-02 03:43:36320 return;
321 }
[email protected]ed65fec2010-08-31 19:30:27322 set_error_code(base::PLATFORM_FILE_ERROR_FAILED);
[email protected]61da1db2010-09-02 03:43:36323 }
[email protected]b90c93ff2010-08-20 22:42:50324 }
325
326 private:
327 FilePath file_path_;
328 bool recursive_;
329};
330
[email protected]61da1db2010-09-02 03:43:36331class RelayCopy : public RelayWithStatusCallback {
332 public:
333 RelayCopy(const FilePath& src_file_path,
334 const FilePath& dest_file_path,
335 base::FileUtilProxy::StatusCallback* callback)
336 : RelayWithStatusCallback(callback),
337 src_file_path_(src_file_path),
338 dest_file_path_(dest_file_path) {
339 }
340
341 protected:
342 virtual void RunWork() {
[email protected]81b18ca2010-10-07 08:35:09343 set_error_code(PerformCommonCheckAndPreparationForMoveAndCopy(
344 src_file_path_, dest_file_path_));
345 if (error_code() != base::PLATFORM_FILE_OK)
[email protected]61da1db2010-09-02 03:43:36346 return;
[email protected]c27a5ed2010-10-06 21:44:35347 if (!file_util::CopyDirectory(src_file_path_, dest_file_path_,
[email protected]81b18ca2010-10-07 08:35:09348 true /* recursive */))
[email protected]c27a5ed2010-10-06 21:44:35349 set_error_code(base::PLATFORM_FILE_ERROR_FAILED);
[email protected]61da1db2010-09-02 03:43:36350 }
351
352 private:
353 FilePath src_file_path_;
354 FilePath dest_file_path_;
355};
356
357class RelayMove : public RelayWithStatusCallback {
358 public:
359 RelayMove(const FilePath& src_file_path,
360 const FilePath& dest_file_path,
361 base::FileUtilProxy::StatusCallback* callback)
362 : RelayWithStatusCallback(callback),
363 src_file_path_(src_file_path),
364 dest_file_path_(dest_file_path) {
365 }
366
367 protected:
368 virtual void RunWork() {
[email protected]81b18ca2010-10-07 08:35:09369 set_error_code(PerformCommonCheckAndPreparationForMoveAndCopy(
370 src_file_path_, dest_file_path_));
371 if (error_code() != base::PLATFORM_FILE_OK)
[email protected]61da1db2010-09-02 03:43:36372 return;
[email protected]81b18ca2010-10-07 08:35:09373 if (!file_util::Move(src_file_path_, dest_file_path_))
[email protected]61da1db2010-09-02 03:43:36374 set_error_code(base::PLATFORM_FILE_ERROR_FAILED);
[email protected]61da1db2010-09-02 03:43:36375 }
376
377 private:
378 FilePath src_file_path_;
379 FilePath dest_file_path_;
380};
381
382class RelayCreateDirectory : public RelayWithStatusCallback {
383 public:
384 RelayCreateDirectory(
385 const FilePath& file_path,
386 bool exclusive,
[email protected]8b201912010-09-08 00:50:41387 bool recursive,
[email protected]61da1db2010-09-02 03:43:36388 base::FileUtilProxy::StatusCallback* callback)
389 : RelayWithStatusCallback(callback),
390 file_path_(file_path),
[email protected]8b201912010-09-08 00:50:41391 exclusive_(exclusive),
392 recursive_(recursive) {
[email protected]61da1db2010-09-02 03:43:36393 }
394
395 protected:
396 virtual void RunWork() {
397 bool path_exists = file_util::PathExists(file_path_);
398 // If parent dir of file doesn't exist.
[email protected]8b201912010-09-08 00:50:41399 if (!recursive_ && !file_util::PathExists(file_path_.DirName())) {
[email protected]61da1db2010-09-02 03:43:36400 set_error_code(base::PLATFORM_FILE_ERROR_NOT_FOUND);
401 return;
402 }
403 if (exclusive_ && path_exists) {
404 set_error_code(base::PLATFORM_FILE_ERROR_EXISTS);
405 return;
406 }
407 // If file exists at the path.
408 if (path_exists && !file_util::DirectoryExists(file_path_)) {
409 set_error_code(base::PLATFORM_FILE_ERROR_EXISTS);
410 return;
411 }
412 if (!file_util::CreateDirectory(file_path_))
413 set_error_code(base::PLATFORM_FILE_ERROR_FAILED);
414 }
415
416 private:
417 FilePath file_path_;
418 bool exclusive_;
[email protected]8b201912010-09-08 00:50:41419 bool recursive_;
[email protected]61da1db2010-09-02 03:43:36420};
421
422class RelayReadDirectory : public MessageLoopRelay {
423 public:
[email protected]a6e689d52011-10-17 20:34:19424 RelayReadDirectory(
425 const FilePath& file_path,
426 const base::FileUtilProxy::ReadDirectoryCallback& callback)
427 : callback_(callback),
428 file_path_(file_path) {
429 DCHECK_EQ(false, callback.is_null());
[email protected]61da1db2010-09-02 03:43:36430 }
431
432 protected:
433 virtual void RunWork() {
434 // TODO(kkanetkar): Implement directory read in multiple chunks.
435 if (!file_util::DirectoryExists(file_path_)) {
436 set_error_code(base::PLATFORM_FILE_ERROR_NOT_FOUND);
437 return;
438 }
439
440 file_util::FileEnumerator file_enum(
[email protected]58b7c5a62011-08-15 13:09:27441 file_path_, false, static_cast<file_util::FileEnumerator::FileType>(
[email protected]61da1db2010-09-02 03:43:36442 file_util::FileEnumerator::FILES |
443 file_util::FileEnumerator::DIRECTORIES));
444 FilePath current;
445 while (!(current = file_enum.Next()).empty()) {
[email protected]841daf1d2010-11-02 20:36:52446 base::FileUtilProxy::Entry entry;
[email protected]61da1db2010-09-02 03:43:36447 file_util::FileEnumerator::FindInfo info;
448 file_enum.GetFindInfo(&info);
[email protected]d8591ca52010-09-02 22:28:49449 entry.is_directory = file_enum.IsDirectory(info);
[email protected]61da1db2010-09-02 03:43:36450 // This will just give the entry's name instead of entire path
451 // if we use current.value().
452 entry.name = file_util::FileEnumerator::GetFilename(info).value();
[email protected]f1ddaa42011-07-19 05:03:03453 entry.size = file_util::FileEnumerator::GetFilesize(info);
454 entry.last_modified_time =
455 file_util::FileEnumerator::GetLastModifiedTime(info);
[email protected]61da1db2010-09-02 03:43:36456 entries_.push_back(entry);
457 }
458 }
459
460 virtual void RunCallback() {
[email protected]a6e689d52011-10-17 20:34:19461 callback_.Run(error_code(), entries_);
[email protected]61da1db2010-09-02 03:43:36462 }
463
464 private:
[email protected]a6e689d52011-10-17 20:34:19465 base::FileUtilProxy::ReadDirectoryCallback callback_;
[email protected]61da1db2010-09-02 03:43:36466 FilePath file_path_;
[email protected]841daf1d2010-11-02 20:36:52467 std::vector<base::FileUtilProxy::Entry> entries_;
[email protected]61da1db2010-09-02 03:43:36468};
469
[email protected]81070042010-08-31 02:42:36470class RelayGetFileInfo : public MessageLoopRelay {
471 public:
472 RelayGetFileInfo(const FilePath& file_path,
[email protected]0f695a72011-10-17 20:12:05473 const base::FileUtilProxy::GetFileInfoCallback& callback)
[email protected]81070042010-08-31 02:42:36474 : callback_(callback),
[email protected]ed65fec2010-08-31 19:30:27475 file_path_(file_path) {
[email protected]0f695a72011-10-17 20:12:05476 DCHECK_EQ(false, callback.is_null());
[email protected]81070042010-08-31 02:42:36477 }
478
479 protected:
480 virtual void RunWork() {
[email protected]61da1db2010-09-02 03:43:36481 if (!file_util::PathExists(file_path_)) {
482 set_error_code(base::PLATFORM_FILE_ERROR_NOT_FOUND);
483 return;
484 }
[email protected]ed65fec2010-08-31 19:30:27485 if (!file_util::GetFileInfo(file_path_, &file_info_))
486 set_error_code(base::PLATFORM_FILE_ERROR_FAILED);
[email protected]81070042010-08-31 02:42:36487 }
488
489 virtual void RunCallback() {
[email protected]0f695a72011-10-17 20:12:05490 callback_.Run(error_code(), file_info_);
[email protected]81070042010-08-31 02:42:36491 }
492
493 private:
[email protected]0f695a72011-10-17 20:12:05494 base::FileUtilProxy::GetFileInfoCallback callback_;
[email protected]81070042010-08-31 02:42:36495 FilePath file_path_;
[email protected]2f0193c22010-09-03 02:28:37496 base::PlatformFileInfo file_info_;
[email protected]81070042010-08-31 02:42:36497};
498
[email protected]3fb43ed12010-09-10 03:01:14499class RelayGetFileInfoFromPlatformFile : public MessageLoopRelay {
500 public:
501 RelayGetFileInfoFromPlatformFile(
502 base::PlatformFile file,
[email protected]0f695a72011-10-17 20:12:05503 const base::FileUtilProxy::GetFileInfoCallback& callback)
[email protected]3fb43ed12010-09-10 03:01:14504 : callback_(callback),
505 file_(file) {
[email protected]0f695a72011-10-17 20:12:05506 DCHECK_EQ(false, callback.is_null());
[email protected]3fb43ed12010-09-10 03:01:14507 }
508
509 protected:
510 virtual void RunWork() {
511 if (!base::GetPlatformFileInfo(file_, &file_info_))
512 set_error_code(base::PLATFORM_FILE_ERROR_FAILED);
513 }
514
515 virtual void RunCallback() {
[email protected]0f695a72011-10-17 20:12:05516 callback_.Run(error_code(), file_info_);
[email protected]3fb43ed12010-09-10 03:01:14517 }
518
519 private:
[email protected]0f695a72011-10-17 20:12:05520 base::FileUtilProxy::GetFileInfoCallback callback_;
[email protected]3fb43ed12010-09-10 03:01:14521 base::PlatformFile file_;
522 base::PlatformFileInfo file_info_;
523};
524
525class RelayRead : public MessageLoopRelay {
526 public:
527 RelayRead(base::PlatformFile file,
528 int64 offset,
[email protected]3fb43ed12010-09-10 03:01:14529 int bytes_to_read,
[email protected]d6c182212011-10-17 20:44:47530 const base::FileUtilProxy::ReadCallback& callback)
[email protected]3fb43ed12010-09-10 03:01:14531 : file_(file),
532 offset_(offset),
[email protected]55181772011-02-04 00:39:34533 buffer_(new char[bytes_to_read]),
[email protected]3fb43ed12010-09-10 03:01:14534 bytes_to_read_(bytes_to_read),
535 callback_(callback),
536 bytes_read_(0) {
537 }
538
539 protected:
540 virtual void RunWork() {
[email protected]55181772011-02-04 00:39:34541 bytes_read_ = base::ReadPlatformFile(file_, offset_, buffer_.get(),
[email protected]3fb43ed12010-09-10 03:01:14542 bytes_to_read_);
543 if (bytes_read_ < 0)
544 set_error_code(base::PLATFORM_FILE_ERROR_FAILED);
545 }
546
547 virtual void RunCallback() {
[email protected]d6c182212011-10-17 20:44:47548 if (!callback_.is_null())
549 callback_.Run(error_code(), buffer_.get(), bytes_read_);
[email protected]3fb43ed12010-09-10 03:01:14550 }
551
552 private:
553 base::PlatformFile file_;
554 int64 offset_;
[email protected]55181772011-02-04 00:39:34555 scoped_array<char> buffer_;
[email protected]3fb43ed12010-09-10 03:01:14556 int bytes_to_read_;
[email protected]d6c182212011-10-17 20:44:47557 base::FileUtilProxy::ReadCallback callback_;
[email protected]3fb43ed12010-09-10 03:01:14558 int bytes_read_;
559};
560
561class RelayWrite : public MessageLoopRelay {
562 public:
563 RelayWrite(base::PlatformFile file,
[email protected]7eb68a22010-10-05 02:26:47564 int64 offset,
[email protected]3fb43ed12010-09-10 03:01:14565 const char* buffer,
566 int bytes_to_write,
[email protected]55181772011-02-04 00:39:34567 base::FileUtilProxy::WriteCallback* callback)
[email protected]3fb43ed12010-09-10 03:01:14568 : file_(file),
569 offset_(offset),
[email protected]55181772011-02-04 00:39:34570 buffer_(new char[bytes_to_write]),
[email protected]3fb43ed12010-09-10 03:01:14571 bytes_to_write_(bytes_to_write),
[email protected]32aa75b2011-03-15 09:56:27572 callback_(callback),
573 bytes_written_(0) {
[email protected]55181772011-02-04 00:39:34574 memcpy(buffer_.get(), buffer, bytes_to_write);
[email protected]3fb43ed12010-09-10 03:01:14575 }
576
577 protected:
578 virtual void RunWork() {
[email protected]55181772011-02-04 00:39:34579 bytes_written_ = base::WritePlatformFile(file_, offset_, buffer_.get(),
[email protected]3fb43ed12010-09-10 03:01:14580 bytes_to_write_);
581 if (bytes_written_ < 0)
582 set_error_code(base::PLATFORM_FILE_ERROR_FAILED);
583 }
584
585 virtual void RunCallback() {
586 if (callback_) {
587 callback_->Run(error_code(), bytes_written_);
588 delete callback_;
589 }
590 }
591
592 private:
593 base::PlatformFile file_;
594 int64 offset_;
[email protected]55181772011-02-04 00:39:34595 scoped_array<char> buffer_;
[email protected]3fb43ed12010-09-10 03:01:14596 int bytes_to_write_;
[email protected]55181772011-02-04 00:39:34597 base::FileUtilProxy::WriteCallback* callback_;
[email protected]3fb43ed12010-09-10 03:01:14598 int bytes_written_;
599};
600
601class RelayTouch : public RelayWithStatusCallback {
602 public:
603 RelayTouch(base::PlatformFile file,
604 const base::Time& last_access_time,
605 const base::Time& last_modified_time,
606 base::FileUtilProxy::StatusCallback* callback)
607 : RelayWithStatusCallback(callback),
608 file_(file),
609 last_access_time_(last_access_time),
610 last_modified_time_(last_modified_time) {
611 }
612
613 protected:
614 virtual void RunWork() {
615 if (!base::TouchPlatformFile(file_, last_access_time_, last_modified_time_))
616 set_error_code(base::PLATFORM_FILE_ERROR_FAILED);
617 }
618
619 private:
620 base::PlatformFile file_;
621 base::Time last_access_time_;
622 base::Time last_modified_time_;
623};
624
[email protected]9fae63af2010-09-24 01:09:32625class RelayTouchFilePath : public RelayWithStatusCallback {
626 public:
627 RelayTouchFilePath(const FilePath& file_path,
628 const base::Time& last_access_time,
629 const base::Time& last_modified_time,
630 base::FileUtilProxy::StatusCallback* callback)
631 : RelayWithStatusCallback(callback),
[email protected]2250e272010-09-24 20:07:41632 file_path_(file_path),
[email protected]9fae63af2010-09-24 01:09:32633 last_access_time_(last_access_time),
634 last_modified_time_(last_modified_time) {
635 }
636
637 protected:
638 virtual void RunWork() {
639 if (!file_util::TouchFile(
640 file_path_, last_access_time_, last_modified_time_))
641 set_error_code(base::PLATFORM_FILE_ERROR_FAILED);
642 }
643
644 private:
645 FilePath file_path_;
646 base::Time last_access_time_;
647 base::Time last_modified_time_;
648};
649
[email protected]7eb68a22010-10-05 02:26:47650class RelayTruncatePlatformFile : public RelayWithStatusCallback {
[email protected]3fb43ed12010-09-10 03:01:14651 public:
[email protected]7eb68a22010-10-05 02:26:47652 RelayTruncatePlatformFile(base::PlatformFile file,
653 int64 length,
654 base::FileUtilProxy::StatusCallback* callback)
[email protected]3fb43ed12010-09-10 03:01:14655 : RelayWithStatusCallback(callback),
656 file_(file),
657 length_(length) {
658 }
659
660 protected:
661 virtual void RunWork() {
662 if (!base::TruncatePlatformFile(file_, length_))
663 set_error_code(base::PLATFORM_FILE_ERROR_FAILED);
664 }
665
666 private:
667 base::PlatformFile file_;
668 int64 length_;
669};
670
[email protected]7eb68a22010-10-05 02:26:47671class RelayTruncate : public RelayWithStatusCallback {
672 public:
673 RelayTruncate(const FilePath& path,
674 int64 length,
675 base::FileUtilProxy::StatusCallback* callback)
676 : RelayWithStatusCallback(callback),
677 path_(path),
678 length_(length) {
679 }
680
681 protected:
682 virtual void RunWork() {
683 base::PlatformFileError error_code(base::PLATFORM_FILE_ERROR_FAILED);
684 base::PlatformFile file =
685 base::CreatePlatformFile(
686 path_,
687 base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_WRITE,
688 NULL,
689 &error_code);
690 if (error_code != base::PLATFORM_FILE_OK) {
691 set_error_code(error_code);
692 return;
693 }
694 if (!base::TruncatePlatformFile(file, length_))
695 set_error_code(base::PLATFORM_FILE_ERROR_FAILED);
696 base::ClosePlatformFile(file);
697 }
698
699 private:
700 FilePath path_;
701 int64 length_;
702};
703
[email protected]3fb43ed12010-09-10 03:01:14704class RelayFlush : public RelayWithStatusCallback {
705 public:
706 RelayFlush(base::PlatformFile file,
707 base::FileUtilProxy::StatusCallback* callback)
708 : RelayWithStatusCallback(callback),
709 file_(file) {
710 }
711
712 protected:
713 virtual void RunWork() {
714 if (!base::FlushPlatformFile(file_))
715 set_error_code(base::PLATFORM_FILE_ERROR_FAILED);
716 }
717
718 private:
719 base::PlatformFile file_;
720};
721
[email protected]d480a3e2010-08-24 20:26:23722bool Start(const tracked_objects::Location& from_here,
[email protected]b90c93ff2010-08-20 22:42:50723 scoped_refptr<base::MessageLoopProxy> message_loop_proxy,
724 scoped_refptr<MessageLoopRelay> relay) {
[email protected]d480a3e2010-08-24 20:26:23725 return relay->Start(message_loop_proxy, from_here);
[email protected]b90c93ff2010-08-20 22:42:50726}
727
728} // namespace
729
730namespace base {
731
732// static
[email protected]d480a3e2010-08-24 20:26:23733bool FileUtilProxy::CreateOrOpen(
[email protected]b90c93ff2010-08-20 22:42:50734 scoped_refptr<MessageLoopProxy> message_loop_proxy,
735 const FilePath& file_path, int file_flags,
[email protected]30c1eea2011-10-17 18:40:30736 const CreateOrOpenCallback& callback) {
[email protected]d480a3e2010-08-24 20:26:23737 return Start(FROM_HERE, message_loop_proxy, new RelayCreateOrOpen(
[email protected]fd55c282010-10-15 00:37:34738 message_loop_proxy, file_path, file_flags, callback));
[email protected]b90c93ff2010-08-20 22:42:50739}
740
741// static
[email protected]d480a3e2010-08-24 20:26:23742bool FileUtilProxy::CreateTemporary(
[email protected]b90c93ff2010-08-20 22:42:50743 scoped_refptr<MessageLoopProxy> message_loop_proxy,
[email protected]86ecf512011-06-13 20:29:50744 int additional_file_flags,
[email protected]7bf4a8e2011-10-17 19:29:29745 const CreateTemporaryCallback& callback) {
[email protected]d480a3e2010-08-24 20:26:23746 return Start(FROM_HERE, message_loop_proxy,
[email protected]86ecf512011-06-13 20:29:50747 new RelayCreateTemporary(message_loop_proxy,
748 additional_file_flags,
749 callback));
[email protected]b90c93ff2010-08-20 22:42:50750}
751
752// static
[email protected]d480a3e2010-08-24 20:26:23753bool FileUtilProxy::Close(scoped_refptr<MessageLoopProxy> message_loop_proxy,
[email protected]b90c93ff2010-08-20 22:42:50754 base::PlatformFile file_handle,
755 StatusCallback* callback) {
[email protected]d480a3e2010-08-24 20:26:23756 return Start(FROM_HERE, message_loop_proxy,
757 new RelayClose(file_handle, callback));
[email protected]b90c93ff2010-08-20 22:42:50758}
759
760// static
[email protected]fd55c282010-10-15 00:37:34761bool FileUtilProxy::EnsureFileExists(
762 scoped_refptr<MessageLoopProxy> message_loop_proxy,
763 const FilePath& file_path,
[email protected]f1ef8d42011-10-17 19:39:59764 const EnsureFileExistsCallback& callback) {
[email protected]fd55c282010-10-15 00:37:34765 return Start(FROM_HERE, message_loop_proxy, new RelayEnsureFileExists(
766 message_loop_proxy, file_path, callback));
767}
768
[email protected]eae9c062011-01-11 00:50:59769// Retrieves the information about a file. It is invalid to pass NULL for the
770// callback.
771bool FileUtilProxy::GetFileInfo(
772 scoped_refptr<MessageLoopProxy> message_loop_proxy,
773 const FilePath& file_path,
[email protected]0f695a72011-10-17 20:12:05774 const GetFileInfoCallback& callback) {
[email protected]eae9c062011-01-11 00:50:59775 return Start(FROM_HERE, message_loop_proxy, new RelayGetFileInfo(
776 file_path, callback));
777}
778
[email protected]fd55c282010-10-15 00:37:34779// static
[email protected]eae9c062011-01-11 00:50:59780bool FileUtilProxy::GetFileInfoFromPlatformFile(
781 scoped_refptr<MessageLoopProxy> message_loop_proxy,
782 PlatformFile file,
[email protected]0f695a72011-10-17 20:12:05783 const GetFileInfoCallback& callback) {
[email protected]d480a3e2010-08-24 20:26:23784 return Start(FROM_HERE, message_loop_proxy,
[email protected]eae9c062011-01-11 00:50:59785 new RelayGetFileInfoFromPlatformFile(file, callback));
786}
787
788// static
789bool FileUtilProxy::ReadDirectory(
790 scoped_refptr<MessageLoopProxy> message_loop_proxy,
791 const FilePath& file_path,
[email protected]a6e689d52011-10-17 20:34:19792 const ReadDirectoryCallback& callback) {
[email protected]eae9c062011-01-11 00:50:59793 return Start(FROM_HERE, message_loop_proxy, new RelayReadDirectory(
794 file_path, callback));
795}
796
797// static
798bool FileUtilProxy::CreateDirectory(
799 scoped_refptr<MessageLoopProxy> message_loop_proxy,
800 const FilePath& file_path,
801 bool exclusive,
802 bool recursive,
803 StatusCallback* callback) {
804 return Start(FROM_HERE, message_loop_proxy, new RelayCreateDirectory(
805 file_path, exclusive, recursive, callback));
[email protected]b90c93ff2010-08-20 22:42:50806}
807
808// static
[email protected]61da1db2010-09-02 03:43:36809bool FileUtilProxy::Copy(scoped_refptr<MessageLoopProxy> message_loop_proxy,
810 const FilePath& src_file_path,
811 const FilePath& dest_file_path,
812 StatusCallback* callback) {
813 return Start(FROM_HERE, message_loop_proxy,
814 new RelayCopy(src_file_path, dest_file_path, callback));
815}
816
817// static
818bool FileUtilProxy::Move(scoped_refptr<MessageLoopProxy> message_loop_proxy,
819 const FilePath& src_file_path,
820 const FilePath& dest_file_path,
821 StatusCallback* callback) {
822 return Start(FROM_HERE, message_loop_proxy,
823 new RelayMove(src_file_path, dest_file_path, callback));
824}
825
826// static
[email protected]eae9c062011-01-11 00:50:59827bool FileUtilProxy::Delete(scoped_refptr<MessageLoopProxy> message_loop_proxy,
828 const FilePath& file_path,
829 bool recursive,
830 StatusCallback* callback) {
831 return Start(FROM_HERE, message_loop_proxy,
832 new RelayDelete(file_path, recursive, callback));
[email protected]61da1db2010-09-02 03:43:36833}
834
835// static
[email protected]d480a3e2010-08-24 20:26:23836bool FileUtilProxy::RecursiveDelete(
[email protected]b90c93ff2010-08-20 22:42:50837 scoped_refptr<MessageLoopProxy> message_loop_proxy,
838 const FilePath& file_path,
839 StatusCallback* callback) {
[email protected]d480a3e2010-08-24 20:26:23840 return Start(FROM_HERE, message_loop_proxy,
841 new RelayDelete(file_path, true, callback));
[email protected]b90c93ff2010-08-20 22:42:50842}
843
[email protected]3fb43ed12010-09-10 03:01:14844// static
[email protected]3fb43ed12010-09-10 03:01:14845bool FileUtilProxy::Read(
846 scoped_refptr<MessageLoopProxy> message_loop_proxy,
847 PlatformFile file,
848 int64 offset,
[email protected]3fb43ed12010-09-10 03:01:14849 int bytes_to_read,
[email protected]d6c182212011-10-17 20:44:47850 const ReadCallback& callback) {
851 if (bytes_to_read < 0)
[email protected]3d6293a2011-08-17 16:16:27852 return false;
[email protected]d6c182212011-10-17 20:44:47853
[email protected]3fb43ed12010-09-10 03:01:14854 return Start(FROM_HERE, message_loop_proxy,
[email protected]55181772011-02-04 00:39:34855 new RelayRead(file, offset, bytes_to_read, callback));
[email protected]3fb43ed12010-09-10 03:01:14856}
857
858// static
859bool FileUtilProxy::Write(
860 scoped_refptr<MessageLoopProxy> message_loop_proxy,
861 PlatformFile file,
862 int64 offset,
863 const char* buffer,
864 int bytes_to_write,
[email protected]55181772011-02-04 00:39:34865 WriteCallback* callback) {
[email protected]4c19b0422011-08-19 10:14:27866 if (bytes_to_write <= 0) {
867 delete callback;
[email protected]a88016d12011-08-17 16:45:48868 return false;
[email protected]4c19b0422011-08-19 10:14:27869 }
[email protected]3fb43ed12010-09-10 03:01:14870 return Start(FROM_HERE, message_loop_proxy,
871 new RelayWrite(file, offset, buffer, bytes_to_write, callback));
872}
873
874// static
875bool FileUtilProxy::Touch(
876 scoped_refptr<MessageLoopProxy> message_loop_proxy,
877 PlatformFile file,
878 const base::Time& last_access_time,
879 const base::Time& last_modified_time,
880 StatusCallback* callback) {
881 return Start(FROM_HERE, message_loop_proxy,
882 new RelayTouch(file, last_access_time, last_modified_time,
883 callback));
884}
885
886// static
[email protected]9fae63af2010-09-24 01:09:32887bool FileUtilProxy::Touch(
888 scoped_refptr<MessageLoopProxy> message_loop_proxy,
889 const FilePath& file_path,
890 const base::Time& last_access_time,
891 const base::Time& last_modified_time,
892 StatusCallback* callback) {
893 return Start(FROM_HERE, message_loop_proxy,
894 new RelayTouchFilePath(file_path, last_access_time,
895 last_modified_time, callback));
896}
897
898// static
[email protected]3fb43ed12010-09-10 03:01:14899bool FileUtilProxy::Truncate(
900 scoped_refptr<MessageLoopProxy> message_loop_proxy,
901 PlatformFile file,
[email protected]7eb68a22010-10-05 02:26:47902 int64 length,
[email protected]3fb43ed12010-09-10 03:01:14903 StatusCallback* callback) {
904 return Start(FROM_HERE, message_loop_proxy,
[email protected]7eb68a22010-10-05 02:26:47905 new RelayTruncatePlatformFile(file, length, callback));
906}
907
908// static
909bool FileUtilProxy::Truncate(
910 scoped_refptr<MessageLoopProxy> message_loop_proxy,
911 const FilePath& path,
912 int64 length,
913 StatusCallback* callback) {
914 return Start(FROM_HERE, message_loop_proxy,
915 new RelayTruncate(path, length, callback));
[email protected]3fb43ed12010-09-10 03:01:14916}
917
918// static
919bool FileUtilProxy::Flush(
920 scoped_refptr<MessageLoopProxy> message_loop_proxy,
921 PlatformFile file,
922 StatusCallback* callback) {
923 return Start(FROM_HERE, message_loop_proxy, new RelayFlush(file, callback));
924}
925
[email protected]61da1db2010-09-02 03:43:36926} // namespace base