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"
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"
20 typedef FileSystemOperationRunner::OperationID OperationID
;
22 class FileSystemOperationRunner::BeginOperationScoper
23 : public base::SupportsWeakPtr
<
24 FileSystemOperationRunner::BeginOperationScoper
> {
26 BeginOperationScoper() {}
28 DISALLOW_COPY_AND_ASSIGN(BeginOperationScoper
);
31 FileSystemOperationRunner::OperationHandle::OperationHandle() {}
32 FileSystemOperationRunner::OperationHandle::~OperationHandle() {}
34 FileSystemOperationRunner::~FileSystemOperationRunner() {
37 void FileSystemOperationRunner::Shutdown() {
41 OperationID
FileSystemOperationRunner::CreateFile(
42 const FileSystemURL
& url
,
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());
52 DidFinish(handle
, callback
, error
);
55 PrepareForWrite(handle
.id
, url
);
56 operation
->CreateFile(
58 base::Bind(&FileSystemOperationRunner::DidFinish
, AsWeakPtr(),
63 OperationID
FileSystemOperationRunner::CreateDirectory(
64 const FileSystemURL
& url
,
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());
74 DidFinish(handle
, callback
, error
);
77 PrepareForWrite(handle
.id
, url
);
78 operation
->CreateDirectory(
79 url
, exclusive
, recursive
,
80 base::Bind(&FileSystemOperationRunner::DidFinish
, AsWeakPtr(),
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());
97 DidFinish(handle
, callback
, error
);
100 PrepareForWrite(handle
.id
, dest_url
);
101 PrepareForRead(handle
.id
, src_url
);
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(),
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());
124 DidFinish(handle
, callback
, error
);
127 PrepareForWrite(handle
.id
, dest_url
);
128 PrepareForWrite(handle
.id
, src_url
);
130 src_url
, dest_url
, option
,
131 base::Bind(&FileSystemOperationRunner::DidFinish
, AsWeakPtr(),
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());
145 DidFinish(handle
, callback
, error
);
148 PrepareForRead(handle
.id
, url
);
149 operation
->DirectoryExists(
151 base::Bind(&FileSystemOperationRunner::DidFinish
, AsWeakPtr(),
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());
165 DidFinish(handle
, callback
, error
);
168 PrepareForRead(handle
.id
, url
);
169 operation
->FileExists(
171 base::Bind(&FileSystemOperationRunner::DidFinish
, AsWeakPtr(),
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());
185 DidGetMetadata(handle
, callback
, error
, base::File::Info());
188 PrepareForRead(handle
.id
, url
);
189 operation
->GetMetadata(
191 base::Bind(&FileSystemOperationRunner::DidGetMetadata
, AsWeakPtr(),
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());
205 DidReadDirectory(handle
, callback
, error
, std::vector
<DirectoryEntry
>(),
209 PrepareForRead(handle
.id
, url
);
210 operation
->ReadDirectory(
212 base::Bind(&FileSystemOperationRunner::DidReadDirectory
, AsWeakPtr(),
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());
226 DidFinish(handle
, callback
, error
);
229 PrepareForWrite(handle
.id
, url
);
232 base::Bind(&FileSystemOperationRunner::DidFinish
, AsWeakPtr(),
237 OperationID
FileSystemOperationRunner::Write(
238 const net::URLRequestContext
* url_request_context
,
239 const FileSystemURL
& url
,
240 scoped_ptr
<storage::BlobDataHandle
> blob
,
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());
250 DidWrite(handle
, callback
, error
, 0, true);
254 scoped_ptr
<FileStreamWriter
> writer(
255 file_system_context_
->CreateFileStreamWriter(url
, offset
));
257 // Write is not supported.
258 DidWrite(handle
, callback
, base::File::FILE_ERROR_SECURITY
, 0, true);
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
);
271 url
, writer_delegate
.Pass(), blob_request
.Pass(),
272 base::Bind(&FileSystemOperationRunner::DidWrite
, AsWeakPtr(),
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());
286 DidFinish(handle
, callback
, error
);
289 PrepareForWrite(handle
.id
, url
);
292 base::Bind(&FileSystemOperationRunner::DidFinish
, AsWeakPtr(),
297 void FileSystemOperationRunner::Cancel(
299 const StatusCallback
& callback
) {
300 if (ContainsKey(finished_operations_
, id
)) {
301 DCHECK(!ContainsKey(stray_cancel_callbacks_
, id
));
302 stray_cancel_callbacks_
[id
] = callback
;
305 FileSystemOperation
* operation
= operations_
.Lookup(id
);
307 // There is no operation with |id|.
308 callback
.Run(base::File::FILE_ERROR_INVALID_OPERATION
);
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());
325 DidFinish(handle
, callback
, error
);
328 PrepareForWrite(handle
.id
, url
);
329 operation
->TouchFile(
330 url
, last_access_time
, last_modified_time
,
331 base::Bind(&FileSystemOperationRunner::DidFinish
, AsWeakPtr(),
336 OperationID
FileSystemOperationRunner::OpenFile(
337 const FileSystemURL
& url
,
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());
346 DidOpenFile(handle
, callback
, base::File(error
), base::Closure());
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
);
357 PrepareForRead(handle
.id
, url
);
361 base::Bind(&FileSystemOperationRunner::DidOpenFile
, AsWeakPtr(),
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());
375 DidCreateSnapshot(handle
, callback
, error
, base::File::Info(),
376 base::FilePath(), NULL
);
379 PrepareForRead(handle
.id
, url
);
380 operation
->CreateSnapshotFile(
382 base::Bind(&FileSystemOperationRunner::DidCreateSnapshot
, AsWeakPtr(),
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());
397 DidFinish(handle
, callback
, error
);
400 PrepareForWrite(handle
.id
, dest_url
);
401 operation
->CopyInForeignFile(
402 src_local_disk_path
, dest_url
,
403 base::Bind(&FileSystemOperationRunner::DidFinish
, AsWeakPtr(),
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());
417 DidFinish(handle
, callback
, error
);
420 PrepareForWrite(handle
.id
, url
);
421 operation
->RemoveFile(
423 base::Bind(&FileSystemOperationRunner::DidFinish
, AsWeakPtr(),
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());
437 DidFinish(handle
, callback
, error
);
440 PrepareForWrite(handle
.id
, url
);
441 operation
->RemoveDirectory(
443 base::Bind(&FileSystemOperationRunner::DidFinish
, AsWeakPtr(),
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());
460 DidFinish(handle
, callback
, error
);
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(),
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());
483 DidFinish(handle
, callback
, error
);
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(),
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())
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
) {
515 finished_operations_
.insert(handle
.id
);
516 base::ThreadTaskRunnerHandle::Get()->PostTask(
517 FROM_HERE
, base::Bind(&FileSystemOperationRunner::DidFinish
,
518 AsWeakPtr(), handle
, callback
, 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
) {
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
));
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
,
548 finished_operations_
.insert(handle
.id
);
549 base::ThreadTaskRunnerHandle::Get()->PostTask(
550 FROM_HERE
, base::Bind(&FileSystemOperationRunner::DidReadDirectory
,
551 AsWeakPtr(), handle
, callback
, rv
,
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
,
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
));
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
,
582 const base::Closure
& on_close_callback
) {
584 finished_operations_
.insert(handle
.id
);
585 base::ThreadTaskRunnerHandle::Get()->PostTask(
586 FROM_HERE
, base::Bind(&FileSystemOperationRunner::DidOpenFile
,
587 AsWeakPtr(), handle
, callback
, Passed(&file
),
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
) {
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
));
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
,
622 base::ThreadTaskRunnerHandle::Get()->PostTask(
623 FROM_HERE
, base::Bind(
624 &FileSystemOperationRunner::OnCopyProgress
,
625 AsWeakPtr(), handle
, callback
, type
, source_url
, dest_url
, size
));
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
;
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