blob: f0192d934465a24b28803a665cc5d3799d401b04 [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]4958f9f2011-10-17 20:56:52567 const 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() {
[email protected]4958f9f2011-10-17 20:56:52586 if (!callback_.is_null())
587 callback_.Run(error_code(), bytes_written_);
[email protected]3fb43ed12010-09-10 03:01:14588 }
589
590 private:
591 base::PlatformFile file_;
592 int64 offset_;
[email protected]55181772011-02-04 00:39:34593 scoped_array<char> buffer_;
[email protected]3fb43ed12010-09-10 03:01:14594 int bytes_to_write_;
[email protected]4958f9f2011-10-17 20:56:52595 base::FileUtilProxy::WriteCallback callback_;
[email protected]3fb43ed12010-09-10 03:01:14596 int bytes_written_;
597};
598
599class RelayTouch : public RelayWithStatusCallback {
600 public:
601 RelayTouch(base::PlatformFile file,
602 const base::Time& last_access_time,
603 const base::Time& last_modified_time,
604 base::FileUtilProxy::StatusCallback* callback)
605 : RelayWithStatusCallback(callback),
606 file_(file),
607 last_access_time_(last_access_time),
608 last_modified_time_(last_modified_time) {
609 }
610
611 protected:
612 virtual void RunWork() {
613 if (!base::TouchPlatformFile(file_, last_access_time_, last_modified_time_))
614 set_error_code(base::PLATFORM_FILE_ERROR_FAILED);
615 }
616
617 private:
618 base::PlatformFile file_;
619 base::Time last_access_time_;
620 base::Time last_modified_time_;
621};
622
[email protected]9fae63af2010-09-24 01:09:32623class RelayTouchFilePath : public RelayWithStatusCallback {
624 public:
625 RelayTouchFilePath(const FilePath& file_path,
626 const base::Time& last_access_time,
627 const base::Time& last_modified_time,
628 base::FileUtilProxy::StatusCallback* callback)
629 : RelayWithStatusCallback(callback),
[email protected]2250e272010-09-24 20:07:41630 file_path_(file_path),
[email protected]9fae63af2010-09-24 01:09:32631 last_access_time_(last_access_time),
632 last_modified_time_(last_modified_time) {
633 }
634
635 protected:
636 virtual void RunWork() {
637 if (!file_util::TouchFile(
638 file_path_, last_access_time_, last_modified_time_))
639 set_error_code(base::PLATFORM_FILE_ERROR_FAILED);
640 }
641
642 private:
643 FilePath file_path_;
644 base::Time last_access_time_;
645 base::Time last_modified_time_;
646};
647
[email protected]7eb68a22010-10-05 02:26:47648class RelayTruncatePlatformFile : public RelayWithStatusCallback {
[email protected]3fb43ed12010-09-10 03:01:14649 public:
[email protected]7eb68a22010-10-05 02:26:47650 RelayTruncatePlatformFile(base::PlatformFile file,
651 int64 length,
652 base::FileUtilProxy::StatusCallback* callback)
[email protected]3fb43ed12010-09-10 03:01:14653 : RelayWithStatusCallback(callback),
654 file_(file),
655 length_(length) {
656 }
657
658 protected:
659 virtual void RunWork() {
660 if (!base::TruncatePlatformFile(file_, length_))
661 set_error_code(base::PLATFORM_FILE_ERROR_FAILED);
662 }
663
664 private:
665 base::PlatformFile file_;
666 int64 length_;
667};
668
[email protected]7eb68a22010-10-05 02:26:47669class RelayTruncate : public RelayWithStatusCallback {
670 public:
671 RelayTruncate(const FilePath& path,
672 int64 length,
673 base::FileUtilProxy::StatusCallback* callback)
674 : RelayWithStatusCallback(callback),
675 path_(path),
676 length_(length) {
677 }
678
679 protected:
680 virtual void RunWork() {
681 base::PlatformFileError error_code(base::PLATFORM_FILE_ERROR_FAILED);
682 base::PlatformFile file =
683 base::CreatePlatformFile(
684 path_,
685 base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_WRITE,
686 NULL,
687 &error_code);
688 if (error_code != base::PLATFORM_FILE_OK) {
689 set_error_code(error_code);
690 return;
691 }
692 if (!base::TruncatePlatformFile(file, length_))
693 set_error_code(base::PLATFORM_FILE_ERROR_FAILED);
694 base::ClosePlatformFile(file);
695 }
696
697 private:
698 FilePath path_;
699 int64 length_;
700};
701
[email protected]3fb43ed12010-09-10 03:01:14702class RelayFlush : public RelayWithStatusCallback {
703 public:
704 RelayFlush(base::PlatformFile file,
705 base::FileUtilProxy::StatusCallback* callback)
706 : RelayWithStatusCallback(callback),
707 file_(file) {
708 }
709
710 protected:
711 virtual void RunWork() {
712 if (!base::FlushPlatformFile(file_))
713 set_error_code(base::PLATFORM_FILE_ERROR_FAILED);
714 }
715
716 private:
717 base::PlatformFile file_;
718};
719
[email protected]d480a3e2010-08-24 20:26:23720bool Start(const tracked_objects::Location& from_here,
[email protected]b90c93ff2010-08-20 22:42:50721 scoped_refptr<base::MessageLoopProxy> message_loop_proxy,
722 scoped_refptr<MessageLoopRelay> relay) {
[email protected]d480a3e2010-08-24 20:26:23723 return relay->Start(message_loop_proxy, from_here);
[email protected]b90c93ff2010-08-20 22:42:50724}
725
726} // namespace
727
728namespace base {
729
730// static
[email protected]d480a3e2010-08-24 20:26:23731bool FileUtilProxy::CreateOrOpen(
[email protected]b90c93ff2010-08-20 22:42:50732 scoped_refptr<MessageLoopProxy> message_loop_proxy,
733 const FilePath& file_path, int file_flags,
[email protected]30c1eea2011-10-17 18:40:30734 const CreateOrOpenCallback& callback) {
[email protected]d480a3e2010-08-24 20:26:23735 return Start(FROM_HERE, message_loop_proxy, new RelayCreateOrOpen(
[email protected]fd55c282010-10-15 00:37:34736 message_loop_proxy, file_path, file_flags, callback));
[email protected]b90c93ff2010-08-20 22:42:50737}
738
739// static
[email protected]d480a3e2010-08-24 20:26:23740bool FileUtilProxy::CreateTemporary(
[email protected]b90c93ff2010-08-20 22:42:50741 scoped_refptr<MessageLoopProxy> message_loop_proxy,
[email protected]86ecf512011-06-13 20:29:50742 int additional_file_flags,
[email protected]7bf4a8e2011-10-17 19:29:29743 const CreateTemporaryCallback& callback) {
[email protected]d480a3e2010-08-24 20:26:23744 return Start(FROM_HERE, message_loop_proxy,
[email protected]86ecf512011-06-13 20:29:50745 new RelayCreateTemporary(message_loop_proxy,
746 additional_file_flags,
747 callback));
[email protected]b90c93ff2010-08-20 22:42:50748}
749
750// static
[email protected]d480a3e2010-08-24 20:26:23751bool FileUtilProxy::Close(scoped_refptr<MessageLoopProxy> message_loop_proxy,
[email protected]b90c93ff2010-08-20 22:42:50752 base::PlatformFile file_handle,
753 StatusCallback* callback) {
[email protected]d480a3e2010-08-24 20:26:23754 return Start(FROM_HERE, message_loop_proxy,
755 new RelayClose(file_handle, callback));
[email protected]b90c93ff2010-08-20 22:42:50756}
757
758// static
[email protected]fd55c282010-10-15 00:37:34759bool FileUtilProxy::EnsureFileExists(
760 scoped_refptr<MessageLoopProxy> message_loop_proxy,
761 const FilePath& file_path,
[email protected]f1ef8d42011-10-17 19:39:59762 const EnsureFileExistsCallback& callback) {
[email protected]fd55c282010-10-15 00:37:34763 return Start(FROM_HERE, message_loop_proxy, new RelayEnsureFileExists(
764 message_loop_proxy, file_path, callback));
765}
766
[email protected]eae9c062011-01-11 00:50:59767// Retrieves the information about a file. It is invalid to pass NULL for the
768// callback.
769bool FileUtilProxy::GetFileInfo(
770 scoped_refptr<MessageLoopProxy> message_loop_proxy,
771 const FilePath& file_path,
[email protected]0f695a72011-10-17 20:12:05772 const GetFileInfoCallback& callback) {
[email protected]eae9c062011-01-11 00:50:59773 return Start(FROM_HERE, message_loop_proxy, new RelayGetFileInfo(
774 file_path, callback));
775}
776
[email protected]fd55c282010-10-15 00:37:34777// static
[email protected]eae9c062011-01-11 00:50:59778bool FileUtilProxy::GetFileInfoFromPlatformFile(
779 scoped_refptr<MessageLoopProxy> message_loop_proxy,
780 PlatformFile file,
[email protected]0f695a72011-10-17 20:12:05781 const GetFileInfoCallback& callback) {
[email protected]d480a3e2010-08-24 20:26:23782 return Start(FROM_HERE, message_loop_proxy,
[email protected]eae9c062011-01-11 00:50:59783 new RelayGetFileInfoFromPlatformFile(file, callback));
784}
785
786// static
787bool FileUtilProxy::ReadDirectory(
788 scoped_refptr<MessageLoopProxy> message_loop_proxy,
789 const FilePath& file_path,
[email protected]a6e689d52011-10-17 20:34:19790 const ReadDirectoryCallback& callback) {
[email protected]eae9c062011-01-11 00:50:59791 return Start(FROM_HERE, message_loop_proxy, new RelayReadDirectory(
792 file_path, callback));
793}
794
795// static
796bool FileUtilProxy::CreateDirectory(
797 scoped_refptr<MessageLoopProxy> message_loop_proxy,
798 const FilePath& file_path,
799 bool exclusive,
800 bool recursive,
801 StatusCallback* callback) {
802 return Start(FROM_HERE, message_loop_proxy, new RelayCreateDirectory(
803 file_path, exclusive, recursive, callback));
[email protected]b90c93ff2010-08-20 22:42:50804}
805
806// static
[email protected]61da1db2010-09-02 03:43:36807bool FileUtilProxy::Copy(scoped_refptr<MessageLoopProxy> message_loop_proxy,
808 const FilePath& src_file_path,
809 const FilePath& dest_file_path,
810 StatusCallback* callback) {
811 return Start(FROM_HERE, message_loop_proxy,
812 new RelayCopy(src_file_path, dest_file_path, callback));
813}
814
815// static
816bool FileUtilProxy::Move(scoped_refptr<MessageLoopProxy> message_loop_proxy,
817 const FilePath& src_file_path,
818 const FilePath& dest_file_path,
819 StatusCallback* callback) {
820 return Start(FROM_HERE, message_loop_proxy,
821 new RelayMove(src_file_path, dest_file_path, callback));
822}
823
824// static
[email protected]eae9c062011-01-11 00:50:59825bool FileUtilProxy::Delete(scoped_refptr<MessageLoopProxy> message_loop_proxy,
826 const FilePath& file_path,
827 bool recursive,
828 StatusCallback* callback) {
829 return Start(FROM_HERE, message_loop_proxy,
830 new RelayDelete(file_path, recursive, callback));
[email protected]61da1db2010-09-02 03:43:36831}
832
833// static
[email protected]d480a3e2010-08-24 20:26:23834bool FileUtilProxy::RecursiveDelete(
[email protected]b90c93ff2010-08-20 22:42:50835 scoped_refptr<MessageLoopProxy> message_loop_proxy,
836 const FilePath& file_path,
837 StatusCallback* callback) {
[email protected]d480a3e2010-08-24 20:26:23838 return Start(FROM_HERE, message_loop_proxy,
839 new RelayDelete(file_path, true, callback));
[email protected]b90c93ff2010-08-20 22:42:50840}
841
[email protected]3fb43ed12010-09-10 03:01:14842// static
[email protected]3fb43ed12010-09-10 03:01:14843bool FileUtilProxy::Read(
844 scoped_refptr<MessageLoopProxy> message_loop_proxy,
845 PlatformFile file,
846 int64 offset,
[email protected]3fb43ed12010-09-10 03:01:14847 int bytes_to_read,
[email protected]d6c182212011-10-17 20:44:47848 const ReadCallback& callback) {
849 if (bytes_to_read < 0)
[email protected]3d6293a2011-08-17 16:16:27850 return false;
[email protected]d6c182212011-10-17 20:44:47851
[email protected]3fb43ed12010-09-10 03:01:14852 return Start(FROM_HERE, message_loop_proxy,
[email protected]55181772011-02-04 00:39:34853 new RelayRead(file, offset, bytes_to_read, callback));
[email protected]3fb43ed12010-09-10 03:01:14854}
855
856// static
857bool FileUtilProxy::Write(
858 scoped_refptr<MessageLoopProxy> message_loop_proxy,
859 PlatformFile file,
860 int64 offset,
861 const char* buffer,
862 int bytes_to_write,
[email protected]4958f9f2011-10-17 20:56:52863 const WriteCallback& callback) {
864 if (bytes_to_write <= 0)
[email protected]a88016d12011-08-17 16:45:48865 return false;
[email protected]4958f9f2011-10-17 20:56:52866
[email protected]3fb43ed12010-09-10 03:01:14867 return Start(FROM_HERE, message_loop_proxy,
868 new RelayWrite(file, offset, buffer, bytes_to_write, callback));
869}
870
871// static
872bool FileUtilProxy::Touch(
873 scoped_refptr<MessageLoopProxy> message_loop_proxy,
874 PlatformFile file,
875 const base::Time& last_access_time,
876 const base::Time& last_modified_time,
877 StatusCallback* callback) {
878 return Start(FROM_HERE, message_loop_proxy,
879 new RelayTouch(file, last_access_time, last_modified_time,
880 callback));
881}
882
883// static
[email protected]9fae63af2010-09-24 01:09:32884bool FileUtilProxy::Touch(
885 scoped_refptr<MessageLoopProxy> message_loop_proxy,
886 const FilePath& file_path,
887 const base::Time& last_access_time,
888 const base::Time& last_modified_time,
889 StatusCallback* callback) {
890 return Start(FROM_HERE, message_loop_proxy,
891 new RelayTouchFilePath(file_path, last_access_time,
892 last_modified_time, callback));
893}
894
895// static
[email protected]3fb43ed12010-09-10 03:01:14896bool FileUtilProxy::Truncate(
897 scoped_refptr<MessageLoopProxy> message_loop_proxy,
898 PlatformFile file,
[email protected]7eb68a22010-10-05 02:26:47899 int64 length,
[email protected]3fb43ed12010-09-10 03:01:14900 StatusCallback* callback) {
901 return Start(FROM_HERE, message_loop_proxy,
[email protected]7eb68a22010-10-05 02:26:47902 new RelayTruncatePlatformFile(file, length, callback));
903}
904
905// static
906bool FileUtilProxy::Truncate(
907 scoped_refptr<MessageLoopProxy> message_loop_proxy,
908 const FilePath& path,
909 int64 length,
910 StatusCallback* callback) {
911 return Start(FROM_HERE, message_loop_proxy,
912 new RelayTruncate(path, length, callback));
[email protected]3fb43ed12010-09-10 03:01:14913}
914
915// static
916bool FileUtilProxy::Flush(
917 scoped_refptr<MessageLoopProxy> message_loop_proxy,
918 PlatformFile file,
919 StatusCallback* callback) {
920 return Start(FROM_HERE, message_loop_proxy, new RelayFlush(file, callback));
921}
922
[email protected]61da1db2010-09-02 03:43:36923} // namespace base