Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / webkit / browser / fileapi / file_system_operation_runner.cc
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.
4
5 #include "webkit/browser/fileapi/file_system_operation_runner.h"
6
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 "webkit/browser/blob/blob_url_request_job_factory.h"
12 #include "webkit/browser/fileapi/file_observers.h"
13 #include "webkit/browser/fileapi/file_stream_writer.h"
14 #include "webkit/browser/fileapi/file_system_context.h"
15 #include "webkit/browser/fileapi/file_system_operation.h"
16 #include "webkit/browser/fileapi/file_writer_delegate.h"
17 #include "webkit/common/blob/shareable_file_reference.h"
18
19 namespace fileapi {
20
21 typedef FileSystemOperationRunner::OperationID OperationID;
22
23 class FileSystemOperationRunner::BeginOperationScoper
24     : public base::SupportsWeakPtr<
25           FileSystemOperationRunner::BeginOperationScoper> {
26  public:
27   BeginOperationScoper() {}
28  private:
29   DISALLOW_COPY_AND_ASSIGN(BeginOperationScoper);
30 };
31
32 FileSystemOperationRunner::OperationHandle::OperationHandle() {}
33 FileSystemOperationRunner::OperationHandle::~OperationHandle() {}
34
35 FileSystemOperationRunner::~FileSystemOperationRunner() {
36 }
37
38 void FileSystemOperationRunner::Shutdown() {
39   operations_.Clear();
40 }
41
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);
49
50   BeginOperationScoper scope;
51   OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr());
52   if (!operation) {
53     DidFinish(handle, callback, error);
54     return handle.id;
55   }
56   PrepareForWrite(handle.id, url);
57   operation->CreateFile(
58       url, exclusive,
59       base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(),
60                  handle, callback));
61   return handle.id;
62 }
63
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;
77   }
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;
84 }
85
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;
100   }
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;
112 }
113
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;
127   }
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;
135 }
136
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;
148   }
149   PrepareForRead(handle.id, url);
150   operation->DirectoryExists(
151       url,
152       base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(),
153                  handle, callback));
154   return handle.id;
155 }
156
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;
168   }
169   PrepareForRead(handle.id, url);
170   operation->FileExists(
171       url,
172       base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(),
173                  handle, callback));
174   return handle.id;
175 }
176
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;
188   }
189   PrepareForRead(handle.id, url);
190   operation->GetMetadata(
191       url,
192       base::Bind(&FileSystemOperationRunner::DidGetMetadata, AsWeakPtr(),
193                  handle, callback));
194   return handle.id;
195 }
196
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;
209   }
210   PrepareForRead(handle.id, url);
211   operation->ReadDirectory(
212       url,
213       base::Bind(&FileSystemOperationRunner::DidReadDirectory, AsWeakPtr(),
214                  handle, callback));
215   return handle.id;
216 }
217
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;
229   }
230   PrepareForWrite(handle.id, url);
231   operation->Remove(
232       url, recursive,
233       base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(),
234                  handle, callback));
235   return handle.id;
236 }
237
238 OperationID FileSystemOperationRunner::Write(
239     const net::URLRequestContext* url_request_context,
240     const FileSystemURL& url,
241     scoped_ptr<webkit_blob::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);
247
248   BeginOperationScoper scope;
249   OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr());
250   if (!operation) {
251     DidWrite(handle, callback, error, 0, true);
252     return handle.id;
253   }
254
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;
261   }
262
263   FileWriterDelegate::FlushPolicy flush_policy =
264       file_system_context_->ShouldFlushOnWriteCompletion(url.type())
265           ? FileWriterDelegate::FLUSH_ON_COMPLETION
266           : FileWriterDelegate::NO_FLUSH_ON_COMPLETION;
267   scoped_ptr<FileWriterDelegate> writer_delegate(
268       new FileWriterDelegate(writer.Pass(), flush_policy));
269
270   scoped_ptr<net::URLRequest> blob_request(
271       webkit_blob::BlobProtocolHandler::CreateBlobRequest(
272           blob.Pass(),
273           url_request_context,
274           writer_delegate.get()));
275
276   PrepareForWrite(handle.id, url);
277   operation->Write(
278       url, writer_delegate.Pass(), blob_request.Pass(),
279       base::Bind(&FileSystemOperationRunner::DidWrite, AsWeakPtr(),
280                  handle, callback));
281   return handle.id;
282 }
283
284 OperationID FileSystemOperationRunner::Truncate(
285     const FileSystemURL& url, int64 length,
286     const StatusCallback& callback) {
287   base::File::Error error = base::File::FILE_OK;
288   FileSystemOperation* operation =
289       file_system_context_->CreateFileSystemOperation(url, &error);
290   BeginOperationScoper scope;
291   OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr());
292   if (!operation) {
293     DidFinish(handle, callback, error);
294     return handle.id;
295   }
296   PrepareForWrite(handle.id, url);
297   operation->Truncate(
298       url, length,
299       base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(),
300                  handle, callback));
301   return handle.id;
302 }
303
304 void FileSystemOperationRunner::Cancel(
305     OperationID id,
306     const StatusCallback& callback) {
307   if (ContainsKey(finished_operations_, id)) {
308     DCHECK(!ContainsKey(stray_cancel_callbacks_, id));
309     stray_cancel_callbacks_[id] = callback;
310     return;
311   }
312   FileSystemOperation* operation = operations_.Lookup(id);
313   if (!operation) {
314     // There is no operation with |id|.
315     callback.Run(base::File::FILE_ERROR_INVALID_OPERATION);
316     return;
317   }
318   operation->Cancel(callback);
319 }
320
321 OperationID FileSystemOperationRunner::TouchFile(
322     const FileSystemURL& url,
323     const base::Time& last_access_time,
324     const base::Time& last_modified_time,
325     const StatusCallback& callback) {
326   base::File::Error error = base::File::FILE_OK;
327   FileSystemOperation* operation =
328       file_system_context_->CreateFileSystemOperation(url, &error);
329   BeginOperationScoper scope;
330   OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr());
331   if (!operation) {
332     DidFinish(handle, callback, error);
333     return handle.id;
334   }
335   PrepareForWrite(handle.id, url);
336   operation->TouchFile(
337       url, last_access_time, last_modified_time,
338       base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(),
339                  handle, callback));
340   return handle.id;
341 }
342
343 OperationID FileSystemOperationRunner::OpenFile(
344     const FileSystemURL& url,
345     int file_flags,
346     const OpenFileCallback& callback) {
347   base::File::Error error = base::File::FILE_OK;
348   FileSystemOperation* operation =
349       file_system_context_->CreateFileSystemOperation(url, &error);
350   BeginOperationScoper scope;
351   OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr());
352   if (!operation) {
353     DidOpenFile(handle, callback, error, base::kInvalidPlatformFileValue,
354                 base::Closure());
355     return handle.id;
356   }
357   if (file_flags &
358       (base::PLATFORM_FILE_CREATE | base::PLATFORM_FILE_OPEN_ALWAYS |
359        base::PLATFORM_FILE_CREATE_ALWAYS | base::PLATFORM_FILE_OPEN_TRUNCATED |
360        base::PLATFORM_FILE_WRITE | base::PLATFORM_FILE_EXCLUSIVE_WRITE |
361        base::PLATFORM_FILE_DELETE_ON_CLOSE |
362        base::PLATFORM_FILE_WRITE_ATTRIBUTES)) {
363     PrepareForWrite(handle.id, url);
364   } else {
365     PrepareForRead(handle.id, url);
366   }
367   operation->OpenFile(
368       url, file_flags,
369       base::Bind(&FileSystemOperationRunner::DidOpenFile, AsWeakPtr(),
370                  handle, callback));
371   return handle.id;
372 }
373
374 OperationID FileSystemOperationRunner::CreateSnapshotFile(
375     const FileSystemURL& url,
376     const SnapshotFileCallback& callback) {
377   base::File::Error error = base::File::FILE_OK;
378   FileSystemOperation* operation =
379       file_system_context_->CreateFileSystemOperation(url, &error);
380   BeginOperationScoper scope;
381   OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr());
382   if (!operation) {
383     DidCreateSnapshot(handle, callback, error, base::File::Info(),
384                       base::FilePath(), NULL);
385     return handle.id;
386   }
387   PrepareForRead(handle.id, url);
388   operation->CreateSnapshotFile(
389       url,
390       base::Bind(&FileSystemOperationRunner::DidCreateSnapshot, AsWeakPtr(),
391                  handle, callback));
392   return handle.id;
393 }
394
395 OperationID FileSystemOperationRunner::CopyInForeignFile(
396     const base::FilePath& src_local_disk_path,
397     const FileSystemURL& dest_url,
398     const StatusCallback& callback) {
399   base::File::Error error = base::File::FILE_OK;
400   FileSystemOperation* operation =
401       file_system_context_->CreateFileSystemOperation(dest_url, &error);
402   BeginOperationScoper scope;
403   OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr());
404   if (!operation) {
405     DidFinish(handle, callback, error);
406     return handle.id;
407   }
408   operation->CopyInForeignFile(
409       src_local_disk_path, dest_url,
410       base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(),
411                  handle, callback));
412   return handle.id;
413 }
414
415 OperationID FileSystemOperationRunner::RemoveFile(
416     const FileSystemURL& url,
417     const StatusCallback& callback) {
418   base::File::Error error = base::File::FILE_OK;
419   FileSystemOperation* operation =
420       file_system_context_->CreateFileSystemOperation(url, &error);
421   BeginOperationScoper scope;
422   OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr());
423   if (!operation) {
424     DidFinish(handle, callback, error);
425     return handle.id;
426   }
427   operation->RemoveFile(
428       url,
429       base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(),
430                  handle, callback));
431   return handle.id;
432 }
433
434 OperationID FileSystemOperationRunner::RemoveDirectory(
435     const FileSystemURL& url,
436     const StatusCallback& callback) {
437   base::File::Error error = base::File::FILE_OK;
438   FileSystemOperation* operation =
439       file_system_context_->CreateFileSystemOperation(url, &error);
440   BeginOperationScoper scope;
441   OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr());
442   if (!operation) {
443     DidFinish(handle, callback, error);
444     return handle.id;
445   }
446   operation->RemoveDirectory(
447       url,
448       base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(),
449                  handle, callback));
450   return handle.id;
451 }
452
453 OperationID FileSystemOperationRunner::CopyFileLocal(
454     const FileSystemURL& src_url,
455     const FileSystemURL& dest_url,
456     CopyOrMoveOption option,
457     const CopyFileProgressCallback& progress_callback,
458     const StatusCallback& callback) {
459   base::File::Error error = base::File::FILE_OK;
460   FileSystemOperation* operation =
461       file_system_context_->CreateFileSystemOperation(src_url, &error);
462   BeginOperationScoper scope;
463   OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr());
464   if (!operation) {
465     DidFinish(handle, callback, error);
466     return handle.id;
467   }
468   operation->CopyFileLocal(
469       src_url, dest_url, option, progress_callback,
470       base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(),
471                  handle, callback));
472   return handle.id;
473 }
474
475 OperationID FileSystemOperationRunner::MoveFileLocal(
476     const FileSystemURL& src_url,
477     const FileSystemURL& dest_url,
478     CopyOrMoveOption option,
479     const StatusCallback& callback) {
480   base::File::Error error = base::File::FILE_OK;
481   FileSystemOperation* operation =
482       file_system_context_->CreateFileSystemOperation(src_url, &error);
483   BeginOperationScoper scope;
484   OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr());
485   if (!operation) {
486     DidFinish(handle, callback, error);
487     return handle.id;
488   }
489   operation->MoveFileLocal(
490       src_url, dest_url, option,
491       base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(),
492                  handle, callback));
493   return handle.id;
494 }
495
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);
505 }
506
507 FileSystemOperationRunner::FileSystemOperationRunner(
508     FileSystemContext* file_system_context)
509     : file_system_context_(file_system_context) {}
510
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;
521   }
522   callback.Run(rv);
523   FinishOperation(handle.id);
524 }
525
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;
537   }
538   callback.Run(rv, file_info);
539   FinishOperation(handle.id);
540 }
541
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;
555   }
556   callback.Run(rv, entries, has_more);
557   if (rv != base::File::FILE_OK || !has_more)
558     FinishOperation(handle.id);
559 }
560
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;
573   }
574   callback.Run(rv, bytes, complete);
575   if (rv != base::File::FILE_OK || complete)
576     FinishOperation(handle.id);
577 }
578
579 void FileSystemOperationRunner::DidOpenFile(
580     const OperationHandle& handle,
581     const OpenFileCallback& callback,
582     base::File::Error rv,
583     base::PlatformFile file,
584     const base::Closure& on_close_callback) {
585   if (handle.scope) {
586     finished_operations_.insert(handle.id);
587     base::MessageLoopProxy::current()->PostTask(
588         FROM_HERE, base::Bind(&FileSystemOperationRunner::DidOpenFile,
589                               AsWeakPtr(), handle, callback, rv, file,
590                               on_close_callback));
591     return;
592   }
593   callback.Run(rv, file, on_close_callback);
594   FinishOperation(handle.id);
595 }
596
597 void FileSystemOperationRunner::DidCreateSnapshot(
598     const OperationHandle& handle,
599     const SnapshotFileCallback& callback,
600     base::File::Error rv,
601     const base::File::Info& file_info,
602     const base::FilePath& platform_path,
603     const scoped_refptr<webkit_blob::ShareableFileReference>& file_ref) {
604   if (handle.scope) {
605     finished_operations_.insert(handle.id);
606     base::MessageLoopProxy::current()->PostTask(
607         FROM_HERE, base::Bind(&FileSystemOperationRunner::DidCreateSnapshot,
608                               AsWeakPtr(), handle, callback, rv, file_info,
609                               platform_path, file_ref));
610     return;
611   }
612   callback.Run(rv, file_info, platform_path, file_ref);
613   FinishOperation(handle.id);
614 }
615
616 void FileSystemOperationRunner::OnCopyProgress(
617     const OperationHandle& handle,
618     const CopyProgressCallback& callback,
619     FileSystemOperation::CopyProgressType type,
620     const FileSystemURL& source_url,
621     const FileSystemURL& dest_url,
622     int64 size) {
623   if (handle.scope) {
624     base::MessageLoopProxy::current()->PostTask(
625         FROM_HERE, base::Bind(
626             &FileSystemOperationRunner::OnCopyProgress,
627             AsWeakPtr(), handle, callback, type, source_url, dest_url, size));
628     return;
629   }
630   callback.Run(type, source_url, dest_url, size);
631 }
632
633 void FileSystemOperationRunner::PrepareForWrite(OperationID id,
634                                                 const FileSystemURL& url) {
635   if (file_system_context_->GetUpdateObservers(url.type())) {
636     file_system_context_->GetUpdateObservers(url.type())->Notify(
637         &FileUpdateObserver::OnStartUpdate, MakeTuple(url));
638   }
639   write_target_urls_[id].insert(url);
640 }
641
642 void FileSystemOperationRunner::PrepareForRead(OperationID id,
643                                                const FileSystemURL& url) {
644   if (file_system_context_->GetAccessObservers(url.type())) {
645     file_system_context_->GetAccessObservers(url.type())->Notify(
646         &FileAccessObserver::OnAccess, MakeTuple(url));
647   }
648 }
649
650 FileSystemOperationRunner::OperationHandle
651 FileSystemOperationRunner::BeginOperation(
652     FileSystemOperation* operation,
653     base::WeakPtr<BeginOperationScoper> scope) {
654   OperationHandle handle;
655   handle.id = operations_.Add(operation);
656   handle.scope = scope;
657   return handle;
658 }
659
660 void FileSystemOperationRunner::FinishOperation(OperationID id) {
661   OperationToURLSet::iterator found = write_target_urls_.find(id);
662   if (found != write_target_urls_.end()) {
663     const FileSystemURLSet& urls = found->second;
664     for (FileSystemURLSet::const_iterator iter = urls.begin();
665         iter != urls.end(); ++iter) {
666       if (file_system_context_->GetUpdateObservers(iter->type())) {
667         file_system_context_->GetUpdateObservers(iter->type())->Notify(
668             &FileUpdateObserver::OnEndUpdate, MakeTuple(*iter));
669       }
670     }
671     write_target_urls_.erase(found);
672   }
673
674   // IDMap::Lookup fails if the operation is NULL, so we don't check
675   // operations_.Lookup(id) here.
676
677   operations_.Remove(id);
678   finished_operations_.erase(id);
679
680   // Dispatch stray cancel callback if exists.
681   std::map<OperationID, StatusCallback>::iterator found_cancel =
682       stray_cancel_callbacks_.find(id);
683   if (found_cancel != stray_cancel_callbacks_.end()) {
684     // This cancel has been requested after the operation has finished,
685     // so report that we failed to stop it.
686     found_cancel->second.Run(base::File::FILE_ERROR_INVALID_OPERATION);
687     stray_cancel_callbacks_.erase(found_cancel);
688   }
689 }
690
691 }  // namespace fileapi