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

Side by Side Diff: chrome/browser/chromeos/file_system_provider/fileapi/file_stream_reader.cc

Issue 288113004: [fsp] Add FileStreamReader for the reading operation. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Cleaned up. Created 6 years, 7 months 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 2014 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 "chrome/browser/chromeos/file_system_provider/fileapi/file_stream_reade r.h"
6
7 #include "base/files/file.h"
8 #include "chrome/browser/chromeos/file_system_provider/fileapi/provider_async_fi le_util.h"
9 #include "chrome/browser/chromeos/file_system_provider/mount_path_util.h"
10 #include "chrome/browser/chromeos/file_system_provider/provided_file_system_inte rface.h"
11 #include "content/public/browser/browser_thread.h"
12 #include "net/base/net_errors.h"
13
14 using content::BrowserThread;
15
16 namespace chromeos {
17 namespace file_system_provider {
18 namespace {
19
20 // Dicards the callback from CloseFile().
21 void EmptyStatusCallback(base::File::Error /* result */) {
22 }
23
24 // Converts net::CompletionCallback to net::Int64CompletionCallback.
25 void Int64ToIntCompletionCallback(net::CompletionCallback callback,
26 int64 result) {
27 callback.Run(static_cast<int>(result));
28 }
29
30 // Opens a file for reading and calls the completion callback. Must be called
31 // on UI thread.
32 void OpenFileOnUIThread(
33 const fileapi::FileSystemURL& url,
34 const FileStreamReader::InitializeCompletedCallback& callback) {
35 // TODO(mtomasz): Check if the modification time of the file is as expected.
36 util::FileSystemURLParser parser(url);
37 if (!parser.Parse()) {
38 BrowserThread::PostTask(
39 BrowserThread::IO,
40 FROM_HERE,
41 base::Bind(callback,
42 base::WeakPtr<ProvidedFileSystemInterface>(),
43 base::FilePath(),
44 0 /* file_handle */,
45 base::File::FILE_ERROR_SECURITY));
kinaba 2014/05/16 07:58:00 I think you can directly do callback.Run() because
mtomasz 2014/05/16 09:18:20 Done. I also added some thread checks.
46 return;
47 }
48
49 parser.file_system()->OpenFile(
50 parser.file_path(),
51 ProvidedFileSystemInterface::OPEN_FILE_MODE_READ,
52 false /* create */,
53 base::Bind(
54 callback, parser.file_system()->GetWeakPtr(), parser.file_path()));
55 }
56
57 // Forwards results of calling OpenFileOnUIThread back to the IO thread.
58 void OnOpenFileCompletedOnUIThread(
59 const FileStreamReader::InitializeCompletedCallback& callback,
60 base::WeakPtr<ProvidedFileSystemInterface> file_system,
61 const base::FilePath& file_path,
62 int file_handle,
63 base::File::Error result) {
64 BrowserThread::PostTask(
65 BrowserThread::IO,
66 FROM_HERE,
67 base::Bind(callback, file_system, file_path, file_handle, result));
68 }
69
70 // Closes a file. Ignores result, since it is called from a constructor.
71 // Must be called on UI thread.
72 void CloseFileOnUIThread(base::WeakPtr<ProvidedFileSystemInterface> file_system,
73 int file_handle) {
74 if (file_system.get())
75 file_system->CloseFile(file_handle, base::Bind(&EmptyStatusCallback));
76 }
77
78 // Requests reading contents of a file. In case of either success or a failure
79 // |callback| is executed. It can be called many times, until |has_next| is set
80 // to false. This function guarantees that it will succeed only if the file has
81 // not been changed while reading. Must be called on UI thread.
82 void ReadFileOnUIThread(
83 base::WeakPtr<ProvidedFileSystemInterface> file_system,
84 int file_handle,
85 net::IOBuffer* buffer,
86 int64 offset,
87 int length,
88 const ProvidedFileSystemInterface::ReadChunkReceivedCallback& callback) {
89 // If the file system got unmounted, then abort the reading operation.
90 if (!file_system.get()) {
91 BrowserThread::PostTask(
92 BrowserThread::IO,
93 FROM_HERE,
94 base::Bind(
95 callback, 0, false /* has_next */, base::File::FILE_ERROR_ABORT));
kinaba 2014/05/16 07:58:00 ditto: no need for posting.
mtomasz 2014/05/16 09:18:20 Done.
96 return;
97 }
98
99 file_system->ReadFile(file_handle, buffer, offset, length, callback);
100 }
101
102 // Forward the completion callback to IO thread.
103 void OnReadChunkReceivedOnUIThread(
104 const ProvidedFileSystemInterface::ReadChunkReceivedCallback&
105 chunk_received_callback,
106 int chunk_length,
107 bool has_next,
108 base::File::Error result) {
109 BrowserThread::PostTask(
110 BrowserThread::IO,
111 FROM_HERE,
112 base::Bind(chunk_received_callback, chunk_length, has_next, result));
113 }
114
115 // TODO(mtomasz): Comment.
kinaba 2014/05/16 07:58:00 Comment.
mtomasz 2014/05/16 09:18:20 Done.
116 void GetMetadataOnUIThread(
117 base::WeakPtr<ProvidedFileSystemInterface> file_system,
118 const base::FilePath& file_path,
119 const fileapi::AsyncFileUtil::GetFileInfoCallback& callback) {
120 // If the file system got unmounted, then abort the get length operation.
121 if (!file_system.get()) {
122 BrowserThread::PostTask(
123 BrowserThread::IO,
124 FROM_HERE,
125 base::Bind(callback, base::File::FILE_ERROR_ABORT, base::File::Info()));
126 return;
kinaba 2014/05/16 07:58:00 ditto: no need for posting.
mtomasz 2014/05/16 09:18:20 Done.
127 }
128
129 file_system->GetMetadata(file_path, callback);
130 }
131
132 // Forward the completion callback to IO thread.
133 void OnGetMetadataReceivedOnUIThread(
134 const fileapi::AsyncFileUtil::GetFileInfoCallback& callback,
135 base::File::Error result,
136 const base::File::Info& file_info) {
137 BrowserThread::PostTask(
138 BrowserThread::IO, FROM_HERE, base::Bind(callback, result, file_info));
139 }
140
141 } // namespace
142
143 FileStreamReader::FileStreamReader(fileapi::FileSystemContext* context,
144 const fileapi::FileSystemURL& url,
145 int64 initial_offset,
146 const base::Time& expected_modification_time)
147 : context_(context),
148 url_(url),
149 current_offset_(initial_offset),
150 current_length_(0),
151 expected_modification_time_(expected_modification_time),
152 file_handle_(0),
153 weak_ptr_factory_(this) {
154 }
155
156 FileStreamReader::~FileStreamReader() {
157 CloseFileOnUIThread(file_system_, file_handle_);
158 }
159
160 void FileStreamReader::Initialize(
161 const base::Closure& pending_closure,
162 const net::Int64CompletionCallback& error_callback) {
163 OpenFileOnUIThread(
164 url_,
165 base::Bind(&OnOpenFileCompletedOnUIThread,
166 base::Bind(&FileStreamReader::OnInitializeCompleted,
167 weak_ptr_factory_.GetWeakPtr(),
168 pending_closure,
169 error_callback)));
170 }
171
172 void FileStreamReader::OnInitializeCompleted(
173 const base::Closure& pending_closure,
174 const net::Int64CompletionCallback& error_callback,
175 base::WeakPtr<ProvidedFileSystemInterface> file_system,
176 const base::FilePath& file_path,
177 int file_handle,
178 base::File::Error result) {
179 // In case of an error, return immediately using the |error_callback| of the
180 // Read() or GetLength() pending request.
181 if (result != base::File::FILE_OK) {
182 error_callback.Run(net::FileErrorToNetError(result));
183 return;
184 }
185
186 file_system_ = file_system;
187 file_path_ = file_path;
188 file_handle_ = file_handle;
189 DCHECK_LT(0, file_handle);
190
191 // Run the task waiting for the initialization to be completed.
192 pending_closure.Run();
193 }
194
195 int FileStreamReader::Read(net::IOBuffer* buffer,
196 int buffer_length,
197 const net::CompletionCallback& callback) {
198 // Lazily initialize with the first call to Read().
199 if (!file_system_.get()) {
kinaba 2014/05/16 07:58:00 Dereferencing a weak pointer in different threads
mtomasz 2014/05/16 09:18:20 Oops. It is also incorrect here, since we don't wa
200 Initialize(base::Bind(&FileStreamReader::ReadAfterInitialized,
201 weak_ptr_factory_.GetWeakPtr(),
202 buffer,
203 buffer_length,
204 callback),
205 base::Bind(&Int64ToIntCompletionCallback, callback));
206 return net::ERR_IO_PENDING;
207 }
208
209 ReadAfterInitialized(buffer, buffer_length, callback);
210 return net::ERR_IO_PENDING;
211 }
212
213 int64 FileStreamReader::GetLength(
214 const net::Int64CompletionCallback& callback) {
215 // Lazily initialize with the first call to Read().
kinaba 2014/05/16 07:58:00 nit: Read() => GetLength()
mtomasz 2014/05/16 09:18:20 Done.
216 if (!file_system_.get()) {
217 Initialize(base::Bind(&FileStreamReader::GetLengthAfterInitialized,
218 weak_ptr_factory_.GetWeakPtr(),
219 callback),
220 callback);
221 return net::ERR_IO_PENDING;
222 }
223
224 GetLengthAfterInitialized(callback);
225 return net::ERR_IO_PENDING;
226 }
227
228 void FileStreamReader::ReadAfterInitialized(
229 net::IOBuffer* buffer,
230 int buffer_length,
231 const net::CompletionCallback& callback) {
232 // If the file system got unmounted, then abort the reading operation.
233 if (!file_system_.get()) {
234 callback.Run(net::ERR_ABORTED);
235 return;
236 }
237
238 current_length_ = 0;
239 BrowserThread::PostTask(
240 BrowserThread::UI,
241 FROM_HERE,
242 base::Bind(&ReadFileOnUIThread,
243 file_system_,
244 file_handle_,
245 buffer,
246 current_offset_,
247 buffer_length,
248 base::Bind(&OnReadChunkReceivedOnUIThread,
249 base::Bind(&FileStreamReader::OnReadChunkReceived,
250 weak_ptr_factory_.GetWeakPtr(),
251 callback))));
252 }
253
254 void FileStreamReader::GetLengthAfterInitialized(
255 const net::Int64CompletionCallback& callback) {
256 // If the file system got unmounted, then abort the length fetching operation.
257 if (!file_system_.get()) {
258 callback.Run(net::ERR_ABORTED);
259 return;
260 }
261
262 BrowserThread::PostTask(
263 BrowserThread::UI,
264 FROM_HERE,
265 base::Bind(
266 &GetMetadataOnUIThread,
267 file_system_,
268 file_path_,
269 base::Bind(
270 &OnGetMetadataReceivedOnUIThread,
271 base::Bind(&FileStreamReader::OnGetMetadataForGetLengthReceived,
272 weak_ptr_factory_.GetWeakPtr(),
273 callback))));
274 }
275
276 void FileStreamReader::OnReadChunkReceived(
277 const net::CompletionCallback& callback,
278 int chunk_length,
279 bool has_next,
280 base::File::Error result) {
281 current_length_ += chunk_length;
282
283 // If this is the last chunk with a success, then finalize.
284 if (!has_next && result == base::File::FILE_OK) {
285 current_offset_ += current_length_;
286 callback.Run(current_length_);
287 return;
288 }
289
290 // In case of an error, abort.
291 if (result != base::File::FILE_OK) {
292 DCHECK(!has_next);
293 callback.Run(net::FileErrorToNetError(result));
kinaba 2014/05/16 07:58:00 return;
mtomasz 2014/05/16 09:18:20 Done.
294 }
295
296 // More data is about to come, so do not call the callback yet.
297 DCHECK(has_next);
298 }
299
300 void FileStreamReader::OnGetMetadataForGetLengthReceived(
301 const net::Int64CompletionCallback& callback,
302 base::File::Error result,
303 const base::File::Info& file_info) {
304 // In case of an error, abort.
305 if (result != base::File::FILE_OK) {
306 callback.Run(net::FileErrorToNetError(result));
307 return;
308 }
309
310 DCHECK_EQ(result, base::File::FILE_OK);
311 callback.Run(file_info.size);
312 }
313
314 } // namespace file_system_provider
315 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698