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

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. Created 6 years, 3 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 storage::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 storage::FileSystemURL& url,
44 const storage::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 // Closing a file must not be aborted, since we could end up on files
71 // which are never closed.
72 file_system_->CloseFile(file_handle_, base::Bind(&EmptyStatusCallback));
73 }
74 }
75
76 // Requests reading contents of a file. In case of either success or a failure
77 // |callback| is executed. It can be called many times, until |has_more| is
78 // set to false. This function guarantees that it will succeed only if the
79 // file has not been changed while reading. Must be called on UI thread.
80 void ReadFileOnUIThread(
81 scoped_refptr<net::IOBuffer> buffer,
82 int64 offset,
83 int length,
84 const ProvidedFileSystemInterface::ReadChunkReceivedCallback& callback) {
85 DCHECK_CURRENTLY_ON(BrowserThread::UI);
86
87 // If the file system got unmounted, then abort the reading operation.
88 if (!file_system_.get()) {
89 BrowserThread::PostTask(
90 BrowserThread::IO,
91 FROM_HERE,
92 base::Bind(
93 callback, 0, false /* has_more */, base::File::FILE_ERROR_ABORT));
94 return;
95 }
96
97 abort_callback_ = file_system_->ReadFile(
98 file_handle_,
99 buffer,
100 offset,
101 length,
102 base::Bind(
103 &OperationRunner::OnReadFileCompletedOnUIThread, this, callback));
104 }
105
106 // Requests metadata of a file. In case of either succes or a failure,
107 // |callback| is executed. Must be called on UI thread.
108 void GetMetadataOnUIThread(
109 const ProvidedFileSystemInterface::GetMetadataCallback& callback) {
110 DCHECK_CURRENTLY_ON(BrowserThread::UI);
111
112 // If the file system got unmounted, then abort the get length operation.
113 if (!file_system_.get()) {
114 BrowserThread::PostTask(
115 BrowserThread::IO,
116 FROM_HERE,
117 base::Bind(callback, EntryMetadata(), base::File::FILE_ERROR_ABORT));
118 return;
119 }
120
121 abort_callback_ = file_system_->GetMetadata(
122 file_path_,
123 base::Bind(&OperationRunner::OnGetMetadataCompletedOnUIThread,
124 this,
125 callback));
126 }
127
128 // Aborts the most recent operation (if exists), and calls the callback.
129 void AbortOnUIThread(const storage::AsyncFileUtil::StatusCallback& callback) {
130 DCHECK_CURRENTLY_ON(BrowserThread::UI);
131
132 if (abort_callback_.is_null()) {
133 // No operation to be cancelled. At most a callback call, which will be
134 // discarded.
135 BrowserThread::PostTask(BrowserThread::IO,
136 FROM_HERE,
137 base::Bind(callback, base::File::FILE_OK));
138 return;
139 }
140
141 const ProvidedFileSystemInterface::AbortCallback abort_callback =
142 abort_callback_;
143 abort_callback_ = ProvidedFileSystemInterface::AbortCallback();
144 abort_callback.Run(base::Bind(
145 &OperationRunner::OnAbortCompletedOnUIThread, this, callback));
146 }
147
148 private:
149 friend class base::RefCountedThreadSafe<OperationRunner>;
150
151 virtual ~OperationRunner() {}
152
153 // Remembers a file handle for further operations and forwards the result to
154 // the IO thread.
155 void OnOpenFileCompletedOnUIThread(
156 const storage::AsyncFileUtil::StatusCallback& callback,
157 int file_handle,
158 base::File::Error result) {
159 DCHECK_CURRENTLY_ON(BrowserThread::UI);
160
161 file_handle_ = file_handle;
162 BrowserThread::PostTask(
163 BrowserThread::IO, FROM_HERE, base::Bind(callback, result));
164 }
165
166 // Forwards a metadata to the IO thread.
167 void OnGetMetadataCompletedOnUIThread(
168 const ProvidedFileSystemInterface::GetMetadataCallback& callback,
169 const EntryMetadata& metadata,
170 base::File::Error result) {
171 DCHECK_CURRENTLY_ON(BrowserThread::UI);
172 BrowserThread::PostTask(
173 BrowserThread::IO, FROM_HERE, base::Bind(callback, metadata, result));
174 }
175
176 // Forwards a response of reading from a file to the IO thread.
177 void OnReadFileCompletedOnUIThread(
178 const ProvidedFileSystemInterface::ReadChunkReceivedCallback&
179 chunk_received_callback,
180 int chunk_length,
181 bool has_more,
182 base::File::Error result) {
183 DCHECK_CURRENTLY_ON(BrowserThread::UI);
184 BrowserThread::PostTask(
185 BrowserThread::IO,
186 FROM_HERE,
187 base::Bind(chunk_received_callback, chunk_length, has_more, result));
188 }
189
190 // Forwards a response of aborting an operation to the IO thread.
191 void OnAbortCompletedOnUIThread(
192 const storage::AsyncFileUtil::StatusCallback& callback,
193 base::File::Error result) {
194 DCHECK_CURRENTLY_ON(BrowserThread::UI);
195 BrowserThread::PostTask(
196 BrowserThread::IO, FROM_HERE, base::Bind(callback, result));
197 }
198
199 ProvidedFileSystemInterface::AbortCallback abort_callback_;
200 base::WeakPtr<ProvidedFileSystemInterface> file_system_;
201 base::FilePath file_path_;
202 int file_handle_;
203
204 DISALLOW_COPY_AND_ASSIGN(OperationRunner);
205 };
206
144 FileStreamReader::FileStreamReader(storage::FileSystemContext* context, 207 FileStreamReader::FileStreamReader(storage::FileSystemContext* context,
145 const storage::FileSystemURL& url, 208 const storage::FileSystemURL& url,
146 int64 initial_offset, 209 int64 initial_offset,
147 const base::Time& expected_modification_time) 210 const base::Time& expected_modification_time)
148 : url_(url), 211 : url_(url),
149 current_offset_(initial_offset), 212 current_offset_(initial_offset),
150 current_length_(0), 213 current_length_(0),
151 expected_modification_time_(expected_modification_time), 214 expected_modification_time_(expected_modification_time),
215 runner_(new OperationRunner),
152 state_(NOT_INITIALIZED), 216 state_(NOT_INITIALIZED),
153 file_handle_(0),
154 weak_ptr_factory_(this) { 217 weak_ptr_factory_(this) {
155 } 218 }
156 219
157 FileStreamReader::~FileStreamReader() { 220 FileStreamReader::~FileStreamReader() {
221 // FileStreamReader doesn't have a Cancel() method like in FileStreamWriter.
222 // Therefore, aborting is done from the destructor.
223 BrowserThread::PostTask(BrowserThread::UI,
224 FROM_HERE,
225 base::Bind(&OperationRunner::AbortOnUIThread,
226 runner_,
227 base::Bind(&EmptyStatusCallback)));
228
158 BrowserThread::PostTask( 229 BrowserThread::PostTask(
159 BrowserThread::UI, 230 BrowserThread::UI,
160 FROM_HERE, 231 FROM_HERE,
161 base::Bind(&CloseFileOnUIThread, file_system_, file_handle_)); 232 base::Bind(&OperationRunner::CloseFileOnUIThread, runner_));
162 } 233 }
163 234
164 void FileStreamReader::Initialize( 235 void FileStreamReader::Initialize(
165 const base::Closure& pending_closure, 236 const base::Closure& pending_closure,
166 const net::Int64CompletionCallback& error_callback) { 237 const net::Int64CompletionCallback& error_callback) {
167 DCHECK_EQ(NOT_INITIALIZED, state_); 238 DCHECK_EQ(NOT_INITIALIZED, state_);
168 state_ = INITIALIZING; 239 state_ = INITIALIZING;
169 240
170 BrowserThread::PostTask( 241 BrowserThread::PostTask(
171 BrowserThread::UI, 242 BrowserThread::UI,
172 FROM_HERE, 243 FROM_HERE,
173 base::Bind(&OpenFileOnUIThread, 244 base::Bind(&OperationRunner::OpenFileOnUIThread,
245 runner_,
174 url_, 246 url_,
175 base::Bind(&OnOpenFileCompletedOnUIThread, 247 base::Bind(&FileStreamReader::OnOpenFileCompleted,
176 base::Bind(&FileStreamReader::OnOpenFileCompleted, 248 weak_ptr_factory_.GetWeakPtr(),
177 weak_ptr_factory_.GetWeakPtr(), 249 pending_closure,
178 pending_closure, 250 error_callback)));
179 error_callback))));
180 } 251 }
181 252
182 void FileStreamReader::OnOpenFileCompleted( 253 void FileStreamReader::OnOpenFileCompleted(
183 const base::Closure& pending_closure, 254 const base::Closure& pending_closure,
184 const net::Int64CompletionCallback& error_callback, 255 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) { 256 base::File::Error result) {
189 DCHECK_CURRENTLY_ON(BrowserThread::IO); 257 DCHECK_CURRENTLY_ON(BrowserThread::IO);
190 DCHECK_EQ(INITIALIZING, state_); 258 DCHECK_EQ(INITIALIZING, state_);
191 259
192 // In case of an error, return immediately using the |error_callback| of the 260 // In case of an error, return immediately using the |error_callback| of the
193 // Read() or GetLength() pending request. 261 // Read() or GetLength() pending request.
194 if (result != base::File::FILE_OK) { 262 if (result != base::File::FILE_OK) {
195 state_ = FAILED; 263 state_ = FAILED;
196 error_callback.Run(net::FileErrorToNetError(result)); 264 error_callback.Run(net::FileErrorToNetError(result));
197 return; 265 return;
198 } 266 }
199 267
200 file_system_ = file_system; 268 DCHECK_EQ(base::File::FILE_OK, result);
201 file_path_ = file_path;
202 file_handle_ = file_handle;
203 DCHECK_LT(0, file_handle);
204 269
205 // Verify the last modification time. 270 // Verify the last modification time.
206 BrowserThread::PostTask( 271 BrowserThread::PostTask(
207 BrowserThread::UI, 272 BrowserThread::UI,
208 FROM_HERE, 273 FROM_HERE,
209 base::Bind(&GetMetadataOnUIThread, 274 base::Bind(&OperationRunner::GetMetadataOnUIThread,
210 file_system_, 275 runner_,
211 file_path_, 276 base::Bind(&FileStreamReader::OnInitializeCompleted,
212 base::Bind(&OnGetMetadataReceivedOnUIThread, 277 weak_ptr_factory_.GetWeakPtr(),
213 base::Bind(&FileStreamReader::OnInitializeCompleted, 278 pending_closure,
214 weak_ptr_factory_.GetWeakPtr(), 279 error_callback)));
215 pending_closure,
216 error_callback))));
217 } 280 }
218 281
219 void FileStreamReader::OnInitializeCompleted( 282 void FileStreamReader::OnInitializeCompleted(
220 const base::Closure& pending_closure, 283 const base::Closure& pending_closure,
221 const net::Int64CompletionCallback& error_callback, 284 const net::Int64CompletionCallback& error_callback,
222 const EntryMetadata& metadata, 285 const EntryMetadata& metadata,
223 base::File::Error result) { 286 base::File::Error result) {
224 DCHECK_CURRENTLY_ON(BrowserThread::IO); 287 DCHECK_CURRENTLY_ON(BrowserThread::IO);
225 DCHECK_EQ(INITIALIZING, state_); 288 DCHECK_EQ(INITIALIZING, state_);
226 289
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
334 scoped_refptr<net::IOBuffer> buffer, 397 scoped_refptr<net::IOBuffer> buffer,
335 int buffer_length, 398 int buffer_length,
336 const net::CompletionCallback& callback) { 399 const net::CompletionCallback& callback) {
337 DCHECK_CURRENTLY_ON(BrowserThread::IO); 400 DCHECK_CURRENTLY_ON(BrowserThread::IO);
338 DCHECK_EQ(INITIALIZED, state_); 401 DCHECK_EQ(INITIALIZED, state_);
339 402
340 current_length_ = 0; 403 current_length_ = 0;
341 BrowserThread::PostTask( 404 BrowserThread::PostTask(
342 BrowserThread::UI, 405 BrowserThread::UI,
343 FROM_HERE, 406 FROM_HERE,
344 base::Bind(&ReadFileOnUIThread, 407 base::Bind(&OperationRunner::ReadFileOnUIThread,
345 file_system_, 408 runner_,
346 file_handle_,
347 buffer, 409 buffer,
348 current_offset_, 410 current_offset_,
349 buffer_length, 411 buffer_length,
350 base::Bind(&OnReadChunkReceivedOnUIThread, 412 base::Bind(&FileStreamReader::OnReadChunkReceived,
351 base::Bind(&FileStreamReader::OnReadChunkReceived, 413 weak_ptr_factory_.GetWeakPtr(),
352 weak_ptr_factory_.GetWeakPtr(), 414 callback)));
353 callback))));
354 } 415 }
355 416
356 void FileStreamReader::GetLengthAfterInitialized( 417 void FileStreamReader::GetLengthAfterInitialized(
357 const net::Int64CompletionCallback& callback) { 418 const net::Int64CompletionCallback& callback) {
358 DCHECK_CURRENTLY_ON(BrowserThread::IO); 419 DCHECK_CURRENTLY_ON(BrowserThread::IO);
359 DCHECK_EQ(INITIALIZED, state_); 420 DCHECK_EQ(INITIALIZED, state_);
360 421
361 BrowserThread::PostTask( 422 BrowserThread::PostTask(
362 BrowserThread::UI, 423 BrowserThread::UI,
363 FROM_HERE, 424 FROM_HERE,
364 base::Bind( 425 base::Bind(
365 &GetMetadataOnUIThread, 426 &OperationRunner::GetMetadataOnUIThread,
366 file_system_, 427 runner_,
367 file_path_, 428 base::Bind(&FileStreamReader::OnGetMetadataForGetLengthReceived,
368 base::Bind( 429 weak_ptr_factory_.GetWeakPtr(),
369 &OnGetMetadataReceivedOnUIThread, 430 callback)));
370 base::Bind(&FileStreamReader::OnGetMetadataForGetLengthReceived,
371 weak_ptr_factory_.GetWeakPtr(),
372 callback))));
373 } 431 }
374 432
375 void FileStreamReader::OnReadChunkReceived( 433 void FileStreamReader::OnReadChunkReceived(
376 const net::CompletionCallback& callback, 434 const net::CompletionCallback& callback,
377 int chunk_length, 435 int chunk_length,
378 bool has_more, 436 bool has_more,
379 base::File::Error result) { 437 base::File::Error result) {
380 DCHECK_CURRENTLY_ON(BrowserThread::IO); 438 DCHECK_CURRENTLY_ON(BrowserThread::IO);
381 DCHECK_EQ(INITIALIZED, state_); 439 DCHECK_EQ(INITIALIZED, state_);
382 440
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
422 callback.Run(net::ERR_UPLOAD_FILE_CHANGED); 480 callback.Run(net::ERR_UPLOAD_FILE_CHANGED);
423 return; 481 return;
424 } 482 }
425 483
426 DCHECK_EQ(base::File::FILE_OK, result); 484 DCHECK_EQ(base::File::FILE_OK, result);
427 callback.Run(metadata.size); 485 callback.Run(metadata.size);
428 } 486 }
429 487
430 } // namespace file_system_provider 488 } // namespace file_system_provider
431 } // namespace chromeos 489 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698