OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 "webkit/fileapi/file_system_operation.h" | 5 #include "webkit/fileapi/file_system_operation.h" |
6 | 6 |
7 #include "base/time.h" | 7 #include "base/time.h" |
8 #include "net/url_request/url_request_context.h" | 8 #include "net/url_request/url_request_context.h" |
9 #include "webkit/fileapi/file_system_callback_dispatcher.h" | 9 #include "webkit/fileapi/file_system_callback_dispatcher.h" |
10 #include "webkit/fileapi/file_writer_delegate.h" | 10 #include "webkit/fileapi/file_writer_delegate.h" |
11 | 11 |
12 namespace fileapi { | 12 namespace fileapi { |
13 | 13 |
14 FileSystemOperation::FileSystemOperation( | 14 FileSystemOperation::FileSystemOperation( |
15 FileSystemCallbackDispatcher* dispatcher, | 15 FileSystemCallbackDispatcher* dispatcher, |
16 scoped_refptr<base::MessageLoopProxy> proxy) | 16 scoped_refptr<base::MessageLoopProxy> proxy) |
17 : proxy_(proxy), | 17 : proxy_(proxy), |
18 dispatcher_(dispatcher), | 18 dispatcher_(dispatcher), |
19 callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)), | 19 callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { |
20 cancel_operation_(NULL) { | |
21 DCHECK(dispatcher); | 20 DCHECK(dispatcher); |
22 #ifndef NDEBUG | 21 #ifndef NDEBUG |
23 pending_operation_ = kOperationNone; | 22 pending_operation_ = kOperationNone; |
24 #endif | 23 #endif |
25 } | 24 } |
26 | 25 |
27 FileSystemOperation::~FileSystemOperation() { | 26 FileSystemOperation::~FileSystemOperation() { |
28 if (file_writer_delegate_.get()) | 27 if (file_writer_delegate_.get()) |
29 base::FileUtilProxy::Close(proxy_, file_writer_delegate_->file(), NULL); | 28 base::FileUtilProxy::Close(proxy_, file_writer_delegate_->file(), NULL); |
30 } | 29 } |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
152 callback_factory_.NewCallback( | 151 callback_factory_.NewCallback( |
153 &FileSystemOperation::OnFileOpenedForWrite)); | 152 &FileSystemOperation::OnFileOpenedForWrite)); |
154 } | 153 } |
155 | 154 |
156 void FileSystemOperation::OnFileOpenedForWrite( | 155 void FileSystemOperation::OnFileOpenedForWrite( |
157 base::PlatformFileError rv, | 156 base::PlatformFileError rv, |
158 base::PassPlatformFile file, | 157 base::PassPlatformFile file, |
159 bool created) { | 158 bool created) { |
160 if (base::PLATFORM_FILE_OK != rv) { | 159 if (base::PLATFORM_FILE_OK != rv) { |
161 dispatcher_->DidFail(rv); | 160 dispatcher_->DidFail(rv); |
| 161 delete this; |
162 return; | 162 return; |
163 } | 163 } |
164 file_writer_delegate_->Start(file.ReleaseValue(), blob_request_.get()); | 164 file_writer_delegate_->Start(file.ReleaseValue(), blob_request_.get()); |
165 } | 165 } |
166 | 166 |
167 void FileSystemOperation::Truncate(const FilePath& path, int64 length) { | 167 void FileSystemOperation::Truncate(const FilePath& path, int64 length) { |
168 #ifndef NDEBUG | 168 #ifndef NDEBUG |
169 DCHECK(kOperationNone == pending_operation_); | 169 DCHECK(kOperationNone == pending_operation_); |
170 pending_operation_ = kOperationTruncate; | 170 pending_operation_ = kOperationTruncate; |
171 #endif | 171 #endif |
(...skipping 10 matching lines...) Expand all Loading... |
182 pending_operation_ = kOperationTouchFile; | 182 pending_operation_ = kOperationTouchFile; |
183 #endif | 183 #endif |
184 | 184 |
185 base::FileUtilProxy::Touch( | 185 base::FileUtilProxy::Touch( |
186 proxy_, path, last_access_time, last_modified_time, | 186 proxy_, path, last_access_time, last_modified_time, |
187 callback_factory_.NewCallback(&FileSystemOperation::DidTouchFile)); | 187 callback_factory_.NewCallback(&FileSystemOperation::DidTouchFile)); |
188 } | 188 } |
189 | 189 |
190 // We can only get here on a write or truncate that's not yet completed. | 190 // We can only get here on a write or truncate that's not yet completed. |
191 // We don't support cancelling any other operation at this time. | 191 // We don't support cancelling any other operation at this time. |
192 void FileSystemOperation::Cancel(FileSystemOperation* cancel_operation) { | 192 void FileSystemOperation::Cancel(FileSystemOperation* cancel_operation_ptr) { |
| 193 scoped_ptr<FileSystemOperation> cancel_operation(cancel_operation_ptr); |
193 if (file_writer_delegate_.get()) { | 194 if (file_writer_delegate_.get()) { |
194 #ifndef NDEBUG | 195 #ifndef NDEBUG |
195 DCHECK(kOperationWrite == pending_operation_); | 196 DCHECK(kOperationWrite == pending_operation_); |
196 #endif | 197 #endif |
197 // Writes are done without proxying through FileUtilProxy after the initial | 198 // Writes are done without proxying through FileUtilProxy after the initial |
198 // opening of the PlatformFile. All state changes are done on this thread, | 199 // opening of the PlatformFile. All state changes are done on this thread, |
199 // so we're guaranteed to be able to shut down atomically. We do need to | 200 // so we're guaranteed to be able to shut down atomically. We do need to |
200 // check that the file has been opened [which means the blob_request_ has | 201 // check that the file has been opened [which means the blob_request_ has |
201 // been created], so we know how much we need to do. | 202 // been created], so we know how much we need to do. |
202 if (blob_request_.get()) | 203 if (blob_request_.get()) |
203 // This halts any calls to file_writer_delegate_ from blob_request_. | 204 // This halts any calls to file_writer_delegate_ from blob_request_. |
204 blob_request_->Cancel(); | 205 blob_request_->Cancel(); |
205 | 206 |
206 // This deletes us, and by proxy deletes file_writer_delegate_ if any. | |
207 dispatcher_->DidFail(base::PLATFORM_FILE_ERROR_ABORT); | 207 dispatcher_->DidFail(base::PLATFORM_FILE_ERROR_ABORT); |
208 cancel_operation->dispatcher_->DidSucceed(); | 208 cancel_operation->dispatcher()->DidSucceed(); |
| 209 delete this; |
209 } else { | 210 } else { |
210 #ifndef NDEBUG | 211 #ifndef NDEBUG |
211 DCHECK(kOperationTruncate == pending_operation_); | 212 DCHECK(kOperationTruncate == pending_operation_); |
212 #endif | 213 #endif |
213 // We're cancelling a truncate operation, but we can't actually stop it | 214 // We're cancelling a truncate operation, but we can't actually stop it |
214 // since it's been proxied to another thread. We need to save the | 215 // since it's been proxied to another thread. We need to save the |
215 // cancel_operation so that when the truncate returns, it can see that it's | 216 // cancel_operation so that when the truncate returns, it can see that it's |
216 // been cancelled, report it, and report that the cancel has succeeded. | 217 // been cancelled, report it, and report that the cancel has succeeded. |
217 cancel_operation_ = cancel_operation; | 218 DCHECK(!cancel_operation_.get()); |
| 219 cancel_operation_.swap(cancel_operation); |
218 } | 220 } |
219 } | 221 } |
220 | 222 |
221 void FileSystemOperation::DidEnsureFileExistsExclusive( | 223 void FileSystemOperation::DidEnsureFileExistsExclusive( |
222 base::PlatformFileError rv, bool created) { | 224 base::PlatformFileError rv, bool created) { |
223 if (rv == base::PLATFORM_FILE_OK && !created) | 225 if (rv == base::PLATFORM_FILE_OK && !created) { |
224 dispatcher_->DidFail(base::PLATFORM_FILE_ERROR_EXISTS); | 226 dispatcher_->DidFail(base::PLATFORM_FILE_ERROR_EXISTS); |
225 else | 227 delete this; |
| 228 } else |
226 DidFinishFileOperation(rv); | 229 DidFinishFileOperation(rv); |
227 } | 230 } |
228 | 231 |
229 void FileSystemOperation::DidEnsureFileExistsNonExclusive( | 232 void FileSystemOperation::DidEnsureFileExistsNonExclusive( |
230 base::PlatformFileError rv, bool /* created */) { | 233 base::PlatformFileError rv, bool /* created */) { |
231 DidFinishFileOperation(rv); | 234 DidFinishFileOperation(rv); |
232 } | 235 } |
233 | 236 |
234 void FileSystemOperation::DidFinishFileOperation( | 237 void FileSystemOperation::DidFinishFileOperation( |
235 base::PlatformFileError rv) { | 238 base::PlatformFileError rv) { |
236 if (cancel_operation_) { | 239 if (cancel_operation_.get()) { |
237 #ifndef NDEBUG | 240 #ifndef NDEBUG |
238 DCHECK(kOperationTruncate == pending_operation_); | 241 DCHECK(kOperationTruncate == pending_operation_); |
239 #endif | 242 #endif |
240 FileSystemOperation *cancel_op = cancel_operation_; | 243 |
241 // This call deletes us, so we have to extract cancel_op first. | |
242 dispatcher_->DidFail(base::PLATFORM_FILE_ERROR_ABORT); | 244 dispatcher_->DidFail(base::PLATFORM_FILE_ERROR_ABORT); |
243 cancel_op->dispatcher_->DidSucceed(); | 245 cancel_operation_->dispatcher()->DidSucceed(); |
244 } else if (rv == base::PLATFORM_FILE_OK) { | 246 } else if (rv == base::PLATFORM_FILE_OK) { |
245 dispatcher_->DidSucceed(); | 247 dispatcher_->DidSucceed(); |
246 } else { | 248 } else { |
247 dispatcher_->DidFail(rv); | 249 dispatcher_->DidFail(rv); |
248 } | 250 } |
| 251 delete this; |
249 } | 252 } |
250 | 253 |
251 void FileSystemOperation::DidDirectoryExists( | 254 void FileSystemOperation::DidDirectoryExists( |
252 base::PlatformFileError rv, | 255 base::PlatformFileError rv, |
253 const base::PlatformFileInfo& file_info) { | 256 const base::PlatformFileInfo& file_info) { |
254 if (rv == base::PLATFORM_FILE_OK) { | 257 if (rv == base::PLATFORM_FILE_OK) { |
255 if (file_info.is_directory) | 258 if (file_info.is_directory) |
256 dispatcher_->DidSucceed(); | 259 dispatcher_->DidSucceed(); |
257 else | 260 else |
258 dispatcher_->DidFail(base::PLATFORM_FILE_ERROR_FAILED); | 261 dispatcher_->DidFail(base::PLATFORM_FILE_ERROR_FAILED); |
259 } else { | 262 } else { |
260 dispatcher_->DidFail(rv); | 263 dispatcher_->DidFail(rv); |
261 } | 264 } |
| 265 delete this; |
262 } | 266 } |
263 | 267 |
264 void FileSystemOperation::DidFileExists( | 268 void FileSystemOperation::DidFileExists( |
265 base::PlatformFileError rv, | 269 base::PlatformFileError rv, |
266 const base::PlatformFileInfo& file_info) { | 270 const base::PlatformFileInfo& file_info) { |
267 if (rv == base::PLATFORM_FILE_OK) { | 271 if (rv == base::PLATFORM_FILE_OK) { |
268 if (file_info.is_directory) | 272 if (file_info.is_directory) |
269 dispatcher_->DidFail(base::PLATFORM_FILE_ERROR_FAILED); | 273 dispatcher_->DidFail(base::PLATFORM_FILE_ERROR_FAILED); |
270 else | 274 else |
271 dispatcher_->DidSucceed(); | 275 dispatcher_->DidSucceed(); |
272 } else { | 276 } else { |
273 dispatcher_->DidFail(rv); | 277 dispatcher_->DidFail(rv); |
274 } | 278 } |
| 279 delete this; |
275 } | 280 } |
276 | 281 |
277 void FileSystemOperation::DidGetMetadata( | 282 void FileSystemOperation::DidGetMetadata( |
278 base::PlatformFileError rv, | 283 base::PlatformFileError rv, |
279 const base::PlatformFileInfo& file_info) { | 284 const base::PlatformFileInfo& file_info) { |
280 if (rv == base::PLATFORM_FILE_OK) | 285 if (rv == base::PLATFORM_FILE_OK) |
281 dispatcher_->DidReadMetadata(file_info); | 286 dispatcher_->DidReadMetadata(file_info); |
282 else | 287 else |
283 dispatcher_->DidFail(rv); | 288 dispatcher_->DidFail(rv); |
| 289 delete this; |
284 } | 290 } |
285 | 291 |
286 void FileSystemOperation::DidReadDirectory( | 292 void FileSystemOperation::DidReadDirectory( |
287 base::PlatformFileError rv, | 293 base::PlatformFileError rv, |
288 const std::vector<base::FileUtilProxy::Entry>& entries) { | 294 const std::vector<base::FileUtilProxy::Entry>& entries) { |
289 if (rv == base::PLATFORM_FILE_OK) | 295 if (rv == base::PLATFORM_FILE_OK) |
290 dispatcher_->DidReadDirectory(entries, false /* has_more */); | 296 dispatcher_->DidReadDirectory(entries, false /* has_more */); |
291 else | 297 else |
292 dispatcher_->DidFail(rv); | 298 dispatcher_->DidFail(rv); |
| 299 delete this; |
293 } | 300 } |
294 | 301 |
295 void FileSystemOperation::DidWrite( | 302 void FileSystemOperation::DidWrite( |
296 base::PlatformFileError rv, | 303 base::PlatformFileError rv, |
297 int64 bytes, | 304 int64 bytes, |
298 bool complete) { | 305 bool complete) { |
299 if (rv == base::PLATFORM_FILE_OK) | 306 if (rv == base::PLATFORM_FILE_OK) |
300 dispatcher_->DidWrite(bytes, complete); | 307 dispatcher_->DidWrite(bytes, complete); |
301 else | 308 else |
302 dispatcher_->DidFail(rv); | 309 dispatcher_->DidFail(rv); |
| 310 if (complete || rv != base::PLATFORM_FILE_OK) |
| 311 delete this; |
303 } | 312 } |
304 | 313 |
305 void FileSystemOperation::DidTouchFile(base::PlatformFileError rv) { | 314 void FileSystemOperation::DidTouchFile(base::PlatformFileError rv) { |
306 if (rv == base::PLATFORM_FILE_OK) | 315 if (rv == base::PLATFORM_FILE_OK) |
307 dispatcher_->DidSucceed(); | 316 dispatcher_->DidSucceed(); |
308 else | 317 else |
309 dispatcher_->DidFail(rv); | 318 dispatcher_->DidFail(rv); |
| 319 delete this; |
310 } | 320 } |
311 | 321 |
312 } // namespace fileapi | 322 } // namespace fileapi |
OLD | NEW |