[Storage] Blob Storage Refactoring pt 1:
[chromium-blink-merge.git] / storage / browser / fileapi / file_system_operation_runner.cc
blob848929f38cdb95a60989524a604a7429f7904d69
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/message_loop/message_loop_proxy.h"
9 #include "base/stl_util.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_system_operation.h"
17 #include "storage/browser/fileapi/file_writer_delegate.h"
19 namespace storage {
21 typedef FileSystemOperationRunner::OperationID OperationID;
23 class FileSystemOperationRunner::BeginOperationScoper
24 : public base::SupportsWeakPtr<
25 FileSystemOperationRunner::BeginOperationScoper> {
26 public:
27 BeginOperationScoper() {}
28 private:
29 DISALLOW_COPY_AND_ASSIGN(BeginOperationScoper);
32 FileSystemOperationRunner::OperationHandle::OperationHandle() {}
33 FileSystemOperationRunner::OperationHandle::~OperationHandle() {}
35 FileSystemOperationRunner::~FileSystemOperationRunner() {
38 void FileSystemOperationRunner::Shutdown() {
39 operations_.Clear();
42 OperationID FileSystemOperationRunner::CreateFile(
43 const FileSystemURL& url,
44 bool exclusive,
45 const StatusCallback& callback) {
46 base::File::Error error = base::File::FILE_OK;
47 FileSystemOperation* operation =
48 file_system_context_->CreateFileSystemOperation(url, &error);
50 BeginOperationScoper scope;
51 OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr());
52 if (!operation) {
53 DidFinish(handle, callback, error);
54 return handle.id;
56 PrepareForWrite(handle.id, url);
57 operation->CreateFile(
58 url, exclusive,
59 base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(),
60 handle, callback));
61 return handle.id;
64 OperationID FileSystemOperationRunner::CreateDirectory(
65 const FileSystemURL& url,
66 bool exclusive,
67 bool recursive,
68 const StatusCallback& callback) {
69 base::File::Error error = base::File::FILE_OK;
70 FileSystemOperation* operation =
71 file_system_context_->CreateFileSystemOperation(url, &error);
72 BeginOperationScoper scope;
73 OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr());
74 if (!operation) {
75 DidFinish(handle, callback, error);
76 return handle.id;
78 PrepareForWrite(handle.id, url);
79 operation->CreateDirectory(
80 url, exclusive, recursive,
81 base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(),
82 handle, callback));
83 return handle.id;
86 OperationID FileSystemOperationRunner::Copy(
87 const FileSystemURL& src_url,
88 const FileSystemURL& dest_url,
89 CopyOrMoveOption option,
90 const CopyProgressCallback& progress_callback,
91 const StatusCallback& callback) {
92 base::File::Error error = base::File::FILE_OK;
93 FileSystemOperation* operation =
94 file_system_context_->CreateFileSystemOperation(dest_url, &error);
95 BeginOperationScoper scope;
96 OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr());
97 if (!operation) {
98 DidFinish(handle, callback, error);
99 return handle.id;
101 PrepareForWrite(handle.id, dest_url);
102 PrepareForRead(handle.id, src_url);
103 operation->Copy(
104 src_url, dest_url, option,
105 progress_callback.is_null() ?
106 CopyProgressCallback() :
107 base::Bind(&FileSystemOperationRunner::OnCopyProgress, AsWeakPtr(),
108 handle, progress_callback),
109 base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(),
110 handle, callback));
111 return handle.id;
114 OperationID FileSystemOperationRunner::Move(
115 const FileSystemURL& src_url,
116 const FileSystemURL& dest_url,
117 CopyOrMoveOption option,
118 const StatusCallback& callback) {
119 base::File::Error error = base::File::FILE_OK;
120 FileSystemOperation* operation =
121 file_system_context_->CreateFileSystemOperation(dest_url, &error);
122 BeginOperationScoper scope;
123 OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr());
124 if (!operation) {
125 DidFinish(handle, callback, error);
126 return handle.id;
128 PrepareForWrite(handle.id, dest_url);
129 PrepareForWrite(handle.id, src_url);
130 operation->Move(
131 src_url, dest_url, option,
132 base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(),
133 handle, callback));
134 return handle.id;
137 OperationID FileSystemOperationRunner::DirectoryExists(
138 const FileSystemURL& url,
139 const StatusCallback& callback) {
140 base::File::Error error = base::File::FILE_OK;
141 FileSystemOperation* operation =
142 file_system_context_->CreateFileSystemOperation(url, &error);
143 BeginOperationScoper scope;
144 OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr());
145 if (!operation) {
146 DidFinish(handle, callback, error);
147 return handle.id;
149 PrepareForRead(handle.id, url);
150 operation->DirectoryExists(
151 url,
152 base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(),
153 handle, callback));
154 return handle.id;
157 OperationID FileSystemOperationRunner::FileExists(
158 const FileSystemURL& url,
159 const StatusCallback& callback) {
160 base::File::Error error = base::File::FILE_OK;
161 FileSystemOperation* operation =
162 file_system_context_->CreateFileSystemOperation(url, &error);
163 BeginOperationScoper scope;
164 OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr());
165 if (!operation) {
166 DidFinish(handle, callback, error);
167 return handle.id;
169 PrepareForRead(handle.id, url);
170 operation->FileExists(
171 url,
172 base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(),
173 handle, callback));
174 return handle.id;
177 OperationID FileSystemOperationRunner::GetMetadata(
178 const FileSystemURL& url,
179 const GetMetadataCallback& callback) {
180 base::File::Error error = base::File::FILE_OK;
181 FileSystemOperation* operation =
182 file_system_context_->CreateFileSystemOperation(url, &error);
183 BeginOperationScoper scope;
184 OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr());
185 if (!operation) {
186 DidGetMetadata(handle, callback, error, base::File::Info());
187 return handle.id;
189 PrepareForRead(handle.id, url);
190 operation->GetMetadata(
191 url,
192 base::Bind(&FileSystemOperationRunner::DidGetMetadata, AsWeakPtr(),
193 handle, callback));
194 return handle.id;
197 OperationID FileSystemOperationRunner::ReadDirectory(
198 const FileSystemURL& url,
199 const ReadDirectoryCallback& callback) {
200 base::File::Error error = base::File::FILE_OK;
201 FileSystemOperation* operation =
202 file_system_context_->CreateFileSystemOperation(url, &error);
203 BeginOperationScoper scope;
204 OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr());
205 if (!operation) {
206 DidReadDirectory(handle, callback, error, std::vector<DirectoryEntry>(),
207 false);
208 return handle.id;
210 PrepareForRead(handle.id, url);
211 operation->ReadDirectory(
212 url,
213 base::Bind(&FileSystemOperationRunner::DidReadDirectory, AsWeakPtr(),
214 handle, callback));
215 return handle.id;
218 OperationID FileSystemOperationRunner::Remove(
219 const FileSystemURL& url, bool recursive,
220 const StatusCallback& callback) {
221 base::File::Error error = base::File::FILE_OK;
222 FileSystemOperation* operation =
223 file_system_context_->CreateFileSystemOperation(url, &error);
224 BeginOperationScoper scope;
225 OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr());
226 if (!operation) {
227 DidFinish(handle, callback, error);
228 return handle.id;
230 PrepareForWrite(handle.id, url);
231 operation->Remove(
232 url, recursive,
233 base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(),
234 handle, callback));
235 return handle.id;
238 OperationID FileSystemOperationRunner::Write(
239 const net::URLRequestContext* url_request_context,
240 const FileSystemURL& url,
241 scoped_ptr<storage::BlobDataHandle> blob,
242 int64 offset,
243 const WriteCallback& callback) {
244 base::File::Error error = base::File::FILE_OK;
245 FileSystemOperation* operation =
246 file_system_context_->CreateFileSystemOperation(url, &error);
248 BeginOperationScoper scope;
249 OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr());
250 if (!operation) {
251 DidWrite(handle, callback, error, 0, true);
252 return handle.id;
255 scoped_ptr<FileStreamWriter> writer(
256 file_system_context_->CreateFileStreamWriter(url, offset));
257 if (!writer) {
258 // Write is not supported.
259 DidWrite(handle, callback, base::File::FILE_ERROR_SECURITY, 0, true);
260 return handle.id;
263 scoped_ptr<FileWriterDelegate> writer_delegate(
264 new FileWriterDelegate(writer.Pass(), url.mount_option().flush_policy()));
266 scoped_ptr<net::URLRequest> blob_request(
267 storage::BlobProtocolHandler::CreateBlobRequest(
268 blob.Pass(), url_request_context, writer_delegate.get()));
270 PrepareForWrite(handle.id, url);
271 operation->Write(
272 url, writer_delegate.Pass(), blob_request.Pass(),
273 base::Bind(&FileSystemOperationRunner::DidWrite, AsWeakPtr(),
274 handle, callback));
275 return handle.id;
278 OperationID FileSystemOperationRunner::Truncate(
279 const FileSystemURL& url, int64 length,
280 const StatusCallback& callback) {
281 base::File::Error error = base::File::FILE_OK;
282 FileSystemOperation* operation =
283 file_system_context_->CreateFileSystemOperation(url, &error);
284 BeginOperationScoper scope;
285 OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr());
286 if (!operation) {
287 DidFinish(handle, callback, error);
288 return handle.id;
290 PrepareForWrite(handle.id, url);
291 operation->Truncate(
292 url, length,
293 base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(),
294 handle, callback));
295 return handle.id;
298 void FileSystemOperationRunner::Cancel(
299 OperationID id,
300 const StatusCallback& callback) {
301 if (ContainsKey(finished_operations_, id)) {
302 DCHECK(!ContainsKey(stray_cancel_callbacks_, id));
303 stray_cancel_callbacks_[id] = callback;
304 return;
306 FileSystemOperation* operation = operations_.Lookup(id);
307 if (!operation) {
308 // There is no operation with |id|.
309 callback.Run(base::File::FILE_ERROR_INVALID_OPERATION);
310 return;
312 operation->Cancel(callback);
315 OperationID FileSystemOperationRunner::TouchFile(
316 const FileSystemURL& url,
317 const base::Time& last_access_time,
318 const base::Time& last_modified_time,
319 const StatusCallback& callback) {
320 base::File::Error error = base::File::FILE_OK;
321 FileSystemOperation* operation =
322 file_system_context_->CreateFileSystemOperation(url, &error);
323 BeginOperationScoper scope;
324 OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr());
325 if (!operation) {
326 DidFinish(handle, callback, error);
327 return handle.id;
329 PrepareForWrite(handle.id, url);
330 operation->TouchFile(
331 url, last_access_time, last_modified_time,
332 base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(),
333 handle, callback));
334 return handle.id;
337 OperationID FileSystemOperationRunner::OpenFile(
338 const FileSystemURL& url,
339 int file_flags,
340 const OpenFileCallback& callback) {
341 base::File::Error error = base::File::FILE_OK;
342 FileSystemOperation* operation =
343 file_system_context_->CreateFileSystemOperation(url, &error);
344 BeginOperationScoper scope;
345 OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr());
346 if (!operation) {
347 DidOpenFile(handle, callback, base::File(error), base::Closure());
348 return handle.id;
350 if (file_flags &
351 (base::File::FLAG_CREATE | base::File::FLAG_OPEN_ALWAYS |
352 base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_OPEN_TRUNCATED |
353 base::File::FLAG_WRITE | base::File::FLAG_EXCLUSIVE_WRITE |
354 base::File::FLAG_DELETE_ON_CLOSE |
355 base::File::FLAG_WRITE_ATTRIBUTES)) {
356 PrepareForWrite(handle.id, url);
357 } else {
358 PrepareForRead(handle.id, url);
360 operation->OpenFile(
361 url, file_flags,
362 base::Bind(&FileSystemOperationRunner::DidOpenFile, AsWeakPtr(),
363 handle, callback));
364 return handle.id;
367 OperationID FileSystemOperationRunner::CreateSnapshotFile(
368 const FileSystemURL& url,
369 const SnapshotFileCallback& callback) {
370 base::File::Error error = base::File::FILE_OK;
371 FileSystemOperation* operation =
372 file_system_context_->CreateFileSystemOperation(url, &error);
373 BeginOperationScoper scope;
374 OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr());
375 if (!operation) {
376 DidCreateSnapshot(handle, callback, error, base::File::Info(),
377 base::FilePath(), NULL);
378 return handle.id;
380 PrepareForRead(handle.id, url);
381 operation->CreateSnapshotFile(
382 url,
383 base::Bind(&FileSystemOperationRunner::DidCreateSnapshot, AsWeakPtr(),
384 handle, callback));
385 return handle.id;
388 OperationID FileSystemOperationRunner::CopyInForeignFile(
389 const base::FilePath& src_local_disk_path,
390 const FileSystemURL& dest_url,
391 const StatusCallback& callback) {
392 base::File::Error error = base::File::FILE_OK;
393 FileSystemOperation* operation =
394 file_system_context_->CreateFileSystemOperation(dest_url, &error);
395 BeginOperationScoper scope;
396 OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr());
397 if (!operation) {
398 DidFinish(handle, callback, error);
399 return handle.id;
401 PrepareForWrite(handle.id, dest_url);
402 operation->CopyInForeignFile(
403 src_local_disk_path, dest_url,
404 base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(),
405 handle, callback));
406 return handle.id;
409 OperationID FileSystemOperationRunner::RemoveFile(
410 const FileSystemURL& url,
411 const StatusCallback& callback) {
412 base::File::Error error = base::File::FILE_OK;
413 FileSystemOperation* operation =
414 file_system_context_->CreateFileSystemOperation(url, &error);
415 BeginOperationScoper scope;
416 OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr());
417 if (!operation) {
418 DidFinish(handle, callback, error);
419 return handle.id;
421 PrepareForWrite(handle.id, url);
422 operation->RemoveFile(
423 url,
424 base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(),
425 handle, callback));
426 return handle.id;
429 OperationID FileSystemOperationRunner::RemoveDirectory(
430 const FileSystemURL& url,
431 const StatusCallback& callback) {
432 base::File::Error error = base::File::FILE_OK;
433 FileSystemOperation* operation =
434 file_system_context_->CreateFileSystemOperation(url, &error);
435 BeginOperationScoper scope;
436 OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr());
437 if (!operation) {
438 DidFinish(handle, callback, error);
439 return handle.id;
441 PrepareForWrite(handle.id, url);
442 operation->RemoveDirectory(
443 url,
444 base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(),
445 handle, callback));
446 return handle.id;
449 OperationID FileSystemOperationRunner::CopyFileLocal(
450 const FileSystemURL& src_url,
451 const FileSystemURL& dest_url,
452 CopyOrMoveOption option,
453 const CopyFileProgressCallback& progress_callback,
454 const StatusCallback& callback) {
455 base::File::Error error = base::File::FILE_OK;
456 FileSystemOperation* operation =
457 file_system_context_->CreateFileSystemOperation(src_url, &error);
458 BeginOperationScoper scope;
459 OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr());
460 if (!operation) {
461 DidFinish(handle, callback, error);
462 return handle.id;
464 PrepareForRead(handle.id, src_url);
465 PrepareForWrite(handle.id, dest_url);
466 operation->CopyFileLocal(
467 src_url, dest_url, option, progress_callback,
468 base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(),
469 handle, callback));
470 return handle.id;
473 OperationID FileSystemOperationRunner::MoveFileLocal(
474 const FileSystemURL& src_url,
475 const FileSystemURL& dest_url,
476 CopyOrMoveOption option,
477 const StatusCallback& callback) {
478 base::File::Error error = base::File::FILE_OK;
479 FileSystemOperation* operation =
480 file_system_context_->CreateFileSystemOperation(src_url, &error);
481 BeginOperationScoper scope;
482 OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr());
483 if (!operation) {
484 DidFinish(handle, callback, error);
485 return handle.id;
487 PrepareForWrite(handle.id, src_url);
488 PrepareForWrite(handle.id, dest_url);
489 operation->MoveFileLocal(
490 src_url, dest_url, option,
491 base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(),
492 handle, callback));
493 return handle.id;
496 base::File::Error FileSystemOperationRunner::SyncGetPlatformPath(
497 const FileSystemURL& url,
498 base::FilePath* platform_path) {
499 base::File::Error error = base::File::FILE_OK;
500 scoped_ptr<FileSystemOperation> operation(
501 file_system_context_->CreateFileSystemOperation(url, &error));
502 if (!operation.get())
503 return error;
504 return operation->SyncGetPlatformPath(url, platform_path);
507 FileSystemOperationRunner::FileSystemOperationRunner(
508 FileSystemContext* file_system_context)
509 : file_system_context_(file_system_context) {}
511 void FileSystemOperationRunner::DidFinish(
512 const OperationHandle& handle,
513 const StatusCallback& callback,
514 base::File::Error rv) {
515 if (handle.scope) {
516 finished_operations_.insert(handle.id);
517 base::MessageLoopProxy::current()->PostTask(
518 FROM_HERE, base::Bind(&FileSystemOperationRunner::DidFinish,
519 AsWeakPtr(), handle, callback, rv));
520 return;
522 callback.Run(rv);
523 FinishOperation(handle.id);
526 void FileSystemOperationRunner::DidGetMetadata(
527 const OperationHandle& handle,
528 const GetMetadataCallback& callback,
529 base::File::Error rv,
530 const base::File::Info& file_info) {
531 if (handle.scope) {
532 finished_operations_.insert(handle.id);
533 base::MessageLoopProxy::current()->PostTask(
534 FROM_HERE, base::Bind(&FileSystemOperationRunner::DidGetMetadata,
535 AsWeakPtr(), handle, callback, rv, file_info));
536 return;
538 callback.Run(rv, file_info);
539 FinishOperation(handle.id);
542 void FileSystemOperationRunner::DidReadDirectory(
543 const OperationHandle& handle,
544 const ReadDirectoryCallback& callback,
545 base::File::Error rv,
546 const std::vector<DirectoryEntry>& entries,
547 bool has_more) {
548 if (handle.scope) {
549 finished_operations_.insert(handle.id);
550 base::MessageLoopProxy::current()->PostTask(
551 FROM_HERE, base::Bind(&FileSystemOperationRunner::DidReadDirectory,
552 AsWeakPtr(), handle, callback, rv,
553 entries, has_more));
554 return;
556 callback.Run(rv, entries, has_more);
557 if (rv != base::File::FILE_OK || !has_more)
558 FinishOperation(handle.id);
561 void FileSystemOperationRunner::DidWrite(
562 const OperationHandle& handle,
563 const WriteCallback& callback,
564 base::File::Error rv,
565 int64 bytes,
566 bool complete) {
567 if (handle.scope) {
568 finished_operations_.insert(handle.id);
569 base::MessageLoopProxy::current()->PostTask(
570 FROM_HERE, base::Bind(&FileSystemOperationRunner::DidWrite, AsWeakPtr(),
571 handle, callback, rv, bytes, complete));
572 return;
574 callback.Run(rv, bytes, complete);
575 if (rv != base::File::FILE_OK || complete)
576 FinishOperation(handle.id);
579 void FileSystemOperationRunner::DidOpenFile(
580 const OperationHandle& handle,
581 const OpenFileCallback& callback,
582 base::File file,
583 const base::Closure& on_close_callback) {
584 if (handle.scope) {
585 finished_operations_.insert(handle.id);
586 base::MessageLoopProxy::current()->PostTask(
587 FROM_HERE, base::Bind(&FileSystemOperationRunner::DidOpenFile,
588 AsWeakPtr(), handle, callback, Passed(&file),
589 on_close_callback));
590 return;
592 callback.Run(file.Pass(), on_close_callback);
593 FinishOperation(handle.id);
596 void FileSystemOperationRunner::DidCreateSnapshot(
597 const OperationHandle& handle,
598 const SnapshotFileCallback& callback,
599 base::File::Error rv,
600 const base::File::Info& file_info,
601 const base::FilePath& platform_path,
602 const scoped_refptr<storage::ShareableFileReference>& file_ref) {
603 if (handle.scope) {
604 finished_operations_.insert(handle.id);
605 base::MessageLoopProxy::current()->PostTask(
606 FROM_HERE, base::Bind(&FileSystemOperationRunner::DidCreateSnapshot,
607 AsWeakPtr(), handle, callback, rv, file_info,
608 platform_path, file_ref));
609 return;
611 callback.Run(rv, file_info, platform_path, file_ref);
612 FinishOperation(handle.id);
615 void FileSystemOperationRunner::OnCopyProgress(
616 const OperationHandle& handle,
617 const CopyProgressCallback& callback,
618 FileSystemOperation::CopyProgressType type,
619 const FileSystemURL& source_url,
620 const FileSystemURL& dest_url,
621 int64 size) {
622 if (handle.scope) {
623 base::MessageLoopProxy::current()->PostTask(
624 FROM_HERE, base::Bind(
625 &FileSystemOperationRunner::OnCopyProgress,
626 AsWeakPtr(), handle, callback, type, source_url, dest_url, size));
627 return;
629 callback.Run(type, source_url, dest_url, size);
632 void FileSystemOperationRunner::PrepareForWrite(OperationID id,
633 const FileSystemURL& url) {
634 if (file_system_context_->GetUpdateObservers(url.type())) {
635 file_system_context_->GetUpdateObservers(url.type())->Notify(
636 &FileUpdateObserver::OnStartUpdate, MakeTuple(url));
638 write_target_urls_[id].insert(url);
641 void FileSystemOperationRunner::PrepareForRead(OperationID id,
642 const FileSystemURL& url) {
643 if (file_system_context_->GetAccessObservers(url.type())) {
644 file_system_context_->GetAccessObservers(url.type())->Notify(
645 &FileAccessObserver::OnAccess, MakeTuple(url));
649 FileSystemOperationRunner::OperationHandle
650 FileSystemOperationRunner::BeginOperation(
651 FileSystemOperation* operation,
652 base::WeakPtr<BeginOperationScoper> scope) {
653 OperationHandle handle;
654 handle.id = operations_.Add(operation);
655 handle.scope = scope;
656 return handle;
659 void FileSystemOperationRunner::FinishOperation(OperationID id) {
660 OperationToURLSet::iterator found = write_target_urls_.find(id);
661 if (found != write_target_urls_.end()) {
662 const FileSystemURLSet& urls = found->second;
663 for (FileSystemURLSet::const_iterator iter = urls.begin();
664 iter != urls.end(); ++iter) {
665 if (file_system_context_->GetUpdateObservers(iter->type())) {
666 file_system_context_->GetUpdateObservers(iter->type())->Notify(
667 &FileUpdateObserver::OnEndUpdate, MakeTuple(*iter));
670 write_target_urls_.erase(found);
673 // IDMap::Lookup fails if the operation is NULL, so we don't check
674 // operations_.Lookup(id) here.
676 operations_.Remove(id);
677 finished_operations_.erase(id);
679 // Dispatch stray cancel callback if exists.
680 std::map<OperationID, StatusCallback>::iterator found_cancel =
681 stray_cancel_callbacks_.find(id);
682 if (found_cancel != stray_cancel_callbacks_.end()) {
683 // This cancel has been requested after the operation has finished,
684 // so report that we failed to stop it.
685 found_cancel->second.Run(base::File::FILE_ERROR_INVALID_OPERATION);
686 stray_cancel_callbacks_.erase(found_cancel);
690 } // namespace storage