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

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

Issue 845083005: [fsp] Simplify aborting logic. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fixed tests. Created 5 years, 11 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
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_write r.h" 5 #include "chrome/browser/chromeos/file_system_provider/fileapi/file_stream_write r.h"
6 6
7 #include "base/debug/trace_event.h" 7 #include "base/debug/trace_event.h"
8 #include "base/memory/ref_counted.h" 8 #include "base/memory/ref_counted.h"
9 #include "base/thread_task_runner_handle.h" 9 #include "base/thread_task_runner_handle.h"
10 #include "chrome/browser/chromeos/file_system_provider/abort_callback.h" 10 #include "chrome/browser/chromeos/file_system_provider/abort_callback.h"
(...skipping 20 matching lines...) Expand all
31 : public base::RefCountedThreadSafe<FileStreamWriter::OperationRunner> { 31 : public base::RefCountedThreadSafe<FileStreamWriter::OperationRunner> {
32 public: 32 public:
33 OperationRunner() : file_handle_(-1) {} 33 OperationRunner() : file_handle_(-1) {}
34 34
35 // Opens a file for writing and calls the completion callback. Must be called 35 // Opens a file for writing and calls the completion callback. Must be called
36 // on UI thread. 36 // on UI thread.
37 void OpenFileOnUIThread( 37 void OpenFileOnUIThread(
38 const storage::FileSystemURL& url, 38 const storage::FileSystemURL& url,
39 const storage::AsyncFileUtil::StatusCallback& callback) { 39 const storage::AsyncFileUtil::StatusCallback& callback) {
40 DCHECK_CURRENTLY_ON(BrowserThread::UI); 40 DCHECK_CURRENTLY_ON(BrowserThread::UI);
41 DCHECK(abort_callback_.is_null());
41 42
42 util::FileSystemURLParser parser(url); 43 util::FileSystemURLParser parser(url);
43 if (!parser.Parse()) { 44 if (!parser.Parse()) {
44 BrowserThread::PostTask( 45 BrowserThread::PostTask(
45 BrowserThread::IO, 46 BrowserThread::IO,
46 FROM_HERE, 47 FROM_HERE,
47 base::Bind(callback, base::File::FILE_ERROR_SECURITY)); 48 base::Bind(callback, base::File::FILE_ERROR_SECURITY));
48 return; 49 return;
49 } 50 }
50 51
51 file_system_ = parser.file_system()->GetWeakPtr(); 52 file_system_ = parser.file_system()->GetWeakPtr();
52 abort_callback_ = parser.file_system()->OpenFile( 53 abort_callback_ = parser.file_system()->OpenFile(
53 parser.file_path(), 54 parser.file_path(),
54 ProvidedFileSystemInterface::OPEN_FILE_MODE_WRITE, 55 ProvidedFileSystemInterface::OPEN_FILE_MODE_WRITE,
55 base::Bind( 56 base::Bind(
56 &OperationRunner::OnOpenFileCompletedOnUIThread, this, callback)); 57 &OperationRunner::OnOpenFileCompletedOnUIThread, this, callback));
57 } 58 }
58 59
59 // Closes a file. Ignores result, since outlives the caller. Must be called on 60 // Closes a file. Ignores result, since outlives the caller. Must be called on
60 // UI thread. 61 // UI thread.
61 void CloseFileOnUIThread() { 62 void CloseFileOnUIThread() {
62 DCHECK_CURRENTLY_ON(BrowserThread::UI); 63 DCHECK_CURRENTLY_ON(BrowserThread::UI);
64 DCHECK(abort_callback_.is_null());
65
63 if (file_system_.get() && file_handle_ != -1) { 66 if (file_system_.get() && file_handle_ != -1) {
64 // Closing a file must not be aborted, since we could end up on files 67 // Closing a file must not be aborted, since we could end up on files
65 // which are never closed. 68 // which are never closed.
66 file_system_->CloseFile(file_handle_, base::Bind(&EmptyStatusCallback)); 69 file_system_->CloseFile(file_handle_, base::Bind(&EmptyStatusCallback));
67 } 70 }
68 } 71 }
69 72
70 // Requests writing bytes to the file. In case of either success or a failure 73 // Requests writing bytes to the file. In case of either success or a failure
71 // |callback| is executed. Must be called on UI thread. 74 // |callback| is executed. Must be called on UI thread.
72 void WriteFileOnUIThread( 75 void WriteFileOnUIThread(
73 scoped_refptr<net::IOBuffer> buffer, 76 scoped_refptr<net::IOBuffer> buffer,
74 int64 offset, 77 int64 offset,
75 int length, 78 int length,
76 const storage::AsyncFileUtil::StatusCallback& callback) { 79 const storage::AsyncFileUtil::StatusCallback& callback) {
77 DCHECK_CURRENTLY_ON(BrowserThread::UI); 80 DCHECK_CURRENTLY_ON(BrowserThread::UI);
81 DCHECK(abort_callback_.is_null());
78 82
79 // If the file system got unmounted, then abort the writing operation. 83 // If the file system got unmounted, then abort the writing operation.
80 if (!file_system_.get()) { 84 if (!file_system_.get()) {
81 BrowserThread::PostTask( 85 BrowserThread::PostTask(
82 BrowserThread::IO, 86 BrowserThread::IO,
83 FROM_HERE, 87 FROM_HERE,
84 base::Bind(callback, base::File::FILE_ERROR_ABORT)); 88 base::Bind(callback, base::File::FILE_ERROR_ABORT));
85 return; 89 return;
86 } 90 }
87 91
88 abort_callback_ = file_system_->WriteFile( 92 abort_callback_ = file_system_->WriteFile(
89 file_handle_, 93 file_handle_,
90 buffer.get(), 94 buffer.get(),
91 offset, 95 offset,
92 length, 96 length,
93 base::Bind( 97 base::Bind(
94 &OperationRunner::OnWriteFileCompletedOnUIThread, this, callback)); 98 &OperationRunner::OnWriteFileCompletedOnUIThread, this, callback));
95 } 99 }
96 100
97 // Aborts the most recent operation (if exists), and calls the callback. 101 // Aborts the most recent operation (if exists).
98 void AbortOnUIThread(const storage::AsyncFileUtil::StatusCallback& callback) { 102 void AbortOnUIThread() {
99 DCHECK_CURRENTLY_ON(BrowserThread::UI); 103 DCHECK_CURRENTLY_ON(BrowserThread::UI);
100 104 if (abort_callback_.is_null())
101 if (abort_callback_.is_null()) {
102 // No operation to be cancelled. At most a callback call, which will be
103 // discarded.
104 BrowserThread::PostTask(BrowserThread::IO,
105 FROM_HERE,
106 base::Bind(callback, base::File::FILE_OK));
107 return; 105 return;
108 }
109 106
110 const AbortCallback last_abort_callback = abort_callback_; 107 const AbortCallback last_abort_callback = abort_callback_;
111 abort_callback_ = AbortCallback(); 108 abort_callback_ = AbortCallback();
112 last_abort_callback.Run(base::Bind( 109 last_abort_callback.Run();
113 &OperationRunner::OnAbortCompletedOnUIThread, this, callback));
114 } 110 }
115 111
116 private: 112 private:
117 friend class base::RefCountedThreadSafe<OperationRunner>; 113 friend class base::RefCountedThreadSafe<OperationRunner>;
118 114
119 virtual ~OperationRunner() {} 115 virtual ~OperationRunner() {}
120 116
121 // Remembers a file handle for further operations and forwards the result to 117 // Remembers a file handle for further operations and forwards the result to
122 // the IO thread. 118 // the IO thread.
123 void OnOpenFileCompletedOnUIThread( 119 void OnOpenFileCompletedOnUIThread(
124 const storage::AsyncFileUtil::StatusCallback& callback, 120 const storage::AsyncFileUtil::StatusCallback& callback,
125 int file_handle, 121 int file_handle,
126 base::File::Error result) { 122 base::File::Error result) {
127 DCHECK_CURRENTLY_ON(BrowserThread::UI); 123 DCHECK_CURRENTLY_ON(BrowserThread::UI);
128 124
125 abort_callback_ = AbortCallback();
129 if (result == base::File::FILE_OK) 126 if (result == base::File::FILE_OK)
130 file_handle_ = file_handle; 127 file_handle_ = file_handle;
131 128
132 BrowserThread::PostTask( 129 BrowserThread::PostTask(
133 BrowserThread::IO, FROM_HERE, base::Bind(callback, result)); 130 BrowserThread::IO, FROM_HERE, base::Bind(callback, result));
134 } 131 }
135 132
136 // Forwards a response of writing to a file to the IO thread. 133 // Forwards a response of writing to a file to the IO thread.
137 void OnWriteFileCompletedOnUIThread( 134 void OnWriteFileCompletedOnUIThread(
138 const storage::AsyncFileUtil::StatusCallback& callback, 135 const storage::AsyncFileUtil::StatusCallback& callback,
139 base::File::Error result) { 136 base::File::Error result) {
140 DCHECK_CURRENTLY_ON(BrowserThread::UI); 137 DCHECK_CURRENTLY_ON(BrowserThread::UI);
138
139 abort_callback_ = AbortCallback();
141 BrowserThread::PostTask( 140 BrowserThread::PostTask(
142 BrowserThread::IO, FROM_HERE, base::Bind(callback, result)); 141 BrowserThread::IO, FROM_HERE, base::Bind(callback, result));
143 } 142 }
144
145 // Forwards a response of aborting an operation to the IO thread.
146 void OnAbortCompletedOnUIThread(
147 const storage::AsyncFileUtil::StatusCallback& callback,
148 base::File::Error result) {
149 DCHECK_CURRENTLY_ON(BrowserThread::UI);
150 BrowserThread::PostTask(
151 BrowserThread::IO, FROM_HERE, base::Bind(callback, result));
152 }
153 143
154 AbortCallback abort_callback_; 144 AbortCallback abort_callback_;
155 base::WeakPtr<ProvidedFileSystemInterface> file_system_; 145 base::WeakPtr<ProvidedFileSystemInterface> file_system_;
156 int file_handle_; 146 int file_handle_;
157 147
158 DISALLOW_COPY_AND_ASSIGN(OperationRunner); 148 DISALLOW_COPY_AND_ASSIGN(OperationRunner);
159 }; 149 };
160 150
161 FileStreamWriter::FileStreamWriter(const storage::FileSystemURL& url, 151 FileStreamWriter::FileStreamWriter(const storage::FileSystemURL& url,
162 int64 initial_offset) 152 int64 initial_offset)
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
245 break; 235 break;
246 236
247 case INITIALIZED: 237 case INITIALIZED:
248 WriteAfterInitialized(buffer, 238 WriteAfterInitialized(buffer,
249 buffer_length, 239 buffer_length,
250 base::Bind(&FileStreamWriter::OnWriteCompleted, 240 base::Bind(&FileStreamWriter::OnWriteCompleted,
251 weak_ptr_factory_.GetWeakPtr(), 241 weak_ptr_factory_.GetWeakPtr(),
252 callback)); 242 callback));
253 break; 243 break;
254 244
245 case EXECUTING:
255 case FAILED: 246 case FAILED:
256 NOTREACHED(); 247 NOTREACHED();
257 break; 248 break;
258 } 249 }
259 250
260 return net::ERR_IO_PENDING; 251 return net::ERR_IO_PENDING;
261 } 252 }
262 253
263 int FileStreamWriter::Cancel(const net::CompletionCallback& callback) { 254 int FileStreamWriter::Cancel(const net::CompletionCallback& callback) {
264 DCHECK_CURRENTLY_ON(BrowserThread::IO); 255 DCHECK_CURRENTLY_ON(BrowserThread::IO);
265 256
257 if (state_ != INITIALIZING && state_ != EXECUTING) {
258 base::ThreadTaskRunnerHandle::Get()->PostTask(
hirono 2015/01/14 05:36:06 Could you explain why it does not return net::ERR_
mtomasz 2015/01/14 08:55:09 Not a strong reason, but for simplicity both FileS
259 FROM_HERE, base::Bind(callback, net::ERR_UNEXPECTED));
260 return net::ERR_IO_PENDING;
261 }
262
263 // Abort and Optimistically return an OK result code, as the aborting
264 // operation is always forced and can't be cancelled.
266 BrowserThread::PostTask( 265 BrowserThread::PostTask(
267 BrowserThread::UI, 266 BrowserThread::UI, FROM_HERE,
268 FROM_HERE, 267 base::Bind(&OperationRunner::AbortOnUIThread, runner_));
269 base::Bind(&OperationRunner::AbortOnUIThread, 268 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
270 runner_, 269 base::Bind(callback, net::OK));
271 base::Bind(&FileStreamWriter::OnAbortCompleted, 270
272 weak_ptr_factory_.GetWeakPtr(),
273 callback)));
274 return net::ERR_IO_PENDING; 271 return net::ERR_IO_PENDING;
275 } 272 }
276 273
277 int FileStreamWriter::Flush(const net::CompletionCallback& callback) { 274 int FileStreamWriter::Flush(const net::CompletionCallback& callback) {
275 DCHECK_CURRENTLY_ON(BrowserThread::IO);
278 base::ThreadTaskRunnerHandle::Get()->PostTask( 276 base::ThreadTaskRunnerHandle::Get()->PostTask(
279 FROM_HERE, 277 FROM_HERE,
280 base::Bind(callback, state_ == INITIALIZED ? net::OK : net::ERR_FAILED)); 278 base::Bind(callback, state_ == INITIALIZED ? net::OK : net::ERR_FAILED));
281 279
282 return net::ERR_IO_PENDING; 280 return net::ERR_IO_PENDING;
283 } 281 }
284 282
285 void FileStreamWriter::OnWriteFileCompleted( 283 void FileStreamWriter::OnWriteFileCompleted(
286 int buffer_length, 284 int buffer_length,
287 const net::CompletionCallback& callback, 285 const net::CompletionCallback& callback,
288 base::File::Error result) { 286 base::File::Error result) {
289 DCHECK_CURRENTLY_ON(BrowserThread::IO); 287 DCHECK_CURRENTLY_ON(BrowserThread::IO);
290 DCHECK_EQ(INITIALIZED, state_); 288 DCHECK_EQ(EXECUTING, state_);
289 state_ = INITIALIZED;
291 290
292 if (result != base::File::FILE_OK) { 291 if (result != base::File::FILE_OK) {
293 state_ = FAILED; 292 state_ = FAILED;
294 callback.Run(net::FileErrorToNetError(result)); 293 callback.Run(net::FileErrorToNetError(result));
295 return; 294 return;
296 } 295 }
297 296
298 current_offset_ += buffer_length; 297 current_offset_ += buffer_length;
299 callback.Run(buffer_length); 298 callback.Run(buffer_length);
300 } 299 }
301 300
302 void FileStreamWriter::OnWriteCompleted(net::CompletionCallback callback, 301 void FileStreamWriter::OnWriteCompleted(net::CompletionCallback callback,
303 int result) { 302 int result) {
304 DCHECK_CURRENTLY_ON(BrowserThread::IO); 303 DCHECK_CURRENTLY_ON(BrowserThread::IO);
305 callback.Run(result); 304 callback.Run(result);
306 TRACE_EVENT_ASYNC_END0( 305 TRACE_EVENT_ASYNC_END0(
307 "file_system_provider", "FileStreamWriter::Write", this); 306 "file_system_provider", "FileStreamWriter::Write", this);
308 } 307 }
309 308
310 void FileStreamWriter::OnAbortCompleted(const net::CompletionCallback& callback,
311 base::File::Error result) {
312 DCHECK_CURRENTLY_ON(BrowserThread::IO);
313
314 if (result != base::File::FILE_OK)
315 state_ = FAILED;
316
317 callback.Run(net::FileErrorToNetError(result));
318 }
319
320 void FileStreamWriter::WriteAfterInitialized( 309 void FileStreamWriter::WriteAfterInitialized(
321 scoped_refptr<net::IOBuffer> buffer, 310 scoped_refptr<net::IOBuffer> buffer,
322 int buffer_length, 311 int buffer_length,
323 const net::CompletionCallback& callback) { 312 const net::CompletionCallback& callback) {
324 DCHECK_CURRENTLY_ON(BrowserThread::IO); 313 DCHECK_CURRENTLY_ON(BrowserThread::IO);
325 DCHECK_EQ(INITIALIZED, state_); 314 DCHECK_EQ(INITIALIZED, state_);
315 state_ = EXECUTING;
326 316
327 BrowserThread::PostTask( 317 BrowserThread::PostTask(
328 BrowserThread::UI, 318 BrowserThread::UI,
329 FROM_HERE, 319 FROM_HERE,
330 base::Bind(&OperationRunner::WriteFileOnUIThread, 320 base::Bind(&OperationRunner::WriteFileOnUIThread,
331 runner_, 321 runner_,
332 buffer, 322 buffer,
333 current_offset_, 323 current_offset_,
334 buffer_length, 324 buffer_length,
335 base::Bind(&FileStreamWriter::OnWriteFileCompleted, 325 base::Bind(&FileStreamWriter::OnWriteFileCompleted,
336 weak_ptr_factory_.GetWeakPtr(), 326 weak_ptr_factory_.GetWeakPtr(),
337 buffer_length, 327 buffer_length,
338 callback))); 328 callback)));
339 } 329 }
340 330
341 } // namespace file_system_provider 331 } // namespace file_system_provider
342 } // namespace chromeos 332 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698