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

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 formatting. 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 33 } // namespace
34 // on UI thread.
35 void OpenFileOnUIThread(
36 const fileapi::FileSystemURL& url,
37 const FileStreamReader::OpenFileCompletedCallback& callback) {
38 DCHECK_CURRENTLY_ON(BrowserThread::UI);
39 34
40 util::FileSystemURLParser parser(url); 35 class FileStreamReader::OperationRunner
41 if (!parser.Parse()) { 36 : public base::RefCountedThreadSafe<FileStreamReader::OperationRunner> {
42 callback.Run(base::WeakPtr<ProvidedFileSystemInterface>(), 37 public:
43 base::FilePath(), 38 OperationRunner() : file_handle_(-1) {}
44 0 /* file_handle */, 39
45 base::File::FILE_ERROR_SECURITY); 40 // Opens a file for reading and calls the completion callback. Must be called
46 return; 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));
47 } 63 }
48 64
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. 65 // Closes a file. Ignores result, since it is called from a constructor.
71 // Must be called on UI thread. 66 // Must be called on UI thread.
72 void CloseFileOnUIThread(base::WeakPtr<ProvidedFileSystemInterface> file_system, 67 void CloseFileOnUIThread() {
73 int file_handle) {
74 DCHECK_CURRENTLY_ON(BrowserThread::UI); 68 DCHECK_CURRENTLY_ON(BrowserThread::UI);
hirono 2014/08/22 05:43:47 The indent is wrong from here?
mtomasz 2014/08/22 06:09:50 Done.
75 if (file_system.get()) 69 if (file_system_.get() && file_handle_ != -1) {
76 file_system->CloseFile(file_handle, base::Bind(&EmptyStatusCallback)); 70 file_system_->CloseFile(file_handle_, base::Bind(&EmptyStatusCallback));
71 // Closing a file must not be aborted, since we could end up on files which
72 // are never closed.
73 abort_callback_ = ProvidedFileSystemInterface::AbortCallback();
74 }
77 } 75 }
78 76
79 // Requests reading contents of a file. In case of either success or a failure 77 // 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 78 // |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 79 // 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. 80 // not been changed while reading. Must be called on UI thread.
83 void ReadFileOnUIThread( 81 void ReadFileOnUIThread(
84 base::WeakPtr<ProvidedFileSystemInterface> file_system,
85 int file_handle,
86 scoped_refptr<net::IOBuffer> buffer, 82 scoped_refptr<net::IOBuffer> buffer,
87 int64 offset, 83 int64 offset,
88 int length, 84 int length,
89 const ProvidedFileSystemInterface::ReadChunkReceivedCallback& callback) { 85 const ProvidedFileSystemInterface::ReadChunkReceivedCallback& callback) {
90 DCHECK_CURRENTLY_ON(BrowserThread::UI); 86 DCHECK_CURRENTLY_ON(BrowserThread::UI);
91 87
92 // If the file system got unmounted, then abort the reading operation. 88 // If the file system got unmounted, then abort the reading operation.
93 if (!file_system.get()) { 89 if (!file_system_.get()) {
94 callback.Run(0, false /* has_more */, base::File::FILE_ERROR_ABORT); 90 BrowserThread::PostTask(
91 BrowserThread::IO,
92 FROM_HERE,
93 base::Bind(
94 callback, 0, false /* has_more */, base::File::FILE_ERROR_ABORT));
95 return; 95 return;
96 } 96 }
97 97
98 file_system->ReadFile(file_handle, buffer, offset, length, callback); 98 abort_callback_ = file_system_->ReadFile(
99 } 99 file_handle_,
100 100 buffer,
101 // Forward the completion callback to IO thread. 101 offset,
102 void OnReadChunkReceivedOnUIThread( 102 length,
103 const ProvidedFileSystemInterface::ReadChunkReceivedCallback& 103 base::Bind(
104 chunk_received_callback, 104 &OperationRunner::OnReadFileCompletedOnUIThread, this, 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 } 105 }
114 106
115 // Requests metadata of a file. In case of either succes or a failure, 107 // Requests metadata of a file. In case of either succes or a failure,
116 // |callback is executed. Must be called on UI thread. 108 // |callback is executed. Must be called on UI thread.
117 void GetMetadataOnUIThread( 109 void GetMetadataOnUIThread(
118 base::WeakPtr<ProvidedFileSystemInterface> file_system,
119 const base::FilePath& file_path,
120 const ProvidedFileSystemInterface::GetMetadataCallback& callback) { 110 const ProvidedFileSystemInterface::GetMetadataCallback& callback) {
121 DCHECK_CURRENTLY_ON(BrowserThread::UI); 111 DCHECK_CURRENTLY_ON(BrowserThread::UI);
122 112
123 // If the file system got unmounted, then abort the get length operation. 113 // If the file system got unmounted, then abort the get length operation.
124 if (!file_system.get()) { 114 if (!file_system_.get()) {
125 callback.Run(EntryMetadata(), base::File::FILE_ERROR_ABORT); 115 BrowserThread::PostTask(
116 BrowserThread::IO,
117 FROM_HERE,
118 base::Bind(callback, EntryMetadata(), base::File::FILE_ERROR_ABORT));
126 return; 119 return;
127 } 120 }
128 121
129 file_system->GetMetadata(file_path, callback); 122 abort_callback_ = file_system_->GetMetadata(
123 file_path_,
124 base::Bind(
125 &OperationRunner::OnGetMetadataCompletedOnUIThread, this, callback));
130 } 126 }
131 127
132 // Forward the completion callback to IO thread. 128 // Aborts the most recent operation (if exists), and calls the callback.
133 void OnGetMetadataReceivedOnUIThread( 129 void AbortOnUIThread(const fileapi::AsyncFileUtil::StatusCallback& callback) {
134 const ProvidedFileSystemInterface::GetMetadataCallback& callback, 130 DCHECK_CURRENTLY_ON(BrowserThread::UI);
135 const EntryMetadata& metadata, 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(
145 base::Bind(&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 fileapi::AsyncFileUtil::StatusCallback& callback,
157 int file_handle,
136 base::File::Error result) { 158 base::File::Error result) {
137 DCHECK_CURRENTLY_ON(BrowserThread::UI); 159 DCHECK_CURRENTLY_ON(BrowserThread::UI);
160
161 file_handle_ = file_handle;
138 BrowserThread::PostTask( 162 BrowserThread::PostTask(
139 BrowserThread::IO, FROM_HERE, base::Bind(callback, metadata, result)); 163 BrowserThread::IO, FROM_HERE, base::Bind(callback, result));
140 } 164 }
141 165
142 } // namespace 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 fileapi::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 };
143 206
144 FileStreamReader::FileStreamReader(fileapi::FileSystemContext* context, 207 FileStreamReader::FileStreamReader(fileapi::FileSystemContext* context,
145 const fileapi::FileSystemURL& url, 208 const fileapi::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