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

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: Fixed tests. 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 DCHECK_CURRENTLY_ON(BrowserThread::UI);
36
37 // TODO(mtomasz): Check if the modification time of the file is as expected.
38 util::FileSystemURLParser parser(url);
39 if (!parser.Parse()) {
40 callback.Run(base::WeakPtr<ProvidedFileSystemInterface>(),
41 base::FilePath(),
42 0 /* file_handle */,
43 base::File::FILE_ERROR_SECURITY);
44 return;
45 }
46
47 parser.file_system()->OpenFile(
48 parser.file_path(),
49 ProvidedFileSystemInterface::OPEN_FILE_MODE_READ,
50 false /* create */,
51 base::Bind(
52 callback, parser.file_system()->GetWeakPtr(), parser.file_path()));
53 }
54
55 // Forwards results of calling OpenFileOnUIThread back to the IO thread.
56 void OnOpenFileCompletedOnUIThread(
57 const FileStreamReader::InitializeCompletedCallback& callback,
58 base::WeakPtr<ProvidedFileSystemInterface> file_system,
59 const base::FilePath& file_path,
60 int file_handle,
61 base::File::Error result) {
62 DCHECK_CURRENTLY_ON(BrowserThread::UI);
63 BrowserThread::PostTask(
64 BrowserThread::IO,
65 FROM_HERE,
66 base::Bind(callback, file_system, file_path, file_handle, result));
67 }
68
69 // Closes a file. Ignores result, since it is called from a constructor.
70 // Must be called on UI thread.
71 void CloseFileOnUIThread(base::WeakPtr<ProvidedFileSystemInterface> file_system,
72 int file_handle) {
73 DCHECK_CURRENTLY_ON(BrowserThread::UI);
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 DCHECK_CURRENTLY_ON(BrowserThread::UI);
90
91 // If the file system got unmounted, then abort the reading operation.
92 if (!file_system.get()) {
93 callback.Run(0, false /* has_next */, base::File::FILE_ERROR_ABORT);
94 return;
95 }
96
97 file_system->ReadFile(file_handle, buffer, offset, length, callback);
98 }
99
100 // Forward the completion callback to IO thread.
101 void OnReadChunkReceivedOnUIThread(
102 const ProvidedFileSystemInterface::ReadChunkReceivedCallback&
103 chunk_received_callback,
104 int chunk_length,
105 bool has_next,
106 base::File::Error result) {
107 DCHECK_CURRENTLY_ON(BrowserThread::UI);
108 BrowserThread::PostTask(
109 BrowserThread::IO,
110 FROM_HERE,
111 base::Bind(chunk_received_callback, chunk_length, has_next, result));
112 }
113
114 // Requests metadata of a file. In case of either succes or a failure,
115 // |callback is executed. Must be called on UI thread.
116 void GetMetadataOnUIThread(
117 base::WeakPtr<ProvidedFileSystemInterface> file_system,
118 const base::FilePath& file_path,
119 const fileapi::AsyncFileUtil::GetFileInfoCallback& callback) {
120 DCHECK_CURRENTLY_ON(BrowserThread::UI);
121
122 // If the file system got unmounted, then abort the get length operation.
123 if (!file_system.get()) {
124 callback.Run(base::File::FILE_ERROR_ABORT, base::File::Info());
125 return;
126 }
127
128 file_system->GetMetadata(file_path, callback);
129 }
130
131 // Forward the completion callback to IO thread.
132 void OnGetMetadataReceivedOnUIThread(
133 const fileapi::AsyncFileUtil::GetFileInfoCallback& callback,
134 base::File::Error result,
135 const base::File::Info& file_info) {
136 DCHECK_CURRENTLY_ON(BrowserThread::UI);
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 : url_(url),
148 current_offset_(initial_offset),
149 current_length_(0),
150 expected_modification_time_(expected_modification_time),
151 file_handle_(0),
152 weak_ptr_factory_(this) {
153 }
154
155 FileStreamReader::~FileStreamReader() {
156 BrowserThread::PostTask(
157 BrowserThread::UI,
158 FROM_HERE,
159 base::Bind(&CloseFileOnUIThread, file_system_, file_handle_));
160 }
161
162 void FileStreamReader::Initialize(
163 const base::Closure& pending_closure,
164 const net::Int64CompletionCallback& error_callback) {
165 BrowserThread::PostTask(
166 BrowserThread::UI,
167 FROM_HERE,
168 base::Bind(&OpenFileOnUIThread,
169 url_,
170 base::Bind(&OnOpenFileCompletedOnUIThread,
171 base::Bind(&FileStreamReader::OnInitializeCompleted,
172 weak_ptr_factory_.GetWeakPtr(),
173 pending_closure,
174 error_callback))));
175 }
176
177 void FileStreamReader::OnInitializeCompleted(
178 const base::Closure& pending_closure,
179 const net::Int64CompletionCallback& error_callback,
180 base::WeakPtr<ProvidedFileSystemInterface> file_system,
181 const base::FilePath& file_path,
182 int file_handle,
183 base::File::Error result) {
184 DCHECK_CURRENTLY_ON(BrowserThread::IO);
185
186 // In case of an error, return immediately using the |error_callback| of the
187 // Read() or GetLength() pending request.
188 if (result != base::File::FILE_OK) {
189 error_callback.Run(net::FileErrorToNetError(result));
190 return;
191 }
192
193 file_system_ = file_system;
194 file_path_ = file_path;
195 file_handle_ = file_handle;
196 DCHECK_LT(0, file_handle);
197
198 // Run the task waiting for the initialization to be completed.
199 pending_closure.Run();
200 }
201
202 int FileStreamReader::Read(net::IOBuffer* buffer,
203 int buffer_length,
204 const net::CompletionCallback& callback) {
205 // Lazily initialize with the first call to Read().
206 if (!file_handle_) {
207 Initialize(base::Bind(&FileStreamReader::ReadAfterInitialized,
208 weak_ptr_factory_.GetWeakPtr(),
209 buffer,
210 buffer_length,
211 callback),
212 base::Bind(&Int64ToIntCompletionCallback, callback));
213 return net::ERR_IO_PENDING;
214 }
215
216 ReadAfterInitialized(buffer, buffer_length, callback);
217 return net::ERR_IO_PENDING;
218 }
219
220 int64 FileStreamReader::GetLength(
221 const net::Int64CompletionCallback& callback) {
222 // Lazily initialize with the first call to GetLength().
223 if (!file_handle_) {
224 Initialize(base::Bind(&FileStreamReader::GetLengthAfterInitialized,
225 weak_ptr_factory_.GetWeakPtr(),
226 callback),
227 callback);
228 return net::ERR_IO_PENDING;
229 }
230
231 GetLengthAfterInitialized(callback);
232 return net::ERR_IO_PENDING;
233 }
234
235 void FileStreamReader::ReadAfterInitialized(
236 net::IOBuffer* buffer,
237 int buffer_length,
238 const net::CompletionCallback& callback) {
239 DCHECK_CURRENTLY_ON(BrowserThread::IO);
240
241 // If the file system got unmounted, then abort the reading operation.
242 if (!file_handle_) {
243 callback.Run(net::ERR_ABORTED);
244 return;
245 }
246
247 current_length_ = 0;
248 BrowserThread::PostTask(
249 BrowserThread::UI,
250 FROM_HERE,
251 base::Bind(&ReadFileOnUIThread,
252 file_system_,
253 file_handle_,
254 buffer,
255 current_offset_,
256 buffer_length,
257 base::Bind(&OnReadChunkReceivedOnUIThread,
258 base::Bind(&FileStreamReader::OnReadChunkReceived,
259 weak_ptr_factory_.GetWeakPtr(),
260 callback))));
261 }
262
263 void FileStreamReader::GetLengthAfterInitialized(
264 const net::Int64CompletionCallback& callback) {
265 DCHECK_CURRENTLY_ON(BrowserThread::IO);
266
267 // If the file system got unmounted, then abort the length fetching operation.
268 if (!file_handle_) {
269 callback.Run(net::ERR_ABORTED);
270 return;
271 }
272
273 BrowserThread::PostTask(
274 BrowserThread::UI,
275 FROM_HERE,
276 base::Bind(
277 &GetMetadataOnUIThread,
278 file_system_,
279 file_path_,
280 base::Bind(
281 &OnGetMetadataReceivedOnUIThread,
282 base::Bind(&FileStreamReader::OnGetMetadataForGetLengthReceived,
283 weak_ptr_factory_.GetWeakPtr(),
284 callback))));
285 }
286
287 void FileStreamReader::OnReadChunkReceived(
288 const net::CompletionCallback& callback,
289 int chunk_length,
290 bool has_next,
291 base::File::Error result) {
292 DCHECK_CURRENTLY_ON(BrowserThread::IO);
293 current_length_ += chunk_length;
294
295 // If this is the last chunk with a success, then finalize.
296 if (!has_next && result == base::File::FILE_OK) {
297 current_offset_ += current_length_;
298 callback.Run(current_length_);
299 return;
300 }
301
302 // In case of an error, abort.
303 if (result != base::File::FILE_OK) {
304 DCHECK(!has_next);
305 callback.Run(net::FileErrorToNetError(result));
306 return;
307 }
308
309 // More data is about to come, so do not call the callback yet.
310 DCHECK(has_next);
311 }
312
313 void FileStreamReader::OnGetMetadataForGetLengthReceived(
314 const net::Int64CompletionCallback& callback,
315 base::File::Error result,
316 const base::File::Info& file_info) {
317 DCHECK_CURRENTLY_ON(BrowserThread::IO);
318
319 // In case of an error, abort.
320 if (result != base::File::FILE_OK) {
321 callback.Run(net::FileErrorToNetError(result));
322 return;
323 }
324
325 DCHECK_EQ(result, base::File::FILE_OK);
326 callback.Run(file_info.size);
327 }
328
329 } // namespace file_system_provider
330 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698