Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(364)

Side by Side Diff: webkit/chromeos/fileapi/file_util_async.cc

Issue 8907014: Implement async verision of FileSystemFileUtil and in-memory file system for testing purposes. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Address comments Created 9 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "webkit/chromeos/fileapi/file_util_async.h"
6
7 #include "base/bind.h"
8 #include "base/memory/weak_ptr.h"
9 #include "base/message_loop.h"
10
11 namespace fileapi {
12
13 // Only one read/write operation may be active at any moment.
14 class FileUtilAsyncFileStream : public AsyncFileStream {
15 public:
16 virtual void Read(
17 char* buffer,
18 int64 length,
19 const ReadWriteCallback& callback) OVERRIDE;
20 virtual void Write(
21 const char* buffer,
22 int64 length,
23 const ReadWriteCallback& callback) OVERRIDE;
24 virtual void Seek(
25 int64 offset,
26 const StatusCallback& callback) OVERRIDE;
27
28 private:
29 friend class FileUtilAsync;
30
31 virtual ~FileUtilAsyncFileStream() {}
32
33 FileUtilAsyncFileStream(
34 FileUtilAsync* file_util,
35 const FilePath& file_path,
36 int flags);
37
38 void DoSeek(
39 int64 offset,
40 const StatusCallback& callback,
41 PlatformFileError get_file_info_res,
42 const base::PlatformFileInfo& file_info);
43
44 void DidReadOrWrite(
45 const ReadWriteCallback& callback,
46 int64 offset,
47 PlatformFileError result,
48 int64 written);
49
50 FileUtilAsync* file_util_; // This class does not own FileUtilAsync.
51 FilePath file_path_;
52 int flags_;
53 bool pending_operation_;
54 int64 offset_;
55 base::WeakPtrFactory<FileUtilAsyncFileStream> weak_ptr_factory_;
56 };
57
58 FileUtilAsyncFileStream::FileUtilAsyncFileStream(
59 FileUtilAsync* file_util,
60 const FilePath& file_path,
61 int flags)
62 : file_util_(file_util),
63 file_path_(file_path),
64 flags_(flags),
65 pending_operation_(false),
66 offset_(0),
67 weak_ptr_factory_(this) {
68 }
69
70 void FileUtilAsyncFileStream::Read(
71 char* buffer,
72 int64 length,
73 const ReadWriteCallback& callback) {
74 DCHECK(!pending_operation_);
75 if ((flags_ & base::PLATFORM_FILE_READ) == 0) {
76 MessageLoop::current()->PostTask(
77 FROM_HERE,
78 base::Bind(callback, base::PLATFORM_FILE_ERROR_INVALID_OPERATION, 0));
79 return;
80 }
81
82 pending_operation_ = true;
83
84 file_util_->Read(
85 file_path_, offset_, buffer, length,
86 base::Bind(&FileUtilAsyncFileStream::DidReadOrWrite,
87 weak_ptr_factory_.GetWeakPtr(), callback, offset_));
88 }
89
90 void FileUtilAsyncFileStream::Write(
91 const char* buffer,
92 int64 length,
93 const ReadWriteCallback& callback) {
94 DCHECK(!pending_operation_);
95 if ((flags_ & base::PLATFORM_FILE_WRITE) == 0) {
96 MessageLoop::current()->PostTask(
97 FROM_HERE,
98 base::Bind(callback, base::PLATFORM_FILE_ERROR_INVALID_OPERATION, 0));
99 return;
100 }
101
102 pending_operation_ = true;
103
104 file_util_->Write(
105 file_path_, offset_, buffer, length,
106 base::Bind(&FileUtilAsyncFileStream::DidReadOrWrite,
107 weak_ptr_factory_.GetWeakPtr(), callback, offset_));
108 }
109
110 void FileUtilAsyncFileStream::Seek(
111 int64 offset,
112 const StatusCallback& callback) {
113 file_util_->GetFileInfo(
114 file_path_,
115 base::Bind(&FileUtilAsyncFileStream::DoSeek,
116 weak_ptr_factory_.GetWeakPtr(), offset, callback));
117 }
118
119 void FileUtilAsyncFileStream::DoSeek(
120 int64 offset,
121 const StatusCallback& callback,
122 PlatformFileError get_file_info_res,
123 const base::PlatformFileInfo& file_info) {
124 if (get_file_info_res != base::PLATFORM_FILE_OK) {
125 callback.Run(get_file_info_res);
126 return;
127 }
128
129 if (offset > file_info.size) {
130 // TODO(satorux): Should we really fail with of an offset larger than
131 // the file size?
132 callback.Run(base::PLATFORM_FILE_ERROR_INVALID_OPERATION);
133 return;
134 }
135
136 offset_ = offset;
137 callback.Run(base::PLATFORM_FILE_OK);
138 }
139
140 void FileUtilAsyncFileStream::DidReadOrWrite(
141 const ReadWriteCallback& callback,
142 int64 offset,
143 PlatformFileError result,
144 int64 written) {
145 DCHECK(pending_operation_);
146 pending_operation_ = false;
147 if (result == base::PLATFORM_FILE_OK) {
148 offset_ = offset + written;
149 }
150
151 callback.Run(result, written);
152 }
153
154 FileUtilAsync::FileUtilAsync() {
155 }
156
157 // Depending on the flags value the flow of file opening will be one of
158 // the following:
159 //
160 // PLATFORM_FILE_OPEN:
161 // GetFileInfo
162 // DidGetFileInfoForOpen
163 // OpenVerifiedFile
164 //
165 // PLATFORM_FILE_CREATE:
166 // Create
167 // DidCreateOrTruncateForOpen
168 // OpenVerifiedFile
169 //
170 // PLATFORM_FILE_OPEN_ALWAYS:
171 // GetFileInfo
172 // DidGetFileInfoForOpen
173 // OpenVerifiedFile OR Create
174 // DidCreateOrTruncateForOpen
175 // OpenVerifiedFile
176 //
177 // PLATFORM_FILE_CREATE_ALWAYS:
178 // Truncate
179 // OpenTruncatedFileOrCreate
180 // OpenVerifiedFile OR Create
181 // DidCreateOrTruncateForOpen
182 // OpenVerifiedFile
183 //
184 // PLATFORM_FILE_OPEN_TRUNCATED:
185 // Truncate
186 // DidCreateOrTruncateForOpen
187 // OpenVerifiedFile
188 //
189 void FileUtilAsync::Open(
190 const FilePath& file_path,
191 int flags,
192 const OpenCallback& callback) {
193 int create_flag = flags & (base::PLATFORM_FILE_OPEN |
194 base::PLATFORM_FILE_CREATE |
195 base::PLATFORM_FILE_OPEN_ALWAYS |
196 base::PLATFORM_FILE_CREATE_ALWAYS |
197 base::PLATFORM_FILE_OPEN_TRUNCATED);
198 switch (create_flag) {
199 case base::PLATFORM_FILE_OPEN:
200 case base::PLATFORM_FILE_OPEN_ALWAYS:
201 GetFileInfo(
202 file_path,
203 base::Bind(&FileUtilAsync::DidGetFileInfoForOpen,
204 base::Unretained(this), file_path, flags, callback));
205
206 break;
207
208 case base::PLATFORM_FILE_CREATE:
209 Create(
210 file_path,
211 base::Bind(&FileUtilAsync::DidCreateOrTruncateForOpen,
212 base::Unretained(this), file_path, flags, 0, callback));
213 break;
214
215 case base::PLATFORM_FILE_CREATE_ALWAYS:
216 Truncate(
217 file_path,
218 0,
219 base::Bind(&FileUtilAsync::OpenTruncatedFileOrCreate,
220 base::Unretained(this), file_path, flags, callback));
221
222 case base::PLATFORM_FILE_OPEN_TRUNCATED:
223 Truncate(
224 file_path,
225 0,
226 base::Bind(&FileUtilAsync::DidCreateOrTruncateForOpen,
227 base::Unretained(this), file_path, flags, 0, callback));
228 break;
229
230 default:
231 MessageLoop::current()->PostTask(
232 FROM_HERE,
233 base::Bind(callback,
234 base::PLATFORM_FILE_ERROR_INVALID_OPERATION,
235 static_cast<AsyncFileStream*>(NULL)));
236 }
237 }
238
239 void FileUtilAsync::OpenVerifiedFile(
240 const FilePath& file_path,
241 int flags,
242 const OpenCallback& callback) {
243 callback.Run(base::PLATFORM_FILE_OK,
244 new FileUtilAsyncFileStream(this, file_path, flags));
245 }
246
247 void FileUtilAsync::DidGetFileInfoForOpen(
248 const FilePath& file_path,
249 int flags,
250 const OpenCallback& callback,
251 PlatformFileError get_info_res,
252 const base::PlatformFileInfo& file_info) {
253 if (get_info_res == base::PLATFORM_FILE_OK && file_info.is_directory) {
254 callback.Run(base::PLATFORM_FILE_ERROR_NOT_A_FILE, NULL);
255 return;
256 }
257
258 if (get_info_res == base::PLATFORM_FILE_OK) {
259 OpenVerifiedFile(file_path, flags, callback);
260 return;
261 }
262
263 if (get_info_res == base::PLATFORM_FILE_ERROR_NOT_FOUND &&
264 flags & base::PLATFORM_FILE_CREATE_ALWAYS) {
265 Create(file_path,
266 base::Bind(&FileUtilAsync::DidCreateOrTruncateForOpen,
267 base::Unretained(this), file_path, flags, 0, callback));
268 return;
269 }
270
271 callback.Run(get_info_res, NULL);
272 }
273
274 void FileUtilAsync::OpenTruncatedFileOrCreate(
275 const FilePath& file_path,
276 int flags,
277 const OpenCallback& callback,
278 PlatformFileError res) {
279 if (res == base::PLATFORM_FILE_OK) {
280 OpenVerifiedFile(file_path, flags, callback);
281 return;
282 }
283
284 if (res == base::PLATFORM_FILE_ERROR_NOT_FOUND) {
285 Create(
286 file_path,
287 base::Bind(&FileUtilAsync::DidCreateOrTruncateForOpen,
288 base::Unretained(this), file_path, flags, 0, callback));
289 return;
290 }
291
292 callback.Run(res, NULL);
293 }
294
295 void FileUtilAsync::DidCreateOrTruncateForOpen(
296 const FilePath& file_path,
297 int flags,
298 int64 size,
299 const OpenCallback& callback,
300 PlatformFileError res) {
301 if (res != base::PLATFORM_FILE_OK) {
302 callback.Run(res, NULL);
303 return;
304 }
305
306 OpenVerifiedFile(file_path, flags, callback);
307 }
308
309 } // namespace fileapi
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698