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

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 callback.Run(base::PLATFORM_FILE_ERROR_INVALID_OPERATION);
131 // ... or should if be _FAILED?
kinuko 2011/12/14 03:39:22 Not really sure if we want this error check. (For
satorux1 2011/12/14 04:43:26 I'm not sure too. lseek() allows a larger offset a
132 return;
133 }
134
135 offset_ = offset;
136 callback.Run(base::PLATFORM_FILE_OK);
137 }
138
139 void FileUtilAsyncFileStream::DidReadOrWrite(
140 const ReadWriteCallback& callback,
141 int64 offset,
142 PlatformFileError result,
143 int64 written) {
144 DCHECK(pending_operation_);
145 pending_operation_ = false;
146 if (result == base::PLATFORM_FILE_OK) {
147 offset_ = offset + written;
148 }
149
150 callback.Run(result, written);
151 }
152
153 FileUtilAsync::FileUtilAsync() {
154 }
155
156 // Depending on the flags value the flow of file opening will be one of
157 // the following:
158 //
159 // PLATFORM_FILE_OPEN:
160 // GetFileInfo
161 // DidGetFileInfoForOpen
162 // OpenVerifiedFile
163 //
164 // PLATFORM_FILE_CREATE:
165 // Create
166 // DidCreateOrTruncateForOpen
167 // OpenVerifiedFile
168 //
169 // PLATFORM_FILE_OPEN_ALWAYS:
170 // GetFileInfo
171 // DidGetFileInfoForOpen
172 // OpenVerifiedFile OR Create
173 // DidCreateOrTruncateForOpen
174 // OpenVerifiedFile
175 //
176 // PLATFORM_FILE_CREATE_ALWAYS:
177 // Truncate
178 // OpenTruncatedFileOrCreate
179 // OpenVerifiedFile OR Create
180 // DidCreateOrTruncateForOpen
181 // OpenVerifiedFile
182 //
183 // PLATFORM_FILE_OPEN_TRUNCATED:
184 // Truncate
185 // DidCreateOrTruncateForOpen
186 // OpenVerifiedFile
187 //
188 void FileUtilAsync::Open(
189 const FilePath& file_path,
190 int flags,
191 const OpenCallback& callback) {
192 int create_flag = flags & (base::PLATFORM_FILE_OPEN |
193 base::PLATFORM_FILE_CREATE |
194 base::PLATFORM_FILE_OPEN_ALWAYS |
195 base::PLATFORM_FILE_CREATE_ALWAYS |
196 base::PLATFORM_FILE_OPEN_TRUNCATED);
197 switch (create_flag) {
198 case base::PLATFORM_FILE_OPEN:
199 case base::PLATFORM_FILE_OPEN_ALWAYS:
200 GetFileInfo(
201 file_path,
202 base::Bind(&FileUtilAsync::DidGetFileInfoForOpen,
203 base::Unretained(this), file_path, flags, callback));
204
205 break;
206
207 case base::PLATFORM_FILE_CREATE:
208 Create(
209 file_path,
210 base::Bind(&FileUtilAsync::DidCreateOrTruncateForOpen,
211 base::Unretained(this), file_path, flags, 0, callback));
212 break;
213
214 case base::PLATFORM_FILE_CREATE_ALWAYS:
215 Truncate(
216 file_path,
217 0,
218 base::Bind(&FileUtilAsync::OpenTruncatedFileOrCreate,
219 base::Unretained(this), file_path, flags, callback));
220
221 case base::PLATFORM_FILE_OPEN_TRUNCATED:
222 Truncate(
223 file_path,
224 0,
225 base::Bind(&FileUtilAsync::DidCreateOrTruncateForOpen,
226 base::Unretained(this), file_path, flags, 0, callback));
227 break;
228
229 default:
230 MessageLoop::current()->PostTask(
231 FROM_HERE,
232 base::Bind(&FileUtilAsync::ReturnOpenError,
233 base::Unretained(this),
234 base::PLATFORM_FILE_ERROR_INVALID_OPERATION, callback));
kinuko 2011/12/14 03:39:22 I think this should work: Bind(callback, INVALID_O
satorux1 2011/12/14 04:43:26 Good idea. Done.
235 }
236 }
237
238 void FileUtilAsync::OpenVerifiedFile(
239 const FilePath& file_path,
240 int flags,
241 const OpenCallback& callback) {
242 callback.Run(base::PLATFORM_FILE_OK,
243 new FileUtilAsyncFileStream(this, file_path, flags));
244 }
245
246 void FileUtilAsync::DidGetFileInfoForOpen(
247 const FilePath& file_path,
248 int flags,
249 const OpenCallback& callback,
250 PlatformFileError get_info_res,
251 const base::PlatformFileInfo& file_info) {
252 if (get_info_res == base::PLATFORM_FILE_OK && file_info.is_directory) {
253 callback.Run(base::PLATFORM_FILE_ERROR_NOT_A_FILE, NULL);
254 return;
255 }
256
257 if (get_info_res == base::PLATFORM_FILE_OK) {
258 OpenVerifiedFile(file_path, flags, callback);
259 return;
260 }
261
262 if (get_info_res == base::PLATFORM_FILE_ERROR_NOT_FOUND &&
263 flags & base::PLATFORM_FILE_CREATE_ALWAYS) {
264 Create(file_path,
265 base::Bind(&FileUtilAsync::DidCreateOrTruncateForOpen,
266 base::Unretained(this), file_path, flags, 0, callback));
267 return;
268 }
269
270 callback.Run(get_info_res, NULL);
271 }
272
273 void FileUtilAsync::OpenTruncatedFileOrCreate(
274 const FilePath& file_path,
275 int flags,
276 const OpenCallback& callback,
277 PlatformFileError res) {
278 if (res == base::PLATFORM_FILE_OK) {
279 OpenVerifiedFile(file_path, flags, callback);
280 return;
281 }
282
283 if (res == base::PLATFORM_FILE_ERROR_NOT_FOUND) {
284 Create(
285 file_path,
286 base::Bind(&FileUtilAsync::DidCreateOrTruncateForOpen,
287 base::Unretained(this), file_path, flags, 0, callback));
kinuko 2011/12/14 03:39:22 need to return here?
satorux1 2011/12/14 04:43:26 Done.
288 }
289
290 callback.Run(res, NULL);
291 }
292
293 void FileUtilAsync::DidCreateOrTruncateForOpen(
294 const FilePath& file_path,
295 int flags,
296 int64 size,
297 const OpenCallback& callback,
298 PlatformFileError res) {
299 if (res != base::PLATFORM_FILE_OK) {
300 callback.Run(res, NULL);
301 return;
302 }
303
304 OpenVerifiedFile(file_path, flags, callback);
305 }
306
307 void FileUtilAsync::ReturnOpenError(
308 PlatformFileError error,
309 const OpenCallback& callback) {
310 callback.Run(error, NULL);
311 }
312
313 } // namespace fileapi
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698