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

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: Cleaned up. 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_ =
86 file_system_->WriteFile(file_handle_, buffer, offset, length, callback);
hirono 2014/08/06 08:33:50 Should we check file_handle_ != -1?
87 }
88
89 // Aborts the most recent operation (if exists), and calls the callback.
90 void AbortOnUIThread(const fileapi::AsyncFileUtil::StatusCallback& callback) {
91 if (abort_callback_.is_null()) {
92 // No operation on the file system being performed. At most a callback
93 // call, which will be discarded.
94 callback.Run(base::File::FILE_OK);
95 return;
96 }
97
98 const ProvidedFileSystemInterface::AbortCallback abort_callback =
99 abort_callback_;
100 abort_callback_ = ProvidedFileSystemInterface::AbortCallback();
101 abort_callback.Run(callback);
102 }
103
104 private:
105 friend class base::RefCountedThreadSafe<OperationRunner>;
106
107 virtual ~OperationRunner() {}
108
109 // Remembers a file handle for further operations and forwards the result to
110 // the IO thread.
111 void OnOpenFileCompletedOnUIThread(
112 const fileapi::AsyncFileUtil::StatusCallback& callback,
113 int file_handle,
114 base::File::Error result) {
115 file_handle_ = file_handle;
116 BrowserThread::PostTask(
117 BrowserThread::IO, FROM_HERE, base::Bind(callback, result));
118 }
119
120 ProvidedFileSystemInterface::AbortCallback abort_callback_;
121 base::WeakPtr<ProvidedFileSystemInterface> file_system_;
122 int file_handle_;
123
124 DISALLOW_COPY_AND_ASSIGN(OperationRunner);
125 };
102 126
103 FileStreamWriter::FileStreamWriter(const fileapi::FileSystemURL& url, 127 FileStreamWriter::FileStreamWriter(const fileapi::FileSystemURL& url,
104 int64 initial_offset) 128 int64 initial_offset)
105 : url_(url), 129 : url_(url),
106 current_offset_(initial_offset), 130 current_offset_(initial_offset),
131 runner_(new OperationRunner),
107 state_(NOT_INITIALIZED), 132 state_(NOT_INITIALIZED),
108 file_handle_(0),
109 weak_ptr_factory_(this) { 133 weak_ptr_factory_(this) {
110 } 134 }
111 135
112 FileStreamWriter::~FileStreamWriter() { 136 FileStreamWriter::~FileStreamWriter() {
113 BrowserThread::PostTask( 137 BrowserThread::PostTask(
114 BrowserThread::UI, 138 BrowserThread::UI,
115 FROM_HERE, 139 FROM_HERE,
116 base::Bind(&CloseFileOnUIThread, file_system_, file_handle_)); 140 base::Bind(&OperationRunner::CloseFileOnUIThread, runner_));
117 } 141 }
118 142
119 void FileStreamWriter::Initialize( 143 void FileStreamWriter::Initialize(
120 const base::Closure& pending_closure, 144 const base::Closure& pending_closure,
121 const net::CompletionCallback& error_callback) { 145 const net::CompletionCallback& error_callback) {
122 DCHECK_EQ(NOT_INITIALIZED, state_); 146 DCHECK_EQ(NOT_INITIALIZED, state_);
123 state_ = INITIALIZING; 147 state_ = INITIALIZING;
124 148
125 BrowserThread::PostTask( 149 BrowserThread::PostTask(
126 BrowserThread::UI, 150 BrowserThread::UI,
127 FROM_HERE, 151 FROM_HERE,
128 base::Bind(&OpenFileOnUIThread, 152 base::Bind(&OperationRunner::OpenFileOnUIThread,
153 runner_,
129 url_, 154 url_,
130 base::Bind(&OnOpenFileCompletedOnUIThread, 155 base::Bind(&FileStreamWriter::OnOpenFileCompleted,
131 base::Bind(&FileStreamWriter::OnOpenFileCompleted, 156 weak_ptr_factory_.GetWeakPtr(),
132 weak_ptr_factory_.GetWeakPtr(), 157 pending_closure,
133 pending_closure, 158 error_callback)));
134 error_callback))));
135 } 159 }
136 160
137 void FileStreamWriter::OnOpenFileCompleted( 161 void FileStreamWriter::OnOpenFileCompleted(
138 const base::Closure& pending_closure, 162 const base::Closure& pending_closure,
139 const net::CompletionCallback& error_callback, 163 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) { 164 base::File::Error result) {
144 DCHECK_CURRENTLY_ON(BrowserThread::IO); 165 DCHECK_CURRENTLY_ON(BrowserThread::IO);
145 DCHECK_EQ(INITIALIZING, state_); 166 DCHECK_EQ(INITIALIZING, state_);
146 167
147 // In case of an error, return immediately using the |error_callback| of the 168 // In case of an error, return immediately using the |error_callback| of the
148 // Write() pending request. 169 // Write() pending request.
149 if (result != base::File::FILE_OK) { 170 if (result != base::File::FILE_OK) {
150 state_ = FAILED; 171 state_ = FAILED;
151 error_callback.Run(net::FileErrorToNetError(result)); 172 error_callback.Run(net::FileErrorToNetError(result));
152 return; 173 return;
153 } 174 }
154 175
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); 176 DCHECK_EQ(base::File::FILE_OK, result);
160 state_ = INITIALIZED; 177 state_ = INITIALIZED;
161 178
162 // Run the task waiting for the initialization to be completed. 179 // Run the task waiting for the initialization to be completed.
163 pending_closure.Run(); 180 pending_closure.Run();
164 } 181 }
165 182
166 int FileStreamWriter::Write(net::IOBuffer* buffer, 183 int FileStreamWriter::Write(net::IOBuffer* buffer,
167 int buffer_length, 184 int buffer_length,
168 const net::CompletionCallback& callback) { 185 const net::CompletionCallback& callback) {
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
202 219
203 case FAILED: 220 case FAILED:
204 NOTREACHED(); 221 NOTREACHED();
205 break; 222 break;
206 } 223 }
207 224
208 return net::ERR_IO_PENDING; 225 return net::ERR_IO_PENDING;
209 } 226 }
210 227
211 int FileStreamWriter::Cancel(const net::CompletionCallback& callback) { 228 int FileStreamWriter::Cancel(const net::CompletionCallback& callback) {
212 NOTIMPLEMENTED(); 229 BrowserThread::PostTask(
213 return net::ERR_FAILED; 230 BrowserThread::UI,
231 FROM_HERE,
232 base::Bind(&OperationRunner::AbortOnUIThread,
233 runner_,
234 base::Bind(&FileStreamWriter::OnAbortCompleted,
235 weak_ptr_factory_.GetWeakPtr(),
236 callback)));
237 return net::ERR_IO_PENDING;
214 } 238 }
215 239
216 int FileStreamWriter::Flush(const net::CompletionCallback& callback) { 240 int FileStreamWriter::Flush(const net::CompletionCallback& callback) {
217 if (state_ != INITIALIZED) 241 if (state_ != INITIALIZED)
218 return net::ERR_FAILED; 242 return net::ERR_FAILED;
219 243
220 return net::OK; 244 return net::OK;
221 } 245 }
222 246
223 void FileStreamWriter::OnWriteFileCompleted( 247 void FileStreamWriter::OnWriteFileCompleted(
(...skipping 14 matching lines...) Expand all
238 } 262 }
239 263
240 void FileStreamWriter::OnWriteCompleted(net::CompletionCallback callback, 264 void FileStreamWriter::OnWriteCompleted(net::CompletionCallback callback,
241 int result) { 265 int result) {
242 DCHECK_CURRENTLY_ON(BrowserThread::IO); 266 DCHECK_CURRENTLY_ON(BrowserThread::IO);
243 callback.Run(result); 267 callback.Run(result);
244 TRACE_EVENT_ASYNC_END0( 268 TRACE_EVENT_ASYNC_END0(
245 "file_system_provider", "FileStreamWriter::Write", this); 269 "file_system_provider", "FileStreamWriter::Write", this);
246 } 270 }
247 271
272 void FileStreamWriter::OnAbortCompleted(const net::CompletionCallback& callback,
273 base::File::Error result) {
274 DCHECK_CURRENTLY_ON(BrowserThread::IO);
275
276 if (result != base::File::FILE_OK)
277 state_ = FAILED;
278
279 callback.Run(net::FileErrorToNetError(result));
280 }
281
248 void FileStreamWriter::WriteAfterInitialized( 282 void FileStreamWriter::WriteAfterInitialized(
249 scoped_refptr<net::IOBuffer> buffer, 283 scoped_refptr<net::IOBuffer> buffer,
250 int buffer_length, 284 int buffer_length,
251 const net::CompletionCallback& callback) { 285 const net::CompletionCallback& callback) {
252 DCHECK_CURRENTLY_ON(BrowserThread::IO); 286 DCHECK_CURRENTLY_ON(BrowserThread::IO);
253 DCHECK_EQ(INITIALIZED, state_); 287 DCHECK_EQ(INITIALIZED, state_);
254 288
255 BrowserThread::PostTask( 289 BrowserThread::PostTask(
256 BrowserThread::UI, 290 BrowserThread::UI,
257 FROM_HERE, 291 FROM_HERE,
258 base::Bind(&WriteFileOnUIThread, 292 base::Bind(&OperationRunner::WriteFileOnUIThread,
259 file_system_, 293 runner_,
260 file_handle_,
261 buffer, 294 buffer,
262 current_offset_, 295 current_offset_,
263 buffer_length, 296 buffer_length,
264 base::Bind(&OnWriteFileCompletedOnUIThread, 297 base::Bind(&FileStreamWriter::OnWriteFileCompleted,
265 base::Bind(&FileStreamWriter::OnWriteFileCompleted, 298 weak_ptr_factory_.GetWeakPtr(),
266 weak_ptr_factory_.GetWeakPtr(), 299 buffer_length,
267 buffer_length, 300 callback)));
268 callback))));
269 } 301 }
270 302
271 } // namespace file_system_provider 303 } // namespace file_system_provider
272 } // namespace chromeos 304 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698