1a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
2a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// found in the LICENSE file.
4a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
5a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/files/file_proxy.h"
6a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
7a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/bind.h"
8a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/bind_helpers.h"
9a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/file_util.h"
10a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/files/file.h"
11a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/location.h"
12a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/message_loop/message_loop_proxy.h"
13a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/task_runner.h"
14a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/task_runner_util.h"
15a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
16010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)namespace {
17010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
18010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void FileDeleter(base::File file) {
19010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
20010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
21010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}  // namespace
22010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
23a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)namespace base {
24a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
25a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)class FileHelper {
26a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) public:
27a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)   FileHelper(FileProxy* proxy, File file)
28a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      : file_(file.Pass()),
29010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        error_(File::FILE_ERROR_FAILED),
30010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        task_runner_(proxy->task_runner()),
31010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        proxy_(AsWeakPtr(proxy)) {
32a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)   }
33a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
34a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)   void PassFile() {
35a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)     if (proxy_)
36a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)       proxy_->SetFile(file_.Pass());
37010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)     else if (file_.IsValid())
38010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)       task_runner_->PostTask(FROM_HERE, Bind(&FileDeleter, Passed(&file_)));
39a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)   }
40a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
41a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) protected:
42a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  File file_;
43a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  File::Error error_;
44a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
45a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) private:
46010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  scoped_refptr<TaskRunner> task_runner_;
47010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  WeakPtr<FileProxy> proxy_;
48a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(FileHelper);
49a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)};
50a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
51a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)namespace {
52a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
53a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)class GenericFileHelper : public FileHelper {
54a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) public:
55a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  GenericFileHelper(FileProxy* proxy, File file)
56a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      : FileHelper(proxy, file.Pass()) {
57a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
58a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
59a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  void Close() {
60a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    file_.Close();
61a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    error_ = File::FILE_OK;
62a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
63a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
64a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  void SetTimes(Time last_access_time, Time last_modified_time) {
65a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    bool rv = file_.SetTimes(last_access_time, last_modified_time);
66a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    error_ = rv ? File::FILE_OK : File::FILE_ERROR_FAILED;
67a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
68a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
69a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  void SetLength(int64 length) {
70a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (file_.SetLength(length))
71a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      error_ = File::FILE_OK;
72a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
73a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
74a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  void Flush() {
75a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (file_.Flush())
76a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      error_ = File::FILE_OK;
77a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
78a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
79a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  void Reply(const FileProxy::StatusCallback& callback) {
80a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    PassFile();
81a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (!callback.is_null())
82a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      callback.Run(error_);
83a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
84a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
85a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) private:
86a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(GenericFileHelper);
87a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)};
88a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
89a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)class CreateOrOpenHelper : public FileHelper {
90a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) public:
91a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  CreateOrOpenHelper(FileProxy* proxy, File file)
92a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      : FileHelper(proxy, file.Pass()) {
93a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
94a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
95a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  void RunWork(const FilePath& file_path, int file_flags) {
96a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    file_.Initialize(file_path, file_flags);
97a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    error_ = file_.IsValid() ? File::FILE_OK : file_.error_details();
98a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
99a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
100a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  void Reply(const FileProxy::StatusCallback& callback) {
101a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    DCHECK(!callback.is_null());
102a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    PassFile();
103a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    callback.Run(error_);
104a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
105a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
106a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) private:
107a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(CreateOrOpenHelper);
108a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)};
109a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
110a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)class CreateTemporaryHelper : public FileHelper {
111a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) public:
112a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  CreateTemporaryHelper(FileProxy* proxy, File file)
113a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      : FileHelper(proxy, file.Pass()) {
114a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
115a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
116a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  void RunWork(uint32 additional_file_flags) {
117a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // TODO(darin): file_util should have a variant of CreateTemporaryFile
118a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // that returns a FilePath and a File.
119a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (!CreateTemporaryFile(&file_path_)) {
120a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      // TODO(davidben): base::CreateTemporaryFile should preserve the error
121a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      // code.
122a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      error_ = File::FILE_ERROR_FAILED;
123a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return;
124a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
125a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
126a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    uint32 file_flags = File::FLAG_WRITE |
127a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                        File::FLAG_TEMPORARY |
128a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                        File::FLAG_CREATE_ALWAYS |
129a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                        additional_file_flags;
130a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
131a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    file_.Initialize(file_path_, file_flags);
132a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (file_.IsValid()) {
133a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      error_ = File::FILE_OK;
134a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    } else {
135a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      error_ = file_.error_details();
136a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      DeleteFile(file_path_, false);
137a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      file_path_.clear();
138a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
139a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
140a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
141a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  void Reply(const FileProxy::CreateTemporaryCallback& callback) {
142a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    DCHECK(!callback.is_null());
143a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    PassFile();
144a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    callback.Run(error_, file_path_);
145a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
146a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
147a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) private:
148a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  FilePath file_path_;
149a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(CreateTemporaryHelper);
150a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)};
151a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
152a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)class GetInfoHelper : public FileHelper {
153a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) public:
154a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  GetInfoHelper(FileProxy* proxy, File file)
155a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      : FileHelper(proxy, file.Pass()) {
156a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
157a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
158a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  void RunWork() {
159a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (file_.GetInfo(&file_info_))
160a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      error_  = File::FILE_OK;
161a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
162a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
163a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  void Reply(const FileProxy::GetFileInfoCallback& callback) {
164a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    PassFile();
165a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    DCHECK(!callback.is_null());
166a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    callback.Run(error_, file_info_);
167a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
168a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
169a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) private:
170a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  File::Info file_info_;
171a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(GetInfoHelper);
172a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)};
173a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
174a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)class ReadHelper : public FileHelper {
175a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) public:
176a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ReadHelper(FileProxy* proxy, File file, int bytes_to_read)
177a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      : FileHelper(proxy, file.Pass()),
178a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        buffer_(new char[bytes_to_read]),
179a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        bytes_to_read_(bytes_to_read),
180a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        bytes_read_(0) {
181a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
182a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
183a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  void RunWork(int64 offset) {
184a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    bytes_read_ = file_.Read(offset, buffer_.get(), bytes_to_read_);
185a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    error_ = (bytes_read_ < 0) ? File::FILE_ERROR_FAILED : File::FILE_OK;
186a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
187a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
188a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  void Reply(const FileProxy::ReadCallback& callback) {
189a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    PassFile();
190a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    DCHECK(!callback.is_null());
191a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    callback.Run(error_, buffer_.get(), bytes_read_);
192a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
193a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
194a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) private:
195a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  scoped_ptr<char[]> buffer_;
196a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  int bytes_to_read_;
197a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  int bytes_read_;
198a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(ReadHelper);
199a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)};
200a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
201a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)class WriteHelper : public FileHelper {
202a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) public:
203a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  WriteHelper(FileProxy* proxy,
204a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)              File file,
205a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)              const char* buffer, int bytes_to_write)
206a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      : FileHelper(proxy, file.Pass()),
207a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        buffer_(new char[bytes_to_write]),
208a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        bytes_to_write_(bytes_to_write),
209a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        bytes_written_(0) {
210a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    memcpy(buffer_.get(), buffer, bytes_to_write);
211a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
212a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
213a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  void RunWork(int64 offset) {
214a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    bytes_written_ = file_.Write(offset, buffer_.get(), bytes_to_write_);
215a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    error_ = (bytes_written_ < 0) ? File::FILE_ERROR_FAILED : File::FILE_OK;
216a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
217a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
218a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  void Reply(const FileProxy::WriteCallback& callback) {
219a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    PassFile();
220a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (!callback.is_null())
221a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      callback.Run(error_, bytes_written_);
222a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
223a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
224a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) private:
225a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  scoped_ptr<char[]> buffer_;
226a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  int bytes_to_write_;
227a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  int bytes_written_;
228a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(WriteHelper);
229a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)};
230a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
231a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}  // namespace
232a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
233a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)FileProxy::FileProxy(TaskRunner* task_runner) : task_runner_(task_runner) {
234a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
235a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
236a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)FileProxy::~FileProxy() {
237010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (file_.IsValid())
238010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    task_runner_->PostTask(FROM_HERE, Bind(&FileDeleter, Passed(&file_)));
239a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
240a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
241a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool FileProxy::CreateOrOpen(const FilePath& file_path,
242a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                             uint32 file_flags,
243a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                             const StatusCallback& callback) {
244a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK(!file_.IsValid());
245a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  CreateOrOpenHelper* helper = new CreateOrOpenHelper(this, File());
246a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return task_runner_->PostTaskAndReply(
247a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      FROM_HERE,
248a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      Bind(&CreateOrOpenHelper::RunWork, Unretained(helper), file_path,
249a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)           file_flags),
250a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      Bind(&CreateOrOpenHelper::Reply, Owned(helper), callback));
251a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
252a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
253a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool FileProxy::CreateTemporary(uint32 additional_file_flags,
254a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                const CreateTemporaryCallback& callback) {
255a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK(!file_.IsValid());
256a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  CreateTemporaryHelper* helper = new CreateTemporaryHelper(this, File());
257a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return task_runner_->PostTaskAndReply(
258a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      FROM_HERE,
259a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      Bind(&CreateTemporaryHelper::RunWork, Unretained(helper),
260a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)           additional_file_flags),
261a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      Bind(&CreateTemporaryHelper::Reply, Owned(helper), callback));
262a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
263a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
264a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool FileProxy::IsValid() const {
265a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return file_.IsValid();
266a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
267a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
268cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void FileProxy::SetFile(File file) {
269cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(!file_.IsValid());
270cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  file_ = file.Pass();
271cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
272cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
273a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)File FileProxy::TakeFile() {
274a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return file_.Pass();
275a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
276a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
277cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)PlatformFile FileProxy::GetPlatformFile() const {
278cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return file_.GetPlatformFile();
279cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
280cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
281a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool FileProxy::Close(const StatusCallback& callback) {
282a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK(file_.IsValid());
283a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  GenericFileHelper* helper = new GenericFileHelper(this, file_.Pass());
284a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return task_runner_->PostTaskAndReply(
285a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      FROM_HERE,
286a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      Bind(&GenericFileHelper::Close, Unretained(helper)),
287a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      Bind(&GenericFileHelper::Reply, Owned(helper), callback));
288a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
289a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
290a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool FileProxy::GetInfo(const GetFileInfoCallback& callback) {
291a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK(file_.IsValid());
292a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  GetInfoHelper* helper = new GetInfoHelper(this, file_.Pass());
293a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return task_runner_->PostTaskAndReply(
294a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      FROM_HERE,
295a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      Bind(&GetInfoHelper::RunWork, Unretained(helper)),
296a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      Bind(&GetInfoHelper::Reply, Owned(helper), callback));
297a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
298a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
299a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool FileProxy::Read(int64 offset,
300a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                     int bytes_to_read,
301a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                     const ReadCallback& callback) {
302a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK(file_.IsValid());
303a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (bytes_to_read < 0)
304a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return false;
305a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
306a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ReadHelper* helper = new ReadHelper(this, file_.Pass(), bytes_to_read);
307a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return task_runner_->PostTaskAndReply(
308a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      FROM_HERE,
309a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      Bind(&ReadHelper::RunWork, Unretained(helper), offset),
310a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      Bind(&ReadHelper::Reply, Owned(helper), callback));
311a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
312a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
313a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool FileProxy::Write(int64 offset,
314a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                      const char* buffer,
315a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                      int bytes_to_write,
316a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                      const WriteCallback& callback) {
317a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK(file_.IsValid());
318a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (bytes_to_write <= 0 || buffer == NULL)
319a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return false;
320a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
321a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  WriteHelper* helper =
322a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      new WriteHelper(this, file_.Pass(), buffer, bytes_to_write);
323a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return task_runner_->PostTaskAndReply(
324a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      FROM_HERE,
325a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      Bind(&WriteHelper::RunWork, Unretained(helper), offset),
326a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      Bind(&WriteHelper::Reply, Owned(helper), callback));
327a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
328a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
329a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool FileProxy::SetTimes(Time last_access_time,
330a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                         Time last_modified_time,
331a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                         const StatusCallback& callback) {
332a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK(file_.IsValid());
333a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  GenericFileHelper* helper = new GenericFileHelper(this, file_.Pass());
334a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return task_runner_->PostTaskAndReply(
335a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      FROM_HERE,
336a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      Bind(&GenericFileHelper::SetTimes, Unretained(helper), last_access_time,
337a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)           last_modified_time),
338a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      Bind(&GenericFileHelper::Reply, Owned(helper), callback));
339a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
340a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
341a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool FileProxy::SetLength(int64 length, const StatusCallback& callback) {
342a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK(file_.IsValid());
343a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  GenericFileHelper* helper = new GenericFileHelper(this, file_.Pass());
344a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return task_runner_->PostTaskAndReply(
345a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      FROM_HERE,
346a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      Bind(&GenericFileHelper::SetLength, Unretained(helper), length),
347a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      Bind(&GenericFileHelper::Reply, Owned(helper), callback));
348a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
349a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
350a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool FileProxy::Flush(const StatusCallback& callback) {
351a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK(file_.IsValid());
352a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  GenericFileHelper* helper = new GenericFileHelper(this, file_.Pass());
353a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return task_runner_->PostTaskAndReply(
354a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      FROM_HERE,
355a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      Bind(&GenericFileHelper::Flush, Unretained(helper)),
356a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      Bind(&GenericFileHelper::Reply, Owned(helper), callback));
357a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
358a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
359a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}  // namespace base
360