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

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

Issue 496953003: [fsp] Make the reading operation abortable. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fixed indents. Created 6 years, 4 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
1 // Copyright 2014 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/chromeos/file_system_provider/fileapi/file_stream_reade r.h" 5 #include "chrome/browser/chromeos/file_system_provider/fileapi/file_stream_reade r.h"
6 6
7 #include "base/debug/trace_event.h" 7 #include "base/debug/trace_event.h"
8 #include "base/files/file.h" 8 #include "base/files/file.h"
9 #include "base/memory/ref_counted.h" 9 #include "base/memory/ref_counted.h"
10 #include "chrome/browser/chromeos/file_system_provider/fileapi/provider_async_fi le_util.h" 10 #include "chrome/browser/chromeos/file_system_provider/fileapi/provider_async_fi le_util.h"
(...skipping 12 matching lines...) Expand all
23 // Dicards the callback from CloseFile(). 23 // Dicards the callback from CloseFile().
24 void EmptyStatusCallback(base::File::Error /* result */) { 24 void EmptyStatusCallback(base::File::Error /* result */) {
25 } 25 }
26 26
27 // Converts net::CompletionCallback to net::Int64CompletionCallback. 27 // Converts net::CompletionCallback to net::Int64CompletionCallback.
28 void Int64ToIntCompletionCallback(net::CompletionCallback callback, 28 void Int64ToIntCompletionCallback(net::CompletionCallback callback,
29 int64 result) { 29 int64 result) {
30 callback.Run(static_cast<int>(result)); 30 callback.Run(static_cast<int>(result));
31 } 31 }
32 32
33 // Opens a file for reading and calls the completion callback. Must be called
34 // on UI thread.
35 void OpenFileOnUIThread(
36 const fileapi::FileSystemURL& url,
37 const FileStreamReader::OpenFileCompletedCallback& callback) {
38 DCHECK_CURRENTLY_ON(BrowserThread::UI);
39
40 util::FileSystemURLParser parser(url);
41 if (!parser.Parse()) {
42 callback.Run(base::WeakPtr<ProvidedFileSystemInterface>(),
43 base::FilePath(),
44 0 /* file_handle */,
45 base::File::FILE_ERROR_SECURITY);
46 return;
47 }
48
49 parser.file_system()->OpenFile(
50 parser.file_path(),
51 ProvidedFileSystemInterface::OPEN_FILE_MODE_READ,
52 base::Bind(
53 callback, parser.file_system()->GetWeakPtr(), parser.file_path()));
54 }
55
56 // Forwards results of calling OpenFileOnUIThread back to the IO thread.
57 void OnOpenFileCompletedOnUIThread(
58 const FileStreamReader::OpenFileCompletedCallback& callback,
59 base::WeakPtr<ProvidedFileSystemInterface> file_system,
60 const base::FilePath& file_path,
61 int file_handle,
62 base::File::Error result) {
63 DCHECK_CURRENTLY_ON(BrowserThread::UI);
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 DCHECK_CURRENTLY_ON(BrowserThread::UI);
75 if (file_system.get())
76 file_system->CloseFile(file_handle, base::Bind(&EmptyStatusCallback));
77 }
78
79 // Requests reading contents of a file. In case of either success or a failure
80 // |callback| is executed. It can be called many times, until |has_more| is set
81 // to false. This function guarantees that it will succeed only if the file has
82 // not been changed while reading. Must be called on UI thread.
83 void ReadFileOnUIThread(
84 base::WeakPtr<ProvidedFileSystemInterface> file_system,
85 int file_handle,
86 scoped_refptr<net::IOBuffer> buffer,
87 int64 offset,
88 int length,
89 const ProvidedFileSystemInterface::ReadChunkReceivedCallback& callback) {
90 DCHECK_CURRENTLY_ON(BrowserThread::UI);
91
92 // If the file system got unmounted, then abort the reading operation.
93 if (!file_system.get()) {
94 callback.Run(0, false /* has_more */, base::File::FILE_ERROR_ABORT);
95 return;
96 }
97
98 file_system->ReadFile(file_handle, buffer, offset, length, callback);
99 }
100
101 // Forward the completion callback to IO thread.
102 void OnReadChunkReceivedOnUIThread(
103 const ProvidedFileSystemInterface::ReadChunkReceivedCallback&
104 chunk_received_callback,
105 int chunk_length,
106 bool has_more,
107 base::File::Error result) {
108 DCHECK_CURRENTLY_ON(BrowserThread::UI);
109 BrowserThread::PostTask(
110 BrowserThread::IO,
111 FROM_HERE,
112 base::Bind(chunk_received_callback, chunk_length, has_more, result));
113 }
114
115 // Requests metadata of a file. In case of either succes or a failure,
116 // |callback is executed. Must be called on UI thread.
117 void GetMetadataOnUIThread(
118 base::WeakPtr<ProvidedFileSystemInterface> file_system,
119 const base::FilePath& file_path,
120 const ProvidedFileSystemInterface::GetMetadataCallback& callback) {
121 DCHECK_CURRENTLY_ON(BrowserThread::UI);
122
123 // If the file system got unmounted, then abort the get length operation.
124 if (!file_system.get()) {
125 callback.Run(EntryMetadata(), base::File::FILE_ERROR_ABORT);
126 return;
127 }
128
129 file_system->GetMetadata(file_path, callback);
130 }
131
132 // Forward the completion callback to IO thread.
133 void OnGetMetadataReceivedOnUIThread(
134 const ProvidedFileSystemInterface::GetMetadataCallback& callback,
135 const EntryMetadata& metadata,
136 base::File::Error result) {
137 DCHECK_CURRENTLY_ON(BrowserThread::UI);
138 BrowserThread::PostTask(
139 BrowserThread::IO, FROM_HERE, base::Bind(callback, metadata, result));
140 }
141
142 } // namespace 33 } // namespace
143 34
35 class FileStreamReader::OperationRunner
36 : public base::RefCountedThreadSafe<FileStreamReader::OperationRunner> {
37 public:
38 OperationRunner() : file_handle_(-1) {}
39
40 // Opens a file for reading and calls the completion callback. Must be called
41 // on UI thread.
42 void OpenFileOnUIThread(
43 const fileapi::FileSystemURL& url,
44 const fileapi::AsyncFileUtil::StatusCallback& callback) {
45 DCHECK_CURRENTLY_ON(BrowserThread::UI);
46
47 util::FileSystemURLParser parser(url);
48 if (!parser.Parse()) {
49 BrowserThread::PostTask(
50 BrowserThread::IO,
51 FROM_HERE,
52 base::Bind(callback, base::File::FILE_ERROR_SECURITY));
53 return;
54 }
55
56 file_system_ = parser.file_system()->GetWeakPtr();
57 file_path_ = parser.file_path();
58 abort_callback_ = parser.file_system()->OpenFile(
59 file_path_,
60 ProvidedFileSystemInterface::OPEN_FILE_MODE_READ,
61 base::Bind(
62 &OperationRunner::OnOpenFileCompletedOnUIThread, this, callback));
63 }
64
65 // Closes a file. Ignores result, since it is called from a constructor.
66 // Must be called on UI thread.
67 void CloseFileOnUIThread() {
68 DCHECK_CURRENTLY_ON(BrowserThread::UI);
69 if (file_system_.get() && file_handle_ != -1) {
70 file_system_->CloseFile(file_handle_, base::Bind(&EmptyStatusCallback));
71 // Closing a file must not be aborted, since we could end up on files
72 // which
73 // are never closed.
74 abort_callback_ = ProvidedFileSystemInterface::AbortCallback();
hirono 2014/08/22 06:44:55 If file_system_.get() == NULL, does not it update
mtomasz 2014/08/22 08:25:19 Hm. The aborting logic has serious flaws. Let me r
mtomasz 2014/08/25 00:46:32 The abort_callback_ should store the callback to t
75 }
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_more| is
80 // set
81 // to false. This function guarantees that it will succeed only if the file
82 // has
83 // not been changed while reading. Must be called on UI thread.
84 void ReadFileOnUIThread(
85 scoped_refptr<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 BrowserThread::PostTask(
94 BrowserThread::IO,
95 FROM_HERE,
96 base::Bind(
97 callback, 0, false /* has_more */, base::File::FILE_ERROR_ABORT));
98 return;
99 }
100
101 abort_callback_ = file_system_->ReadFile(
102 file_handle_,
103 buffer,
104 offset,
105 length,
106 base::Bind(
107 &OperationRunner::OnReadFileCompletedOnUIThread, this, callback));
108 }
109
110 // Requests metadata of a file. In case of either succes or a failure,
111 // |callback is executed. Must be called on UI thread.
112 void GetMetadataOnUIThread(
113 const ProvidedFileSystemInterface::GetMetadataCallback& callback) {
114 DCHECK_CURRENTLY_ON(BrowserThread::UI);
115
116 // If the file system got unmounted, then abort the get length operation.
117 if (!file_system_.get()) {
118 BrowserThread::PostTask(
119 BrowserThread::IO,
120 FROM_HERE,
121 base::Bind(callback, EntryMetadata(), base::File::FILE_ERROR_ABORT));
122 return;
123 }
124
125 abort_callback_ = file_system_->GetMetadata(
126 file_path_,
127 base::Bind(&OperationRunner::OnGetMetadataCompletedOnUIThread,
128 this,
129 callback));
130 }
131
132 // Aborts the most recent operation (if exists), and calls the callback.
133 void AbortOnUIThread(const fileapi::AsyncFileUtil::StatusCallback& callback) {
134 DCHECK_CURRENTLY_ON(BrowserThread::UI);
135
136 if (abort_callback_.is_null()) {
137 // No operation to be cancelled. At most a callback call, which will be
138 // discarded.
139 BrowserThread::PostTask(BrowserThread::IO,
140 FROM_HERE,
141 base::Bind(callback, base::File::FILE_OK));
142 return;
143 }
144
145 const ProvidedFileSystemInterface::AbortCallback abort_callback =
146 abort_callback_;
147 abort_callback_ = ProvidedFileSystemInterface::AbortCallback();
148 abort_callback.Run(base::Bind(
149 &OperationRunner::OnAbortCompletedOnUIThread, this, callback));
150 }
151
152 private:
153 friend class base::RefCountedThreadSafe<OperationRunner>;
154
155 virtual ~OperationRunner() {}
156
157 // Remembers a file handle for further operations and forwards the result to
158 // the IO thread.
159 void OnOpenFileCompletedOnUIThread(
160 const fileapi::AsyncFileUtil::StatusCallback& callback,
161 int file_handle,
162 base::File::Error result) {
163 DCHECK_CURRENTLY_ON(BrowserThread::UI);
164
165 file_handle_ = file_handle;
hirono 2014/08/22 06:44:55 The complete callback does not clear abort_callbac
166 BrowserThread::PostTask(
167 BrowserThread::IO, FROM_HERE, base::Bind(callback, result));
168 }
169
170 // Forwards a metadata to the IO thread.
171 void OnGetMetadataCompletedOnUIThread(
172 const ProvidedFileSystemInterface::GetMetadataCallback& callback,
173 const EntryMetadata& metadata,
174 base::File::Error result) {
175 DCHECK_CURRENTLY_ON(BrowserThread::UI);
176 BrowserThread::PostTask(
177 BrowserThread::IO, FROM_HERE, base::Bind(callback, metadata, result));
178 }
179
180 // Forwards a response of reading from a file to the IO thread.
181 void OnReadFileCompletedOnUIThread(
182 const ProvidedFileSystemInterface::ReadChunkReceivedCallback&
183 chunk_received_callback,
184 int chunk_length,
185 bool has_more,
186 base::File::Error result) {
187 DCHECK_CURRENTLY_ON(BrowserThread::UI);
188 BrowserThread::PostTask(
189 BrowserThread::IO,
190 FROM_HERE,
191 base::Bind(chunk_received_callback, chunk_length, has_more, result));
192 }
193
194 // Forwards a response of aborting an operation to the IO thread.
195 void OnAbortCompletedOnUIThread(
196 const fileapi::AsyncFileUtil::StatusCallback& callback,
197 base::File::Error result) {
198 DCHECK_CURRENTLY_ON(BrowserThread::UI);
199 BrowserThread::PostTask(
200 BrowserThread::IO, FROM_HERE, base::Bind(callback, result));
201 }
202
203 ProvidedFileSystemInterface::AbortCallback abort_callback_;
204 base::WeakPtr<ProvidedFileSystemInterface> file_system_;
205 base::FilePath file_path_;
206 int file_handle_;
207
208 DISALLOW_COPY_AND_ASSIGN(OperationRunner);
209 };
210
144 FileStreamReader::FileStreamReader(fileapi::FileSystemContext* context, 211 FileStreamReader::FileStreamReader(fileapi::FileSystemContext* context,
145 const fileapi::FileSystemURL& url, 212 const fileapi::FileSystemURL& url,
146 int64 initial_offset, 213 int64 initial_offset,
147 const base::Time& expected_modification_time) 214 const base::Time& expected_modification_time)
148 : url_(url), 215 : url_(url),
149 current_offset_(initial_offset), 216 current_offset_(initial_offset),
150 current_length_(0), 217 current_length_(0),
151 expected_modification_time_(expected_modification_time), 218 expected_modification_time_(expected_modification_time),
219 runner_(new OperationRunner),
152 state_(NOT_INITIALIZED), 220 state_(NOT_INITIALIZED),
153 file_handle_(0),
154 weak_ptr_factory_(this) { 221 weak_ptr_factory_(this) {
155 } 222 }
156 223
157 FileStreamReader::~FileStreamReader() { 224 FileStreamReader::~FileStreamReader() {
225 // FileStreamReader doesn't have a Cancel() method like in FileStreamWriter.
226 // Therefore, aborting is done from the destructor.
227 BrowserThread::PostTask(BrowserThread::UI,
228 FROM_HERE,
229 base::Bind(&OperationRunner::AbortOnUIThread,
230 runner_,
231 base::Bind(&EmptyStatusCallback)));
232
158 BrowserThread::PostTask( 233 BrowserThread::PostTask(
159 BrowserThread::UI, 234 BrowserThread::UI,
160 FROM_HERE, 235 FROM_HERE,
161 base::Bind(&CloseFileOnUIThread, file_system_, file_handle_)); 236 base::Bind(&OperationRunner::CloseFileOnUIThread, runner_));
162 } 237 }
163 238
164 void FileStreamReader::Initialize( 239 void FileStreamReader::Initialize(
165 const base::Closure& pending_closure, 240 const base::Closure& pending_closure,
166 const net::Int64CompletionCallback& error_callback) { 241 const net::Int64CompletionCallback& error_callback) {
167 DCHECK_EQ(NOT_INITIALIZED, state_); 242 DCHECK_EQ(NOT_INITIALIZED, state_);
168 state_ = INITIALIZING; 243 state_ = INITIALIZING;
169 244
170 BrowserThread::PostTask( 245 BrowserThread::PostTask(
171 BrowserThread::UI, 246 BrowserThread::UI,
172 FROM_HERE, 247 FROM_HERE,
173 base::Bind(&OpenFileOnUIThread, 248 base::Bind(&OperationRunner::OpenFileOnUIThread,
249 runner_,
174 url_, 250 url_,
175 base::Bind(&OnOpenFileCompletedOnUIThread, 251 base::Bind(&FileStreamReader::OnOpenFileCompleted,
176 base::Bind(&FileStreamReader::OnOpenFileCompleted, 252 weak_ptr_factory_.GetWeakPtr(),
177 weak_ptr_factory_.GetWeakPtr(), 253 pending_closure,
178 pending_closure, 254 error_callback)));
179 error_callback))));
180 } 255 }
181 256
182 void FileStreamReader::OnOpenFileCompleted( 257 void FileStreamReader::OnOpenFileCompleted(
183 const base::Closure& pending_closure, 258 const base::Closure& pending_closure,
184 const net::Int64CompletionCallback& error_callback, 259 const net::Int64CompletionCallback& error_callback,
185 base::WeakPtr<ProvidedFileSystemInterface> file_system,
186 const base::FilePath& file_path,
187 int file_handle,
188 base::File::Error result) { 260 base::File::Error result) {
189 DCHECK_CURRENTLY_ON(BrowserThread::IO); 261 DCHECK_CURRENTLY_ON(BrowserThread::IO);
190 DCHECK_EQ(INITIALIZING, state_); 262 DCHECK_EQ(INITIALIZING, state_);
191 263
192 // In case of an error, return immediately using the |error_callback| of the 264 // In case of an error, return immediately using the |error_callback| of the
193 // Read() or GetLength() pending request. 265 // Read() or GetLength() pending request.
194 if (result != base::File::FILE_OK) { 266 if (result != base::File::FILE_OK) {
195 state_ = FAILED; 267 state_ = FAILED;
196 error_callback.Run(net::FileErrorToNetError(result)); 268 error_callback.Run(net::FileErrorToNetError(result));
197 return; 269 return;
198 } 270 }
199 271
200 file_system_ = file_system; 272 DCHECK_EQ(base::File::FILE_OK, result);
201 file_path_ = file_path;
202 file_handle_ = file_handle;
203 DCHECK_LT(0, file_handle);
204 273
205 // Verify the last modification time. 274 // Verify the last modification time.
206 BrowserThread::PostTask( 275 BrowserThread::PostTask(
207 BrowserThread::UI, 276 BrowserThread::UI,
208 FROM_HERE, 277 FROM_HERE,
209 base::Bind(&GetMetadataOnUIThread, 278 base::Bind(&OperationRunner::GetMetadataOnUIThread,
210 file_system_, 279 runner_,
211 file_path_, 280 base::Bind(&FileStreamReader::OnInitializeCompleted,
212 base::Bind(&OnGetMetadataReceivedOnUIThread, 281 weak_ptr_factory_.GetWeakPtr(),
213 base::Bind(&FileStreamReader::OnInitializeCompleted, 282 pending_closure,
214 weak_ptr_factory_.GetWeakPtr(), 283 error_callback)));
215 pending_closure,
216 error_callback))));
217 } 284 }
218 285
219 void FileStreamReader::OnInitializeCompleted( 286 void FileStreamReader::OnInitializeCompleted(
220 const base::Closure& pending_closure, 287 const base::Closure& pending_closure,
221 const net::Int64CompletionCallback& error_callback, 288 const net::Int64CompletionCallback& error_callback,
222 const EntryMetadata& metadata, 289 const EntryMetadata& metadata,
223 base::File::Error result) { 290 base::File::Error result) {
224 DCHECK_CURRENTLY_ON(BrowserThread::IO); 291 DCHECK_CURRENTLY_ON(BrowserThread::IO);
225 DCHECK_EQ(INITIALIZING, state_); 292 DCHECK_EQ(INITIALIZING, state_);
226 293
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
334 scoped_refptr<net::IOBuffer> buffer, 401 scoped_refptr<net::IOBuffer> buffer,
335 int buffer_length, 402 int buffer_length,
336 const net::CompletionCallback& callback) { 403 const net::CompletionCallback& callback) {
337 DCHECK_CURRENTLY_ON(BrowserThread::IO); 404 DCHECK_CURRENTLY_ON(BrowserThread::IO);
338 DCHECK_EQ(INITIALIZED, state_); 405 DCHECK_EQ(INITIALIZED, state_);
339 406
340 current_length_ = 0; 407 current_length_ = 0;
341 BrowserThread::PostTask( 408 BrowserThread::PostTask(
342 BrowserThread::UI, 409 BrowserThread::UI,
343 FROM_HERE, 410 FROM_HERE,
344 base::Bind(&ReadFileOnUIThread, 411 base::Bind(&OperationRunner::ReadFileOnUIThread,
345 file_system_, 412 runner_,
346 file_handle_,
347 buffer, 413 buffer,
348 current_offset_, 414 current_offset_,
349 buffer_length, 415 buffer_length,
350 base::Bind(&OnReadChunkReceivedOnUIThread, 416 base::Bind(&FileStreamReader::OnReadChunkReceived,
351 base::Bind(&FileStreamReader::OnReadChunkReceived, 417 weak_ptr_factory_.GetWeakPtr(),
352 weak_ptr_factory_.GetWeakPtr(), 418 callback)));
353 callback))));
354 } 419 }
355 420
356 void FileStreamReader::GetLengthAfterInitialized( 421 void FileStreamReader::GetLengthAfterInitialized(
357 const net::Int64CompletionCallback& callback) { 422 const net::Int64CompletionCallback& callback) {
358 DCHECK_CURRENTLY_ON(BrowserThread::IO); 423 DCHECK_CURRENTLY_ON(BrowserThread::IO);
359 DCHECK_EQ(INITIALIZED, state_); 424 DCHECK_EQ(INITIALIZED, state_);
360 425
361 BrowserThread::PostTask( 426 BrowserThread::PostTask(
362 BrowserThread::UI, 427 BrowserThread::UI,
363 FROM_HERE, 428 FROM_HERE,
364 base::Bind( 429 base::Bind(
365 &GetMetadataOnUIThread, 430 &OperationRunner::GetMetadataOnUIThread,
366 file_system_, 431 runner_,
367 file_path_, 432 base::Bind(&FileStreamReader::OnGetMetadataForGetLengthReceived,
368 base::Bind( 433 weak_ptr_factory_.GetWeakPtr(),
369 &OnGetMetadataReceivedOnUIThread, 434 callback)));
370 base::Bind(&FileStreamReader::OnGetMetadataForGetLengthReceived,
371 weak_ptr_factory_.GetWeakPtr(),
372 callback))));
373 } 435 }
374 436
375 void FileStreamReader::OnReadChunkReceived( 437 void FileStreamReader::OnReadChunkReceived(
376 const net::CompletionCallback& callback, 438 const net::CompletionCallback& callback,
377 int chunk_length, 439 int chunk_length,
378 bool has_more, 440 bool has_more,
379 base::File::Error result) { 441 base::File::Error result) {
380 DCHECK_CURRENTLY_ON(BrowserThread::IO); 442 DCHECK_CURRENTLY_ON(BrowserThread::IO);
381 DCHECK_EQ(INITIALIZED, state_); 443 DCHECK_EQ(INITIALIZED, state_);
382 444
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
422 callback.Run(net::ERR_UPLOAD_FILE_CHANGED); 484 callback.Run(net::ERR_UPLOAD_FILE_CHANGED);
423 return; 485 return;
424 } 486 }
425 487
426 DCHECK_EQ(base::File::FILE_OK, result); 488 DCHECK_EQ(base::File::FILE_OK, result);
427 callback.Run(metadata.size); 489 callback.Run(metadata.size);
428 } 490 }
429 491
430 } // namespace file_system_provider 492 } // namespace file_system_provider
431 } // namespace chromeos 493 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698