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

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

Issue 440653003: [fsp] Add support for aborting running operations. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fixed DCHECKs. 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_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 "chrome/browser/chromeos/file_system_provider/fileapi/provider_async_fi le_util.h" 9 #include "chrome/browser/chromeos/file_system_provider/fileapi/provider_async_fi le_util.h"
10 #include "chrome/browser/chromeos/file_system_provider/mount_path_util.h" 10 #include "chrome/browser/chromeos/file_system_provider/mount_path_util.h"
11 #include "chrome/browser/chromeos/file_system_provider/provided_file_system_inte rface.h" 11 #include "chrome/browser/chromeos/file_system_provider/provided_file_system_inte rface.h"
12 #include "content/public/browser/browser_thread.h" 12 #include "content/public/browser/browser_thread.h"
13 #include "net/base/io_buffer.h" 13 #include "net/base/io_buffer.h"
14 #include "net/base/net_errors.h" 14 #include "net/base/net_errors.h"
15 15
16 using content::BrowserThread; 16 using content::BrowserThread;
17 17
18 namespace chromeos { 18 namespace chromeos {
19 namespace file_system_provider { 19 namespace file_system_provider {
20 namespace { 20 namespace {
21 21
22 // Dicards the callback from CloseFile(). 22 // Dicards the callback from CloseFile().
23 void EmptyStatusCallback(base::File::Error /* result */) { 23 void EmptyStatusCallback(base::File::Error /* result */) {
24 } 24 }
25 25
26 // Opens a file for writing and calls the completion callback. Must be called 26 } // namespace
27 // on UI thread.
28 void OpenFileOnUIThread(
29 const fileapi::FileSystemURL& url,
30 const FileStreamWriter::OpenFileCompletedCallback& callback) {
31 DCHECK_CURRENTLY_ON(BrowserThread::UI);
32 27
33 util::FileSystemURLParser parser(url); 28 class FileStreamWriter::OperationRunner
34 if (!parser.Parse()) { 29 : public base::RefCountedThreadSafe<FileStreamWriter::OperationRunner> {
35 callback.Run(base::WeakPtr<ProvidedFileSystemInterface>(), 30 public:
36 base::FilePath(), 31 OperationRunner() : file_handle_(-1) {}
37 0 /* file_handle */, 32
38 base::File::FILE_ERROR_SECURITY); 33 // Opens a file for writing and calls the completion callback. Must be called
39 return; 34 // on UI thread.
35 void OpenFileOnUIThread(
36 const fileapi::FileSystemURL& url,
37 const fileapi::AsyncFileUtil::StatusCallback& callback) {
38 DCHECK_CURRENTLY_ON(BrowserThread::UI);
39
40 util::FileSystemURLParser parser(url);
41 if (!parser.Parse()) {
42 BrowserThread::PostTask(
43 BrowserThread::IO,
44 FROM_HERE,
45 base::Bind(callback, base::File::FILE_ERROR_SECURITY));
46 return;
47 }
48
49 file_system_ = parser.file_system()->GetWeakPtr();
50 abort_callback_ = parser.file_system()->OpenFile(
51 parser.file_path(),
52 ProvidedFileSystemInterface::OPEN_FILE_MODE_WRITE,
53 base::Bind(
54 &OperationRunner::OnOpenFileCompletedOnUIThread, this, callback));
40 } 55 }
41 56
42 parser.file_system()->OpenFile( 57 // Closes a file. Ignores result, since outlives the caller. Must be called on
43 parser.file_path(), 58 // UI thread.
44 ProvidedFileSystemInterface::OPEN_FILE_MODE_WRITE, 59 void CloseFileOnUIThread() {
45 base::Bind( 60 DCHECK_CURRENTLY_ON(BrowserThread::UI);
46 callback, parser.file_system()->GetWeakPtr(), parser.file_path())); 61 if (file_system_.get() && file_handle_ != -1) {
47 } 62 abort_callback_ = file_system_->CloseFile(
48 63 file_handle_, base::Bind(&EmptyStatusCallback));
49 // Forwards results of calling OpenFileOnUIThread back to the IO thread. 64 }
50 void OnOpenFileCompletedOnUIThread(
51 const FileStreamWriter::OpenFileCompletedCallback& callback,
52 base::WeakPtr<ProvidedFileSystemInterface> file_system,
53 const base::FilePath& file_path,
54 int file_handle,
55 base::File::Error result) {
56 DCHECK_CURRENTLY_ON(BrowserThread::UI);
57 BrowserThread::PostTask(
58 BrowserThread::IO,
59 FROM_HERE,
60 base::Bind(callback, file_system, file_path, file_handle, result));
61 }
62
63 // Closes a file. Ignores result, since it is called from a constructor.
64 // Must be called on UI thread.
65 void CloseFileOnUIThread(base::WeakPtr<ProvidedFileSystemInterface> file_system,
66 int file_handle) {
67 DCHECK_CURRENTLY_ON(BrowserThread::UI);
68 if (file_system.get())
69 file_system->CloseFile(file_handle, base::Bind(&EmptyStatusCallback));
70 }
71
72 // Requests writing bytes to the file. In case of either success or a failure
73 // |callback| is executed. Must be called on UI thread.
74 void WriteFileOnUIThread(
75 base::WeakPtr<ProvidedFileSystemInterface> file_system,
76 int file_handle,
77 scoped_refptr<net::IOBuffer> buffer,
78 int64 offset,
79 int length,
80 const fileapi::AsyncFileUtil::StatusCallback& callback) {
81 DCHECK_CURRENTLY_ON(BrowserThread::UI);
82
83 // If the file system got unmounted, then abort the writing operation.
84 if (!file_system.get()) {
85 callback.Run(base::File::FILE_ERROR_ABORT);
86 return;
87 } 65 }
88 66
89 file_system->WriteFile(file_handle, buffer, offset, length, callback); 67 // Requests writing bytes to the file. In case of either success or a failure
90 } 68 // |callback| is executed. Must be called on UI thread.
69 void WriteFileOnUIThread(
70 scoped_refptr<net::IOBuffer> buffer,
71 int64 offset,
72 int length,
73 const fileapi::AsyncFileUtil::StatusCallback& callback) {
74 DCHECK_CURRENTLY_ON(BrowserThread::UI);
91 75
92 // Forward the completion callback to IO thread. 76 // If the file system got unmounted, then abort the writing operation.
93 void OnWriteFileCompletedOnUIThread( 77 if (!file_system_.get()) {
94 const fileapi::AsyncFileUtil::StatusCallback& callback, 78 BrowserThread::PostTask(
95 base::File::Error result) { 79 BrowserThread::IO,
96 DCHECK_CURRENTLY_ON(BrowserThread::UI); 80 FROM_HERE,
97 BrowserThread::PostTask( 81 base::Bind(callback, base::File::FILE_ERROR_ABORT));
98 BrowserThread::IO, FROM_HERE, base::Bind(callback, result)); 82 return;
99 } 83 }
100 84
101 } // namespace 85 abort_callback_ = file_system_->WriteFile(
86 file_handle_,
87 buffer,
88 offset,
89 length,
90 base::Bind(
91 &OperationRunner::OnWriteFileCompletedOnUIThread, this, callback));
92 }
93
94 // Aborts the most recent operation (if exists), and calls the callback.
95 void AbortOnUIThread(const fileapi::AsyncFileUtil::StatusCallback& callback) {
96 DCHECK_CURRENTLY_ON(BrowserThread::UI);
97
98 if (abort_callback_.is_null()) {
99 // No operation on the file system being performed. At most a callback
100 // call, which will be discarded.
101 BrowserThread::PostTask(
102 BrowserThread::IO,
103 FROM_HERE,
104 base::Bind(callback, base::File::FILE_ERROR_ABORT));
105 return;
106 }
107
108 const ProvidedFileSystemInterface::AbortCallback abort_callback =
109 abort_callback_;
110 abort_callback_ = ProvidedFileSystemInterface::AbortCallback();
111 abort_callback.Run(base::Bind(
112 &OperationRunner::OnAbortCompletedOnUIThread, this, callback));
113 }
114
115 private:
116 friend class base::RefCountedThreadSafe<OperationRunner>;
117
118 virtual ~OperationRunner() {}
119
120 // Remembers a file handle for further operations and forwards the result to
121 // the IO thread.
122 void OnOpenFileCompletedOnUIThread(
123 const fileapi::AsyncFileUtil::StatusCallback& callback,
124 int file_handle,
125 base::File::Error result) {
126 DCHECK_CURRENTLY_ON(BrowserThread::UI);
127
128 file_handle_ = file_handle;
129 BrowserThread::PostTask(
130 BrowserThread::IO, FROM_HERE, base::Bind(callback, result));
131 }
132
133 // Forwards a response of writing to a file to the IO thread.
134 void OnWriteFileCompletedOnUIThread(
135 const fileapi::AsyncFileUtil::StatusCallback& callback,
136 base::File::Error result) {
137 DCHECK_CURRENTLY_ON(BrowserThread::UI);
138 BrowserThread::PostTask(
139 BrowserThread::IO, FROM_HERE, base::Bind(callback, result));
140 }
141
142 // Forwards a response of aborting an operation to the IO thread.
143 void OnAbortCompletedOnUIThread(
144 const fileapi::AsyncFileUtil::StatusCallback& callback,
145 base::File::Error result) {
146 DCHECK_CURRENTLY_ON(BrowserThread::UI);
147 BrowserThread::PostTask(
148 BrowserThread::IO, FROM_HERE, base::Bind(callback, result));
149 }
150
151 ProvidedFileSystemInterface::AbortCallback abort_callback_;
152 base::WeakPtr<ProvidedFileSystemInterface> file_system_;
153 int file_handle_;
154
155 DISALLOW_COPY_AND_ASSIGN(OperationRunner);
156 };
102 157
103 FileStreamWriter::FileStreamWriter(const fileapi::FileSystemURL& url, 158 FileStreamWriter::FileStreamWriter(const fileapi::FileSystemURL& url,
104 int64 initial_offset) 159 int64 initial_offset)
105 : url_(url), 160 : url_(url),
106 current_offset_(initial_offset), 161 current_offset_(initial_offset),
162 runner_(new OperationRunner),
107 state_(NOT_INITIALIZED), 163 state_(NOT_INITIALIZED),
108 file_handle_(0),
109 weak_ptr_factory_(this) { 164 weak_ptr_factory_(this) {
110 } 165 }
111 166
112 FileStreamWriter::~FileStreamWriter() { 167 FileStreamWriter::~FileStreamWriter() {
113 BrowserThread::PostTask( 168 BrowserThread::PostTask(
114 BrowserThread::UI, 169 BrowserThread::UI,
115 FROM_HERE, 170 FROM_HERE,
116 base::Bind(&CloseFileOnUIThread, file_system_, file_handle_)); 171 base::Bind(&OperationRunner::CloseFileOnUIThread, runner_));
117 } 172 }
118 173
119 void FileStreamWriter::Initialize( 174 void FileStreamWriter::Initialize(
120 const base::Closure& pending_closure, 175 const base::Closure& pending_closure,
121 const net::CompletionCallback& error_callback) { 176 const net::CompletionCallback& error_callback) {
177 DCHECK_CURRENTLY_ON(BrowserThread::IO);
122 DCHECK_EQ(NOT_INITIALIZED, state_); 178 DCHECK_EQ(NOT_INITIALIZED, state_);
123 state_ = INITIALIZING; 179 state_ = INITIALIZING;
124 180
125 BrowserThread::PostTask( 181 BrowserThread::PostTask(
126 BrowserThread::UI, 182 BrowserThread::UI,
127 FROM_HERE, 183 FROM_HERE,
128 base::Bind(&OpenFileOnUIThread, 184 base::Bind(&OperationRunner::OpenFileOnUIThread,
185 runner_,
129 url_, 186 url_,
130 base::Bind(&OnOpenFileCompletedOnUIThread, 187 base::Bind(&FileStreamWriter::OnOpenFileCompleted,
131 base::Bind(&FileStreamWriter::OnOpenFileCompleted, 188 weak_ptr_factory_.GetWeakPtr(),
132 weak_ptr_factory_.GetWeakPtr(), 189 pending_closure,
133 pending_closure, 190 error_callback)));
134 error_callback))));
135 } 191 }
136 192
137 void FileStreamWriter::OnOpenFileCompleted( 193 void FileStreamWriter::OnOpenFileCompleted(
138 const base::Closure& pending_closure, 194 const base::Closure& pending_closure,
139 const net::CompletionCallback& error_callback, 195 const net::CompletionCallback& error_callback,
140 base::WeakPtr<ProvidedFileSystemInterface> file_system,
141 const base::FilePath& file_path,
142 int file_handle,
143 base::File::Error result) { 196 base::File::Error result) {
144 DCHECK_CURRENTLY_ON(BrowserThread::IO); 197 DCHECK_CURRENTLY_ON(BrowserThread::IO);
145 DCHECK_EQ(INITIALIZING, state_); 198 DCHECK_EQ(INITIALIZING, state_);
146 199
147 // In case of an error, return immediately using the |error_callback| of the 200 // In case of an error, return immediately using the |error_callback| of the
148 // Write() pending request. 201 // Write() pending request.
149 if (result != base::File::FILE_OK) { 202 if (result != base::File::FILE_OK) {
150 state_ = FAILED; 203 state_ = FAILED;
151 error_callback.Run(net::FileErrorToNetError(result)); 204 error_callback.Run(net::FileErrorToNetError(result));
152 return; 205 return;
153 } 206 }
154 207
155 file_system_ = file_system;
156 file_path_ = file_path;
157 file_handle_ = file_handle;
158 DCHECK_LT(0, file_handle);
159 DCHECK_EQ(base::File::FILE_OK, result); 208 DCHECK_EQ(base::File::FILE_OK, result);
160 state_ = INITIALIZED; 209 state_ = INITIALIZED;
161 210
162 // Run the task waiting for the initialization to be completed. 211 // Run the task waiting for the initialization to be completed.
163 pending_closure.Run(); 212 pending_closure.Run();
164 } 213 }
165 214
166 int FileStreamWriter::Write(net::IOBuffer* buffer, 215 int FileStreamWriter::Write(net::IOBuffer* buffer,
167 int buffer_length, 216 int buffer_length,
168 const net::CompletionCallback& callback) { 217 const net::CompletionCallback& callback) {
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
202 251
203 case FAILED: 252 case FAILED:
204 NOTREACHED(); 253 NOTREACHED();
205 break; 254 break;
206 } 255 }
207 256
208 return net::ERR_IO_PENDING; 257 return net::ERR_IO_PENDING;
209 } 258 }
210 259
211 int FileStreamWriter::Cancel(const net::CompletionCallback& callback) { 260 int FileStreamWriter::Cancel(const net::CompletionCallback& callback) {
212 NOTIMPLEMENTED(); 261 DCHECK_CURRENTLY_ON(BrowserThread::IO);
213 return net::ERR_FAILED; 262
263 BrowserThread::PostTask(
264 BrowserThread::UI,
265 FROM_HERE,
266 base::Bind(&OperationRunner::AbortOnUIThread,
267 runner_,
268 base::Bind(&FileStreamWriter::OnAbortCompleted,
269 weak_ptr_factory_.GetWeakPtr(),
270 callback)));
271 return net::ERR_IO_PENDING;
214 } 272 }
215 273
216 int FileStreamWriter::Flush(const net::CompletionCallback& callback) { 274 int FileStreamWriter::Flush(const net::CompletionCallback& callback) {
217 if (state_ != INITIALIZED) 275 if (state_ != INITIALIZED)
218 return net::ERR_FAILED; 276 return net::ERR_FAILED;
219 277
220 return net::OK; 278 return net::OK;
221 } 279 }
222 280
223 void FileStreamWriter::OnWriteFileCompleted( 281 void FileStreamWriter::OnWriteFileCompleted(
(...skipping 14 matching lines...) Expand all
238 } 296 }
239 297
240 void FileStreamWriter::OnWriteCompleted(net::CompletionCallback callback, 298 void FileStreamWriter::OnWriteCompleted(net::CompletionCallback callback,
241 int result) { 299 int result) {
242 DCHECK_CURRENTLY_ON(BrowserThread::IO); 300 DCHECK_CURRENTLY_ON(BrowserThread::IO);
243 callback.Run(result); 301 callback.Run(result);
244 TRACE_EVENT_ASYNC_END0( 302 TRACE_EVENT_ASYNC_END0(
245 "file_system_provider", "FileStreamWriter::Write", this); 303 "file_system_provider", "FileStreamWriter::Write", this);
246 } 304 }
247 305
306 void FileStreamWriter::OnAbortCompleted(const net::CompletionCallback& callback,
307 base::File::Error result) {
308 DCHECK_CURRENTLY_ON(BrowserThread::IO);
309
310 if (result != base::File::FILE_OK)
311 state_ = FAILED;
312
313 callback.Run(net::FileErrorToNetError(result));
314 }
315
248 void FileStreamWriter::WriteAfterInitialized( 316 void FileStreamWriter::WriteAfterInitialized(
249 scoped_refptr<net::IOBuffer> buffer, 317 scoped_refptr<net::IOBuffer> buffer,
250 int buffer_length, 318 int buffer_length,
251 const net::CompletionCallback& callback) { 319 const net::CompletionCallback& callback) {
252 DCHECK_CURRENTLY_ON(BrowserThread::IO); 320 DCHECK_CURRENTLY_ON(BrowserThread::IO);
253 DCHECK_EQ(INITIALIZED, state_); 321 DCHECK_EQ(INITIALIZED, state_);
254 322
255 BrowserThread::PostTask( 323 BrowserThread::PostTask(
256 BrowserThread::UI, 324 BrowserThread::UI,
257 FROM_HERE, 325 FROM_HERE,
258 base::Bind(&WriteFileOnUIThread, 326 base::Bind(&OperationRunner::WriteFileOnUIThread,
259 file_system_, 327 runner_,
260 file_handle_,
261 buffer, 328 buffer,
262 current_offset_, 329 current_offset_,
263 buffer_length, 330 buffer_length,
264 base::Bind(&OnWriteFileCompletedOnUIThread, 331 base::Bind(&FileStreamWriter::OnWriteFileCompleted,
265 base::Bind(&FileStreamWriter::OnWriteFileCompleted, 332 weak_ptr_factory_.GetWeakPtr(),
266 weak_ptr_factory_.GetWeakPtr(), 333 buffer_length,
267 buffer_length, 334 callback)));
268 callback))));
269 } 335 }
270 336
271 } // namespace file_system_provider 337 } // namespace file_system_provider
272 } // namespace chromeos 338 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698