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 namespace { | |
15 | |
16 // A helper callback dispatcher class to make it easy to control | |
17 // FileSystemOperation's lifetime. Calling any callback methods of this | |
18 // class would delete the corresponding FileSystemOperation. | |
19 class DispatchAndDeleteCallbackWrapper | |
20 : public FileSystemCallbackDispatcher { | |
21 public: | |
22 DispatchAndDeleteCallbackWrapper( | |
23 FileSystemOperation* operation, | |
24 FileSystemCallbackDispatcher* dispatcher) | |
25 : operation_(operation), | |
26 dispatcher_(dispatcher) { } | |
27 | |
28 // Returns the wrapped dispatcher. | |
29 // This would be useful when the caller does not want to delete the operation. | |
30 FileSystemCallbackDispatcher* wrapped() const { return dispatcher_.get(); } | |
31 | |
32 virtual void DidSucceed() { | |
33 dispatcher_->DidSucceed(); | |
34 delete operation_; | |
35 } | |
36 | |
37 virtual void DidReadMetadata(const base::PlatformFileInfo& file_info) { | |
38 dispatcher_->DidReadMetadata(file_info); | |
39 delete operation_; | |
40 } | |
41 | |
42 virtual void DidReadDirectory( | |
43 const std::vector<base::FileUtilProxy::Entry>& entries, | |
44 bool has_more) { | |
45 dispatcher_->DidReadDirectory(entries, has_more); | |
46 delete operation_; | |
47 } | |
48 | |
49 virtual void DidOpenFileSystem(const std::string& name, | |
50 const FilePath& root_path) { | |
51 dispatcher_->DidOpenFileSystem(name, root_path); | |
52 delete operation_; | |
53 } | |
54 | |
55 virtual void DidFail(base::PlatformFileError error_code) { | |
56 dispatcher_->DidFail(error_code); | |
57 delete operation_; | |
58 } | |
59 | |
60 virtual void DidWrite(int64 bytes, bool complete) { | |
61 dispatcher_->DidWrite(bytes, complete); | |
62 if (complete) | |
63 delete operation_; | |
64 } | |
65 | |
66 private: | |
67 FileSystemOperation* operation_; | |
68 scoped_ptr<FileSystemCallbackDispatcher> dispatcher_; | |
69 }; | |
70 | |
71 } // namespace | |
72 | |
14 FileSystemOperation::FileSystemOperation( | 73 FileSystemOperation::FileSystemOperation( |
15 FileSystemCallbackDispatcher* dispatcher, | 74 FileSystemCallbackDispatcher* dispatcher, |
16 scoped_refptr<base::MessageLoopProxy> proxy) | 75 scoped_refptr<base::MessageLoopProxy> proxy) |
17 : proxy_(proxy), | 76 : proxy_(proxy), |
18 dispatcher_(dispatcher), | 77 destructive_dispatcher_( |
78 new DispatchAndDeleteCallbackWrapper( | |
79 ALLOW_THIS_IN_INITIALIZER_LIST(this), dispatcher)), | |
ericu
2010/11/16 19:26:54
This seems a bit odd to me. We're creating a wrap
| |
19 callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)), | 80 callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)), |
20 cancel_operation_(NULL) { | 81 cancel_operation_(NULL) { |
21 DCHECK(dispatcher); | 82 DCHECK(dispatcher); |
22 #ifndef NDEBUG | 83 #ifndef NDEBUG |
23 pending_operation_ = kOperationNone; | 84 pending_operation_ = kOperationNone; |
24 #endif | 85 #endif |
25 } | 86 } |
26 | 87 |
27 FileSystemOperation::~FileSystemOperation() { | 88 FileSystemOperation::~FileSystemOperation() { |
28 if (file_writer_delegate_.get()) | 89 if (file_writer_delegate_.get()) |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
151 base::PLATFORM_FILE_ASYNC, | 212 base::PLATFORM_FILE_ASYNC, |
152 callback_factory_.NewCallback( | 213 callback_factory_.NewCallback( |
153 &FileSystemOperation::OnFileOpenedForWrite)); | 214 &FileSystemOperation::OnFileOpenedForWrite)); |
154 } | 215 } |
155 | 216 |
156 void FileSystemOperation::OnFileOpenedForWrite( | 217 void FileSystemOperation::OnFileOpenedForWrite( |
157 base::PlatformFileError rv, | 218 base::PlatformFileError rv, |
158 base::PassPlatformFile file, | 219 base::PassPlatformFile file, |
159 bool created) { | 220 bool created) { |
160 if (base::PLATFORM_FILE_OK != rv) { | 221 if (base::PLATFORM_FILE_OK != rv) { |
161 dispatcher_->DidFail(rv); | 222 destructive_dispatcher()->DidFail(rv); |
162 return; | 223 return; |
163 } | 224 } |
164 file_writer_delegate_->Start(file.ReleaseValue(), blob_request_.get()); | 225 file_writer_delegate_->Start(file.ReleaseValue(), blob_request_.get()); |
165 } | 226 } |
166 | 227 |
167 void FileSystemOperation::Truncate(const FilePath& path, int64 length) { | 228 void FileSystemOperation::Truncate(const FilePath& path, int64 length) { |
168 #ifndef NDEBUG | 229 #ifndef NDEBUG |
169 DCHECK(kOperationNone == pending_operation_); | 230 DCHECK(kOperationNone == pending_operation_); |
170 pending_operation_ = kOperationTruncate; | 231 pending_operation_ = kOperationTruncate; |
171 #endif | 232 #endif |
(...skipping 25 matching lines...) Expand all Loading... | |
197 // Writes are done without proxying through FileUtilProxy after the initial | 258 // Writes are done without proxying through FileUtilProxy after the initial |
198 // opening of the PlatformFile. All state changes are done on this thread, | 259 // 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 | 260 // 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 | 261 // 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. | 262 // been created], so we know how much we need to do. |
202 if (blob_request_.get()) | 263 if (blob_request_.get()) |
203 // This halts any calls to file_writer_delegate_ from blob_request_. | 264 // This halts any calls to file_writer_delegate_ from blob_request_. |
204 blob_request_->Cancel(); | 265 blob_request_->Cancel(); |
205 | 266 |
206 // This deletes us, and by proxy deletes file_writer_delegate_ if any. | 267 // This deletes us, and by proxy deletes file_writer_delegate_ if any. |
207 dispatcher_->DidFail(base::PLATFORM_FILE_ERROR_ABORT); | 268 destructive_dispatcher()->DidFail(base::PLATFORM_FILE_ERROR_ABORT); |
208 cancel_operation->dispatcher_->DidSucceed(); | 269 cancel_operation->destructive_dispatcher()->DidSucceed(); |
209 } else { | 270 } else { |
210 #ifndef NDEBUG | 271 #ifndef NDEBUG |
211 DCHECK(kOperationTruncate == pending_operation_); | 272 DCHECK(kOperationTruncate == pending_operation_); |
212 #endif | 273 #endif |
213 // We're cancelling a truncate operation, but we can't actually stop it | 274 // 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 | 275 // 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 | 276 // 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. | 277 // been cancelled, report it, and report that the cancel has succeeded. |
278 DCHECK(!cancel_operation_); | |
217 cancel_operation_ = cancel_operation; | 279 cancel_operation_ = cancel_operation; |
218 } | 280 } |
219 } | 281 } |
220 | 282 |
283 FileSystemCallbackDispatcher* | |
284 FileSystemOperation::non_destructive_dispatcher() const { | |
285 return static_cast<DispatchAndDeleteCallbackWrapper*>( | |
286 destructive_dispatcher_.get())->wrapped(); | |
287 } | |
288 | |
221 void FileSystemOperation::DidEnsureFileExistsExclusive( | 289 void FileSystemOperation::DidEnsureFileExistsExclusive( |
222 base::PlatformFileError rv, bool created) { | 290 base::PlatformFileError rv, bool created) { |
223 if (rv == base::PLATFORM_FILE_OK && !created) | 291 if (rv == base::PLATFORM_FILE_OK && !created) { |
224 dispatcher_->DidFail(base::PLATFORM_FILE_ERROR_EXISTS); | 292 destructive_dispatcher()->DidFail(base::PLATFORM_FILE_ERROR_EXISTS); |
225 else | 293 } else |
226 DidFinishFileOperation(rv); | 294 DidFinishFileOperation(rv); |
227 } | 295 } |
228 | 296 |
229 void FileSystemOperation::DidEnsureFileExistsNonExclusive( | 297 void FileSystemOperation::DidEnsureFileExistsNonExclusive( |
230 base::PlatformFileError rv, bool /* created */) { | 298 base::PlatformFileError rv, bool /* created */) { |
231 DidFinishFileOperation(rv); | 299 DidFinishFileOperation(rv); |
232 } | 300 } |
233 | 301 |
234 void FileSystemOperation::DidFinishFileOperation( | 302 void FileSystemOperation::DidFinishFileOperation( |
235 base::PlatformFileError rv) { | 303 base::PlatformFileError rv) { |
236 if (cancel_operation_) { | 304 if (cancel_operation_) { |
237 #ifndef NDEBUG | 305 #ifndef NDEBUG |
238 DCHECK(kOperationTruncate == pending_operation_); | 306 DCHECK(kOperationTruncate == pending_operation_); |
239 #endif | 307 #endif |
240 FileSystemOperation *cancel_op = cancel_operation_; | 308 |
241 // This call deletes us, so we have to extract cancel_op first. | 309 // Call non-destructive dispatcher's method not to delete this instance yet. |
242 dispatcher_->DidFail(base::PLATFORM_FILE_ERROR_ABORT); | 310 non_destructive_dispatcher()->DidFail(base::PLATFORM_FILE_ERROR_ABORT); |
243 cancel_op->dispatcher_->DidSucceed(); | 311 cancel_operation_->destructive_dispatcher()->DidSucceed(); |
312 delete this; | |
244 } else if (rv == base::PLATFORM_FILE_OK) { | 313 } else if (rv == base::PLATFORM_FILE_OK) { |
245 dispatcher_->DidSucceed(); | 314 destructive_dispatcher()->DidSucceed(); |
246 } else { | 315 } else { |
247 dispatcher_->DidFail(rv); | 316 destructive_dispatcher()->DidFail(rv); |
248 } | 317 } |
249 } | 318 } |
250 | 319 |
251 void FileSystemOperation::DidDirectoryExists( | 320 void FileSystemOperation::DidDirectoryExists( |
252 base::PlatformFileError rv, | 321 base::PlatformFileError rv, |
253 const base::PlatformFileInfo& file_info) { | 322 const base::PlatformFileInfo& file_info) { |
254 if (rv == base::PLATFORM_FILE_OK) { | 323 if (rv == base::PLATFORM_FILE_OK) { |
255 if (file_info.is_directory) | 324 if (file_info.is_directory) |
256 dispatcher_->DidSucceed(); | 325 destructive_dispatcher()->DidSucceed(); |
257 else | 326 else |
258 dispatcher_->DidFail(base::PLATFORM_FILE_ERROR_FAILED); | 327 destructive_dispatcher()->DidFail(base::PLATFORM_FILE_ERROR_FAILED); |
259 } else { | 328 } else { |
260 dispatcher_->DidFail(rv); | 329 destructive_dispatcher()->DidFail(rv); |
261 } | 330 } |
262 } | 331 } |
263 | 332 |
264 void FileSystemOperation::DidFileExists( | 333 void FileSystemOperation::DidFileExists( |
265 base::PlatformFileError rv, | 334 base::PlatformFileError rv, |
266 const base::PlatformFileInfo& file_info) { | 335 const base::PlatformFileInfo& file_info) { |
267 if (rv == base::PLATFORM_FILE_OK) { | 336 if (rv == base::PLATFORM_FILE_OK) { |
268 if (file_info.is_directory) | 337 if (file_info.is_directory) |
269 dispatcher_->DidFail(base::PLATFORM_FILE_ERROR_FAILED); | 338 destructive_dispatcher()->DidFail(base::PLATFORM_FILE_ERROR_FAILED); |
270 else | 339 else |
271 dispatcher_->DidSucceed(); | 340 destructive_dispatcher()->DidSucceed(); |
272 } else { | 341 } else { |
273 dispatcher_->DidFail(rv); | 342 destructive_dispatcher()->DidFail(rv); |
274 } | 343 } |
275 } | 344 } |
276 | 345 |
277 void FileSystemOperation::DidGetMetadata( | 346 void FileSystemOperation::DidGetMetadata( |
278 base::PlatformFileError rv, | 347 base::PlatformFileError rv, |
279 const base::PlatformFileInfo& file_info) { | 348 const base::PlatformFileInfo& file_info) { |
280 if (rv == base::PLATFORM_FILE_OK) | 349 if (rv == base::PLATFORM_FILE_OK) |
281 dispatcher_->DidReadMetadata(file_info); | 350 destructive_dispatcher()->DidReadMetadata(file_info); |
282 else | 351 else |
283 dispatcher_->DidFail(rv); | 352 destructive_dispatcher()->DidFail(rv); |
284 } | 353 } |
285 | 354 |
286 void FileSystemOperation::DidReadDirectory( | 355 void FileSystemOperation::DidReadDirectory( |
287 base::PlatformFileError rv, | 356 base::PlatformFileError rv, |
288 const std::vector<base::FileUtilProxy::Entry>& entries) { | 357 const std::vector<base::FileUtilProxy::Entry>& entries) { |
289 if (rv == base::PLATFORM_FILE_OK) | 358 if (rv == base::PLATFORM_FILE_OK) |
290 dispatcher_->DidReadDirectory(entries, false /* has_more */); | 359 destructive_dispatcher()->DidReadDirectory(entries, false /* has_more */); |
291 else | 360 else |
292 dispatcher_->DidFail(rv); | 361 destructive_dispatcher()->DidFail(rv); |
293 } | 362 } |
294 | 363 |
295 void FileSystemOperation::DidWrite( | 364 void FileSystemOperation::DidWrite( |
296 base::PlatformFileError rv, | 365 base::PlatformFileError rv, |
297 int64 bytes, | 366 int64 bytes, |
298 bool complete) { | 367 bool complete) { |
299 if (rv == base::PLATFORM_FILE_OK) | 368 if (rv == base::PLATFORM_FILE_OK) |
300 dispatcher_->DidWrite(bytes, complete); | 369 destructive_dispatcher()->DidWrite(bytes, complete); |
ericu
2010/11/16 19:26:54
Given that we explicitly don't want to delete the
| |
301 else | 370 else |
302 dispatcher_->DidFail(rv); | 371 destructive_dispatcher()->DidFail(rv); |
303 } | 372 } |
304 | 373 |
305 void FileSystemOperation::DidTouchFile(base::PlatformFileError rv) { | 374 void FileSystemOperation::DidTouchFile(base::PlatformFileError rv) { |
306 if (rv == base::PLATFORM_FILE_OK) | 375 if (rv == base::PLATFORM_FILE_OK) |
307 dispatcher_->DidSucceed(); | 376 destructive_dispatcher()->DidSucceed(); |
308 else | 377 else |
309 dispatcher_->DidFail(rv); | 378 destructive_dispatcher()->DidFail(rv); |
310 } | 379 } |
311 | 380 |
312 } // namespace fileapi | 381 } // namespace fileapi |
OLD | NEW |