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/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"
21 typedef FileSystemOperationRunner::OperationID OperationID
;
23 class FileSystemOperationRunner::BeginOperationScoper
24 : public base::SupportsWeakPtr
<
25 FileSystemOperationRunner::BeginOperationScoper
> {
27 BeginOperationScoper() {}
29 DISALLOW_COPY_AND_ASSIGN(BeginOperationScoper
);
32 FileSystemOperationRunner::OperationHandle::OperationHandle() {}
33 FileSystemOperationRunner::OperationHandle::~OperationHandle() {}
35 FileSystemOperationRunner::~FileSystemOperationRunner() {
38 void FileSystemOperationRunner::Shutdown() {
42 OperationID
FileSystemOperationRunner::CreateFile(
43 const FileSystemURL
& url
,
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());
53 DidFinish(handle
, callback
, error
);
56 PrepareForWrite(handle
.id
, url
);
57 operation
->CreateFile(
59 base::Bind(&FileSystemOperationRunner::DidFinish
, AsWeakPtr(),
64 OperationID
FileSystemOperationRunner::CreateDirectory(
65 const FileSystemURL
& url
,
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());
75 DidFinish(handle
, callback
, error
);
78 PrepareForWrite(handle
.id
, url
);
79 operation
->CreateDirectory(
80 url
, exclusive
, recursive
,
81 base::Bind(&FileSystemOperationRunner::DidFinish
, AsWeakPtr(),
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());
98 DidFinish(handle
, callback
, error
);
101 PrepareForWrite(handle
.id
, dest_url
);
102 PrepareForRead(handle
.id
, src_url
);
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(),
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());
125 DidFinish(handle
, callback
, error
);
128 PrepareForWrite(handle
.id
, dest_url
);
129 PrepareForWrite(handle
.id
, src_url
);
131 src_url
, dest_url
, option
,
132 base::Bind(&FileSystemOperationRunner::DidFinish
, AsWeakPtr(),
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());
146 DidFinish(handle
, callback
, error
);
149 PrepareForRead(handle
.id
, url
);
150 operation
->DirectoryExists(
152 base::Bind(&FileSystemOperationRunner::DidFinish
, AsWeakPtr(),
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());
166 DidFinish(handle
, callback
, error
);
169 PrepareForRead(handle
.id
, url
);
170 operation
->FileExists(
172 base::Bind(&FileSystemOperationRunner::DidFinish
, AsWeakPtr(),
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());
186 DidGetMetadata(handle
, callback
, error
, base::File::Info());
189 PrepareForRead(handle
.id
, url
);
190 operation
->GetMetadata(
192 base::Bind(&FileSystemOperationRunner::DidGetMetadata
, AsWeakPtr(),
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());
206 DidReadDirectory(handle
, callback
, error
, std::vector
<DirectoryEntry
>(),
210 PrepareForRead(handle
.id
, url
);
211 operation
->ReadDirectory(
213 base::Bind(&FileSystemOperationRunner::DidReadDirectory
, AsWeakPtr(),
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());
227 DidFinish(handle
, callback
, error
);
230 PrepareForWrite(handle
.id
, url
);
233 base::Bind(&FileSystemOperationRunner::DidFinish
, AsWeakPtr(),
238 OperationID
FileSystemOperationRunner::Write(
239 const net::URLRequestContext
* url_request_context
,
240 const FileSystemURL
& url
,
241 scoped_ptr
<storage::BlobDataHandle
> blob
,
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());
251 DidWrite(handle
, callback
, error
, 0, true);
255 scoped_ptr
<FileStreamWriter
> writer(
256 file_system_context_
->CreateFileStreamWriter(url
, offset
));
258 // Write is not supported.
259 DidWrite(handle
, callback
, base::File::FILE_ERROR_SECURITY
, 0, true);
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
);
272 url
, writer_delegate
.Pass(), blob_request
.Pass(),
273 base::Bind(&FileSystemOperationRunner::DidWrite
, AsWeakPtr(),
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());
287 DidFinish(handle
, callback
, error
);
290 PrepareForWrite(handle
.id
, url
);
293 base::Bind(&FileSystemOperationRunner::DidFinish
, AsWeakPtr(),
298 void FileSystemOperationRunner::Cancel(
300 const StatusCallback
& callback
) {
301 if (ContainsKey(finished_operations_
, id
)) {
302 DCHECK(!ContainsKey(stray_cancel_callbacks_
, id
));
303 stray_cancel_callbacks_
[id
] = callback
;
306 FileSystemOperation
* operation
= operations_
.Lookup(id
);
308 // There is no operation with |id|.
309 callback
.Run(base::File::FILE_ERROR_INVALID_OPERATION
);
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());
326 DidFinish(handle
, callback
, error
);
329 PrepareForWrite(handle
.id
, url
);
330 operation
->TouchFile(
331 url
, last_access_time
, last_modified_time
,
332 base::Bind(&FileSystemOperationRunner::DidFinish
, AsWeakPtr(),
337 OperationID
FileSystemOperationRunner::OpenFile(
338 const FileSystemURL
& url
,
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());
347 DidOpenFile(handle
, callback
, base::File(error
), base::Closure());
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
);
358 PrepareForRead(handle
.id
, url
);
362 base::Bind(&FileSystemOperationRunner::DidOpenFile
, AsWeakPtr(),
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());
376 DidCreateSnapshot(handle
, callback
, error
, base::File::Info(),
377 base::FilePath(), NULL
);
380 PrepareForRead(handle
.id
, url
);
381 operation
->CreateSnapshotFile(
383 base::Bind(&FileSystemOperationRunner::DidCreateSnapshot
, AsWeakPtr(),
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());
398 DidFinish(handle
, callback
, error
);
401 PrepareForWrite(handle
.id
, dest_url
);
402 operation
->CopyInForeignFile(
403 src_local_disk_path
, dest_url
,
404 base::Bind(&FileSystemOperationRunner::DidFinish
, AsWeakPtr(),
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());
418 DidFinish(handle
, callback
, error
);
421 PrepareForWrite(handle
.id
, url
);
422 operation
->RemoveFile(
424 base::Bind(&FileSystemOperationRunner::DidFinish
, AsWeakPtr(),
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());
438 DidFinish(handle
, callback
, error
);
441 PrepareForWrite(handle
.id
, url
);
442 operation
->RemoveDirectory(
444 base::Bind(&FileSystemOperationRunner::DidFinish
, AsWeakPtr(),
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());
461 DidFinish(handle
, callback
, error
);
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(),
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());
484 DidFinish(handle
, callback
, error
);
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(),
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())
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
) {
516 finished_operations_
.insert(handle
.id
);
517 base::MessageLoopProxy::current()->PostTask(
518 FROM_HERE
, base::Bind(&FileSystemOperationRunner::DidFinish
,
519 AsWeakPtr(), handle
, callback
, 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
) {
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
));
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
,
549 finished_operations_
.insert(handle
.id
);
550 base::MessageLoopProxy::current()->PostTask(
551 FROM_HERE
, base::Bind(&FileSystemOperationRunner::DidReadDirectory
,
552 AsWeakPtr(), handle
, callback
, rv
,
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
,
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
));
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
,
583 const base::Closure
& on_close_callback
) {
585 finished_operations_
.insert(handle
.id
);
586 base::MessageLoopProxy::current()->PostTask(
587 FROM_HERE
, base::Bind(&FileSystemOperationRunner::DidOpenFile
,
588 AsWeakPtr(), handle
, callback
, Passed(&file
),
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
) {
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
));
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
,
623 base::MessageLoopProxy::current()->PostTask(
624 FROM_HERE
, base::Bind(
625 &FileSystemOperationRunner::OnCopyProgress
,
626 AsWeakPtr(), handle
, callback
, type
, source_url
, dest_url
, size
));
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
;
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