Include all dupe types (event when value is zero) in scan stats.
[chromium-blink-merge.git] / storage / browser / fileapi / file_system_operation_runner.cc
blob8dc39e6c747c33452a8888b128f5823ac7eed208
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "storage/browser/fileapi/file_system_operation_runner.h"
7 #include "base/bind.h"
8 #include "base/stl_util.h"
9 #include "base/thread_task_runner_handle.h"
10 #include "net/url_request/url_request_context.h"
11 #include "storage/browser/blob/blob_url_request_job_factory.h"
12 #include "storage/browser/blob/shareable_file_reference.h"
13 #include "storage/browser/fileapi/file_observers.h"
14 #include "storage/browser/fileapi/file_stream_writer.h"
15 #include "storage/browser/fileapi/file_system_context.h"
16 #include "storage/browser/fileapi/file_writer_delegate.h"
18 namespace storage {
20 typedef FileSystemOperationRunner::OperationID OperationID;
22 class FileSystemOperationRunner::BeginOperationScoper
23 : public base::SupportsWeakPtr<
24 FileSystemOperationRunner::BeginOperationScoper> {
25 public:
26 BeginOperationScoper() {}
27 private:
28 DISALLOW_COPY_AND_ASSIGN(BeginOperationScoper);
31 FileSystemOperationRunner::OperationHandle::OperationHandle() {}
32 FileSystemOperationRunner::OperationHandle::~OperationHandle() {}
34 FileSystemOperationRunner::~FileSystemOperationRunner() {
37 void FileSystemOperationRunner::Shutdown() {
38 operations_.Clear();
41 OperationID FileSystemOperationRunner::CreateFile(
42 const FileSystemURL& url,
43 bool exclusive,
44 const StatusCallback& callback) {
45 base::File::Error error = base::File::FILE_OK;
46 FileSystemOperation* operation =
47 file_system_context_->CreateFileSystemOperation(url, &error);
49 BeginOperationScoper scope;
50 OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr());
51 if (!operation) {
52 DidFinish(handle, callback, error);
53 return handle.id;
55 PrepareForWrite(handle.id, url);
56 operation->CreateFile(
57 url, exclusive,
58 base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(),
59 handle, callback));
60 return handle.id;
63 OperationID FileSystemOperationRunner::CreateDirectory(
64 const FileSystemURL& url,
65 bool exclusive,
66 bool recursive,
67 const StatusCallback& callback) {
68 base::File::Error error = base::File::FILE_OK;
69 FileSystemOperation* operation =
70 file_system_context_->CreateFileSystemOperation(url, &error);
71 BeginOperationScoper scope;
72 OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr());
73 if (!operation) {
74 DidFinish(handle, callback, error);
75 return handle.id;
77 PrepareForWrite(handle.id, url);
78 operation->CreateDirectory(
79 url, exclusive, recursive,
80 base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(),
81 handle, callback));
82 return handle.id;
85 OperationID FileSystemOperationRunner::Copy(
86 const FileSystemURL& src_url,
87 const FileSystemURL& dest_url,
88 CopyOrMoveOption option,
89 const CopyProgressCallback& progress_callback,
90 const StatusCallback& callback) {
91 base::File::Error error = base::File::FILE_OK;
92 FileSystemOperation* operation =
93 file_system_context_->CreateFileSystemOperation(dest_url, &error);
94 BeginOperationScoper scope;
95 OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr());
96 if (!operation) {
97 DidFinish(handle, callback, error);
98 return handle.id;
100 PrepareForWrite(handle.id, dest_url);
101 PrepareForRead(handle.id, src_url);
102 operation->Copy(
103 src_url, dest_url, option,
104 progress_callback.is_null() ?
105 CopyProgressCallback() :
106 base::Bind(&FileSystemOperationRunner::OnCopyProgress, AsWeakPtr(),
107 handle, progress_callback),
108 base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(),
109 handle, callback));
110 return handle.id;
113 OperationID FileSystemOperationRunner::Move(
114 const FileSystemURL& src_url,
115 const FileSystemURL& dest_url,
116 CopyOrMoveOption option,
117 const StatusCallback& callback) {
118 base::File::Error error = base::File::FILE_OK;
119 FileSystemOperation* operation =
120 file_system_context_->CreateFileSystemOperation(dest_url, &error);
121 BeginOperationScoper scope;
122 OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr());
123 if (!operation) {
124 DidFinish(handle, callback, error);
125 return handle.id;
127 PrepareForWrite(handle.id, dest_url);
128 PrepareForWrite(handle.id, src_url);
129 operation->Move(
130 src_url, dest_url, option,
131 base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(),
132 handle, callback));
133 return handle.id;
136 OperationID FileSystemOperationRunner::DirectoryExists(
137 const FileSystemURL& url,
138 const StatusCallback& callback) {
139 base::File::Error error = base::File::FILE_OK;
140 FileSystemOperation* operation =
141 file_system_context_->CreateFileSystemOperation(url, &error);
142 BeginOperationScoper scope;
143 OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr());
144 if (!operation) {
145 DidFinish(handle, callback, error);
146 return handle.id;
148 PrepareForRead(handle.id, url);
149 operation->DirectoryExists(
150 url,
151 base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(),
152 handle, callback));
153 return handle.id;
156 OperationID FileSystemOperationRunner::FileExists(
157 const FileSystemURL& url,
158 const StatusCallback& callback) {
159 base::File::Error error = base::File::FILE_OK;
160 FileSystemOperation* operation =
161 file_system_context_->CreateFileSystemOperation(url, &error);
162 BeginOperationScoper scope;
163 OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr());
164 if (!operation) {
165 DidFinish(handle, callback, error);
166 return handle.id;
168 PrepareForRead(handle.id, url);
169 operation->FileExists(
170 url,
171 base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(),
172 handle, callback));
173 return handle.id;
176 OperationID FileSystemOperationRunner::GetMetadata(
177 const FileSystemURL& url,
178 const GetMetadataCallback& callback) {
179 base::File::Error error = base::File::FILE_OK;
180 FileSystemOperation* operation =
181 file_system_context_->CreateFileSystemOperation(url, &error);
182 BeginOperationScoper scope;
183 OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr());
184 if (!operation) {
185 DidGetMetadata(handle, callback, error, base::File::Info());
186 return handle.id;
188 PrepareForRead(handle.id, url);
189 operation->GetMetadata(
190 url,
191 base::Bind(&FileSystemOperationRunner::DidGetMetadata, AsWeakPtr(),
192 handle, callback));
193 return handle.id;
196 OperationID FileSystemOperationRunner::ReadDirectory(
197 const FileSystemURL& url,
198 const ReadDirectoryCallback& callback) {
199 base::File::Error error = base::File::FILE_OK;
200 FileSystemOperation* operation =
201 file_system_context_->CreateFileSystemOperation(url, &error);
202 BeginOperationScoper scope;
203 OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr());
204 if (!operation) {
205 DidReadDirectory(handle, callback, error, std::vector<DirectoryEntry>(),
206 false);
207 return handle.id;
209 PrepareForRead(handle.id, url);
210 operation->ReadDirectory(
211 url,
212 base::Bind(&FileSystemOperationRunner::DidReadDirectory, AsWeakPtr(),
213 handle, callback));
214 return handle.id;
217 OperationID FileSystemOperationRunner::Remove(
218 const FileSystemURL& url, bool recursive,
219 const StatusCallback& callback) {
220 base::File::Error error = base::File::FILE_OK;
221 FileSystemOperation* operation =
222 file_system_context_->CreateFileSystemOperation(url, &error);
223 BeginOperationScoper scope;
224 OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr());
225 if (!operation) {
226 DidFinish(handle, callback, error);
227 return handle.id;
229 PrepareForWrite(handle.id, url);
230 operation->Remove(
231 url, recursive,
232 base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(),
233 handle, callback));
234 return handle.id;
237 OperationID FileSystemOperationRunner::Write(
238 const net::URLRequestContext* url_request_context,
239 const FileSystemURL& url,
240 scoped_ptr<storage::BlobDataHandle> blob,
241 int64 offset,
242 const WriteCallback& callback) {
243 base::File::Error error = base::File::FILE_OK;
244 FileSystemOperation* operation =
245 file_system_context_->CreateFileSystemOperation(url, &error);
247 BeginOperationScoper scope;
248 OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr());
249 if (!operation) {
250 DidWrite(handle, callback, error, 0, true);
251 return handle.id;
254 scoped_ptr<FileStreamWriter> writer(
255 file_system_context_->CreateFileStreamWriter(url, offset));
256 if (!writer) {
257 // Write is not supported.
258 DidWrite(handle, callback, base::File::FILE_ERROR_SECURITY, 0, true);
259 return handle.id;
262 scoped_ptr<FileWriterDelegate> writer_delegate(
263 new FileWriterDelegate(writer.Pass(), url.mount_option().flush_policy()));
265 scoped_ptr<net::URLRequest> blob_request(
266 storage::BlobProtocolHandler::CreateBlobRequest(
267 blob.Pass(), url_request_context, writer_delegate.get()));
269 PrepareForWrite(handle.id, url);
270 operation->Write(
271 url, writer_delegate.Pass(), blob_request.Pass(),
272 base::Bind(&FileSystemOperationRunner::DidWrite, AsWeakPtr(),
273 handle, callback));
274 return handle.id;
277 OperationID FileSystemOperationRunner::Truncate(
278 const FileSystemURL& url, int64 length,
279 const StatusCallback& callback) {
280 base::File::Error error = base::File::FILE_OK;
281 FileSystemOperation* operation =
282 file_system_context_->CreateFileSystemOperation(url, &error);
283 BeginOperationScoper scope;
284 OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr());
285 if (!operation) {
286 DidFinish(handle, callback, error);
287 return handle.id;
289 PrepareForWrite(handle.id, url);
290 operation->Truncate(
291 url, length,
292 base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(),
293 handle, callback));
294 return handle.id;
297 void FileSystemOperationRunner::Cancel(
298 OperationID id,
299 const StatusCallback& callback) {
300 if (ContainsKey(finished_operations_, id)) {
301 DCHECK(!ContainsKey(stray_cancel_callbacks_, id));
302 stray_cancel_callbacks_[id] = callback;
303 return;
305 FileSystemOperation* operation = operations_.Lookup(id);
306 if (!operation) {
307 // There is no operation with |id|.
308 callback.Run(base::File::FILE_ERROR_INVALID_OPERATION);
309 return;
311 operation->Cancel(callback);
314 OperationID FileSystemOperationRunner::TouchFile(
315 const FileSystemURL& url,
316 const base::Time& last_access_time,
317 const base::Time& last_modified_time,
318 const StatusCallback& callback) {
319 base::File::Error error = base::File::FILE_OK;
320 FileSystemOperation* operation =
321 file_system_context_->CreateFileSystemOperation(url, &error);
322 BeginOperationScoper scope;
323 OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr());
324 if (!operation) {
325 DidFinish(handle, callback, error);
326 return handle.id;
328 PrepareForWrite(handle.id, url);
329 operation->TouchFile(
330 url, last_access_time, last_modified_time,
331 base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(),
332 handle, callback));
333 return handle.id;
336 OperationID FileSystemOperationRunner::OpenFile(
337 const FileSystemURL& url,
338 int file_flags,
339 const OpenFileCallback& callback) {
340 base::File::Error error = base::File::FILE_OK;
341 FileSystemOperation* operation =
342 file_system_context_->CreateFileSystemOperation(url, &error);
343 BeginOperationScoper scope;
344 OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr());
345 if (!operation) {
346 DidOpenFile(handle, callback, base::File(error), base::Closure());
347 return handle.id;
349 if (file_flags &
350 (base::File::FLAG_CREATE | base::File::FLAG_OPEN_ALWAYS |
351 base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_OPEN_TRUNCATED |
352 base::File::FLAG_WRITE | base::File::FLAG_EXCLUSIVE_WRITE |
353 base::File::FLAG_DELETE_ON_CLOSE |
354 base::File::FLAG_WRITE_ATTRIBUTES)) {
355 PrepareForWrite(handle.id, url);
356 } else {
357 PrepareForRead(handle.id, url);
359 operation->OpenFile(
360 url, file_flags,
361 base::Bind(&FileSystemOperationRunner::DidOpenFile, AsWeakPtr(),
362 handle, callback));
363 return handle.id;
366 OperationID FileSystemOperationRunner::CreateSnapshotFile(
367 const FileSystemURL& url,
368 const SnapshotFileCallback& callback) {
369 base::File::Error error = base::File::FILE_OK;
370 FileSystemOperation* operation =
371 file_system_context_->CreateFileSystemOperation(url, &error);
372 BeginOperationScoper scope;
373 OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr());
374 if (!operation) {
375 DidCreateSnapshot(handle, callback, error, base::File::Info(),
376 base::FilePath(), NULL);
377 return handle.id;
379 PrepareForRead(handle.id, url);
380 operation->CreateSnapshotFile(
381 url,
382 base::Bind(&FileSystemOperationRunner::DidCreateSnapshot, AsWeakPtr(),
383 handle, callback));
384 return handle.id;
387 OperationID FileSystemOperationRunner::CopyInForeignFile(
388 const base::FilePath& src_local_disk_path,
389 const FileSystemURL& dest_url,
390 const StatusCallback& callback) {
391 base::File::Error error = base::File::FILE_OK;
392 FileSystemOperation* operation =
393 file_system_context_->CreateFileSystemOperation(dest_url, &error);
394 BeginOperationScoper scope;
395 OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr());
396 if (!operation) {
397 DidFinish(handle, callback, error);
398 return handle.id;
400 PrepareForWrite(handle.id, dest_url);
401 operation->CopyInForeignFile(
402 src_local_disk_path, dest_url,
403 base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(),
404 handle, callback));
405 return handle.id;
408 OperationID FileSystemOperationRunner::RemoveFile(
409 const FileSystemURL& url,
410 const StatusCallback& callback) {
411 base::File::Error error = base::File::FILE_OK;
412 FileSystemOperation* operation =
413 file_system_context_->CreateFileSystemOperation(url, &error);
414 BeginOperationScoper scope;
415 OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr());
416 if (!operation) {
417 DidFinish(handle, callback, error);
418 return handle.id;
420 PrepareForWrite(handle.id, url);
421 operation->RemoveFile(
422 url,
423 base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(),
424 handle, callback));
425 return handle.id;
428 OperationID FileSystemOperationRunner::RemoveDirectory(
429 const FileSystemURL& url,
430 const StatusCallback& callback) {
431 base::File::Error error = base::File::FILE_OK;
432 FileSystemOperation* operation =
433 file_system_context_->CreateFileSystemOperation(url, &error);
434 BeginOperationScoper scope;
435 OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr());
436 if (!operation) {
437 DidFinish(handle, callback, error);
438 return handle.id;
440 PrepareForWrite(handle.id, url);
441 operation->RemoveDirectory(
442 url,
443 base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(),
444 handle, callback));
445 return handle.id;
448 OperationID FileSystemOperationRunner::CopyFileLocal(
449 const FileSystemURL& src_url,
450 const FileSystemURL& dest_url,
451 CopyOrMoveOption option,
452 const CopyFileProgressCallback& progress_callback,
453 const StatusCallback& callback) {
454 base::File::Error error = base::File::FILE_OK;
455 FileSystemOperation* operation =
456 file_system_context_->CreateFileSystemOperation(src_url, &error);
457 BeginOperationScoper scope;
458 OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr());
459 if (!operation) {
460 DidFinish(handle, callback, error);
461 return handle.id;
463 PrepareForRead(handle.id, src_url);
464 PrepareForWrite(handle.id, dest_url);
465 operation->CopyFileLocal(
466 src_url, dest_url, option, progress_callback,
467 base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(),
468 handle, callback));
469 return handle.id;
472 OperationID FileSystemOperationRunner::MoveFileLocal(
473 const FileSystemURL& src_url,
474 const FileSystemURL& dest_url,
475 CopyOrMoveOption option,
476 const StatusCallback& callback) {
477 base::File::Error error = base::File::FILE_OK;
478 FileSystemOperation* operation =
479 file_system_context_->CreateFileSystemOperation(src_url, &error);
480 BeginOperationScoper scope;
481 OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr());
482 if (!operation) {
483 DidFinish(handle, callback, error);
484 return handle.id;
486 PrepareForWrite(handle.id, src_url);
487 PrepareForWrite(handle.id, dest_url);
488 operation->MoveFileLocal(
489 src_url, dest_url, option,
490 base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(),
491 handle, callback));
492 return handle.id;
495 base::File::Error FileSystemOperationRunner::SyncGetPlatformPath(
496 const FileSystemURL& url,
497 base::FilePath* platform_path) {
498 base::File::Error error = base::File::FILE_OK;
499 scoped_ptr<FileSystemOperation> operation(
500 file_system_context_->CreateFileSystemOperation(url, &error));
501 if (!operation.get())
502 return error;
503 return operation->SyncGetPlatformPath(url, platform_path);
506 FileSystemOperationRunner::FileSystemOperationRunner(
507 FileSystemContext* file_system_context)
508 : file_system_context_(file_system_context) {}
510 void FileSystemOperationRunner::DidFinish(
511 const OperationHandle& handle,
512 const StatusCallback& callback,
513 base::File::Error rv) {
514 if (handle.scope) {
515 finished_operations_.insert(handle.id);
516 base::ThreadTaskRunnerHandle::Get()->PostTask(
517 FROM_HERE, base::Bind(&FileSystemOperationRunner::DidFinish,
518 AsWeakPtr(), handle, callback, rv));
519 return;
521 callback.Run(rv);
522 FinishOperation(handle.id);
525 void FileSystemOperationRunner::DidGetMetadata(
526 const OperationHandle& handle,
527 const GetMetadataCallback& callback,
528 base::File::Error rv,
529 const base::File::Info& file_info) {
530 if (handle.scope) {
531 finished_operations_.insert(handle.id);
532 base::ThreadTaskRunnerHandle::Get()->PostTask(
533 FROM_HERE, base::Bind(&FileSystemOperationRunner::DidGetMetadata,
534 AsWeakPtr(), handle, callback, rv, file_info));
535 return;
537 callback.Run(rv, file_info);
538 FinishOperation(handle.id);
541 void FileSystemOperationRunner::DidReadDirectory(
542 const OperationHandle& handle,
543 const ReadDirectoryCallback& callback,
544 base::File::Error rv,
545 const std::vector<DirectoryEntry>& entries,
546 bool has_more) {
547 if (handle.scope) {
548 finished_operations_.insert(handle.id);
549 base::ThreadTaskRunnerHandle::Get()->PostTask(
550 FROM_HERE, base::Bind(&FileSystemOperationRunner::DidReadDirectory,
551 AsWeakPtr(), handle, callback, rv,
552 entries, has_more));
553 return;
555 callback.Run(rv, entries, has_more);
556 if (rv != base::File::FILE_OK || !has_more)
557 FinishOperation(handle.id);
560 void FileSystemOperationRunner::DidWrite(
561 const OperationHandle& handle,
562 const WriteCallback& callback,
563 base::File::Error rv,
564 int64 bytes,
565 bool complete) {
566 if (handle.scope) {
567 finished_operations_.insert(handle.id);
568 base::ThreadTaskRunnerHandle::Get()->PostTask(
569 FROM_HERE, base::Bind(&FileSystemOperationRunner::DidWrite, AsWeakPtr(),
570 handle, callback, rv, bytes, complete));
571 return;
573 callback.Run(rv, bytes, complete);
574 if (rv != base::File::FILE_OK || complete)
575 FinishOperation(handle.id);
578 void FileSystemOperationRunner::DidOpenFile(
579 const OperationHandle& handle,
580 const OpenFileCallback& callback,
581 base::File file,
582 const base::Closure& on_close_callback) {
583 if (handle.scope) {
584 finished_operations_.insert(handle.id);
585 base::ThreadTaskRunnerHandle::Get()->PostTask(
586 FROM_HERE, base::Bind(&FileSystemOperationRunner::DidOpenFile,
587 AsWeakPtr(), handle, callback, Passed(&file),
588 on_close_callback));
589 return;
591 callback.Run(file.Pass(), on_close_callback);
592 FinishOperation(handle.id);
595 void FileSystemOperationRunner::DidCreateSnapshot(
596 const OperationHandle& handle,
597 const SnapshotFileCallback& callback,
598 base::File::Error rv,
599 const base::File::Info& file_info,
600 const base::FilePath& platform_path,
601 const scoped_refptr<storage::ShareableFileReference>& file_ref) {
602 if (handle.scope) {
603 finished_operations_.insert(handle.id);
604 base::ThreadTaskRunnerHandle::Get()->PostTask(
605 FROM_HERE, base::Bind(&FileSystemOperationRunner::DidCreateSnapshot,
606 AsWeakPtr(), handle, callback, rv, file_info,
607 platform_path, file_ref));
608 return;
610 callback.Run(rv, file_info, platform_path, file_ref);
611 FinishOperation(handle.id);
614 void FileSystemOperationRunner::OnCopyProgress(
615 const OperationHandle& handle,
616 const CopyProgressCallback& callback,
617 FileSystemOperation::CopyProgressType type,
618 const FileSystemURL& source_url,
619 const FileSystemURL& dest_url,
620 int64 size) {
621 if (handle.scope) {
622 base::ThreadTaskRunnerHandle::Get()->PostTask(
623 FROM_HERE, base::Bind(
624 &FileSystemOperationRunner::OnCopyProgress,
625 AsWeakPtr(), handle, callback, type, source_url, dest_url, size));
626 return;
628 callback.Run(type, source_url, dest_url, size);
631 void FileSystemOperationRunner::PrepareForWrite(OperationID id,
632 const FileSystemURL& url) {
633 if (file_system_context_->GetUpdateObservers(url.type())) {
634 file_system_context_->GetUpdateObservers(url.type())->Notify(
635 &FileUpdateObserver::OnStartUpdate, base::MakeTuple(url));
637 write_target_urls_[id].insert(url);
640 void FileSystemOperationRunner::PrepareForRead(OperationID id,
641 const FileSystemURL& url) {
642 if (file_system_context_->GetAccessObservers(url.type())) {
643 file_system_context_->GetAccessObservers(url.type())->Notify(
644 &FileAccessObserver::OnAccess, base::MakeTuple(url));
648 FileSystemOperationRunner::OperationHandle
649 FileSystemOperationRunner::BeginOperation(
650 FileSystemOperation* operation,
651 base::WeakPtr<BeginOperationScoper> scope) {
652 OperationHandle handle;
653 handle.id = operations_.Add(operation);
654 handle.scope = scope;
655 return handle;
658 void FileSystemOperationRunner::FinishOperation(OperationID id) {
659 OperationToURLSet::iterator found = write_target_urls_.find(id);
660 if (found != write_target_urls_.end()) {
661 const FileSystemURLSet& urls = found->second;
662 for (FileSystemURLSet::const_iterator iter = urls.begin();
663 iter != urls.end(); ++iter) {
664 if (file_system_context_->GetUpdateObservers(iter->type())) {
665 file_system_context_->GetUpdateObservers(iter->type())->Notify(
666 &FileUpdateObserver::OnEndUpdate, base::MakeTuple(*iter));
669 write_target_urls_.erase(found);
672 // IDMap::Lookup fails if the operation is NULL, so we don't check
673 // operations_.Lookup(id) here.
675 operations_.Remove(id);
676 finished_operations_.erase(id);
678 // Dispatch stray cancel callback if exists.
679 std::map<OperationID, StatusCallback>::iterator found_cancel =
680 stray_cancel_callbacks_.find(id);
681 if (found_cancel != stray_cancel_callbacks_.end()) {
682 // This cancel has been requested after the operation has finished,
683 // so report that we failed to stop it.
684 found_cancel->second.Run(base::File::FILE_ERROR_INVALID_OPERATION);
685 stray_cancel_callbacks_.erase(found_cancel);
689 } // namespace storage