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

Side by Side Diff: webkit/fileapi/file_system_operation.cc

Issue 4821005: Make FileSystemOperation's lifetime more explicit. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: '' Created 10 years, 1 month 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 (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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698