- add sources.
[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::PlatformFileError error = base::PLATFORM_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::PlatformFileError error = base::PLATFORM_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::PlatformFileError error = base::PLATFORM_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::PlatformFileError error = base::PLATFORM_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::PlatformFileError error = base::PLATFORM_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::PlatformFileError error = base::PLATFORM_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::PlatformFileError error = base::PLATFORM_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::PlatformFileInfo());
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::PlatformFileError error = base::PLATFORM_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::PlatformFileError error = base::PLATFORM_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::PlatformFileError error = base::PLATFORM_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::PLATFORM_FILE_ERROR_SECURITY, 0, true);
260     return handle.id;
261   }
262
263   scoped_ptr<FileWriterDelegate> writer_delegate(
264       new FileWriterDelegate(writer.Pass()));
265
266   scoped_ptr<net::URLRequest> blob_request(
267       webkit_blob::BlobProtocolHandler::CreateBlobRequest(
268           blob.Pass(),
269           url_request_context,
270           writer_delegate.get()));
271
272   PrepareForWrite(handle.id, url);
273   operation->Write(
274       url, writer_delegate.Pass(), blob_request.Pass(),
275       base::Bind(&FileSystemOperationRunner::DidWrite, AsWeakPtr(),
276                  handle, callback));
277   return handle.id;
278 }
279
280 OperationID FileSystemOperationRunner::Truncate(
281     const FileSystemURL& url, int64 length,
282     const StatusCallback& callback) {
283   base::PlatformFileError error = base::PLATFORM_FILE_OK;
284   FileSystemOperation* operation =
285       file_system_context_->CreateFileSystemOperation(url, &error);
286   BeginOperationScoper scope;
287   OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr());
288   if (!operation) {
289     DidFinish(handle, callback, error);
290     return handle.id;
291   }
292   PrepareForWrite(handle.id, url);
293   operation->Truncate(
294       url, length,
295       base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(),
296                  handle, callback));
297   return handle.id;
298 }
299
300 void FileSystemOperationRunner::Cancel(
301     OperationID id,
302     const StatusCallback& callback) {
303   if (ContainsKey(finished_operations_, id)) {
304     DCHECK(!ContainsKey(stray_cancel_callbacks_, id));
305     stray_cancel_callbacks_[id] = callback;
306     return;
307   }
308   FileSystemOperation* operation = operations_.Lookup(id);
309   if (!operation) {
310     // There is no operation with |id|.
311     callback.Run(base::PLATFORM_FILE_ERROR_INVALID_OPERATION);
312     return;
313   }
314   operation->Cancel(callback);
315 }
316
317 OperationID FileSystemOperationRunner::TouchFile(
318     const FileSystemURL& url,
319     const base::Time& last_access_time,
320     const base::Time& last_modified_time,
321     const StatusCallback& callback) {
322   base::PlatformFileError error = base::PLATFORM_FILE_OK;
323   FileSystemOperation* operation =
324       file_system_context_->CreateFileSystemOperation(url, &error);
325   BeginOperationScoper scope;
326   OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr());
327   if (!operation) {
328     DidFinish(handle, callback, error);
329     return handle.id;
330   }
331   PrepareForWrite(handle.id, url);
332   operation->TouchFile(
333       url, last_access_time, last_modified_time,
334       base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(),
335                  handle, callback));
336   return handle.id;
337 }
338
339 OperationID FileSystemOperationRunner::OpenFile(
340     const FileSystemURL& url,
341     int file_flags,
342     base::ProcessHandle peer_handle,
343     const OpenFileCallback& callback) {
344   base::PlatformFileError error = base::PLATFORM_FILE_OK;
345   FileSystemOperation* operation =
346       file_system_context_->CreateFileSystemOperation(url, &error);
347   BeginOperationScoper scope;
348   OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr());
349   if (!operation) {
350     DidOpenFile(handle, callback, error, base::kInvalidPlatformFileValue,
351                 base::Closure(), base::ProcessHandle());
352     return handle.id;
353   }
354   if (file_flags &
355       (base::PLATFORM_FILE_CREATE | base::PLATFORM_FILE_OPEN_ALWAYS |
356        base::PLATFORM_FILE_CREATE_ALWAYS | base::PLATFORM_FILE_OPEN_TRUNCATED |
357        base::PLATFORM_FILE_WRITE | base::PLATFORM_FILE_EXCLUSIVE_WRITE |
358        base::PLATFORM_FILE_DELETE_ON_CLOSE |
359        base::PLATFORM_FILE_WRITE_ATTRIBUTES)) {
360     PrepareForWrite(handle.id, url);
361   } else {
362     PrepareForRead(handle.id, url);
363   }
364   operation->OpenFile(
365       url, file_flags, peer_handle,
366       base::Bind(&FileSystemOperationRunner::DidOpenFile, AsWeakPtr(),
367                  handle, callback));
368   return handle.id;
369 }
370
371 OperationID FileSystemOperationRunner::CreateSnapshotFile(
372     const FileSystemURL& url,
373     const SnapshotFileCallback& callback) {
374   base::PlatformFileError error = base::PLATFORM_FILE_OK;
375   FileSystemOperation* operation =
376       file_system_context_->CreateFileSystemOperation(url, &error);
377   BeginOperationScoper scope;
378   OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr());
379   if (!operation) {
380     DidCreateSnapshot(handle, callback, error, base::PlatformFileInfo(),
381                       base::FilePath(), NULL);
382     return handle.id;
383   }
384   PrepareForRead(handle.id, url);
385   operation->CreateSnapshotFile(
386       url,
387       base::Bind(&FileSystemOperationRunner::DidCreateSnapshot, AsWeakPtr(),
388                  handle, callback));
389   return handle.id;
390 }
391
392 OperationID FileSystemOperationRunner::CopyInForeignFile(
393     const base::FilePath& src_local_disk_path,
394     const FileSystemURL& dest_url,
395     const StatusCallback& callback) {
396   base::PlatformFileError error = base::PLATFORM_FILE_OK;
397   FileSystemOperation* operation =
398       file_system_context_->CreateFileSystemOperation(dest_url, &error);
399   BeginOperationScoper scope;
400   OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr());
401   if (!operation) {
402     DidFinish(handle, callback, error);
403     return handle.id;
404   }
405   operation->CopyInForeignFile(
406       src_local_disk_path, dest_url,
407       base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(),
408                  handle, callback));
409   return handle.id;
410 }
411
412 OperationID FileSystemOperationRunner::RemoveFile(
413     const FileSystemURL& url,
414     const StatusCallback& callback) {
415   base::PlatformFileError error = base::PLATFORM_FILE_OK;
416   FileSystemOperation* operation =
417       file_system_context_->CreateFileSystemOperation(url, &error);
418   BeginOperationScoper scope;
419   OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr());
420   if (!operation) {
421     DidFinish(handle, callback, error);
422     return handle.id;
423   }
424   operation->RemoveFile(
425       url,
426       base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(),
427                  handle, callback));
428   return handle.id;
429 }
430
431 OperationID FileSystemOperationRunner::RemoveDirectory(
432     const FileSystemURL& url,
433     const StatusCallback& callback) {
434   base::PlatformFileError error = base::PLATFORM_FILE_OK;
435   FileSystemOperation* operation =
436       file_system_context_->CreateFileSystemOperation(url, &error);
437   BeginOperationScoper scope;
438   OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr());
439   if (!operation) {
440     DidFinish(handle, callback, error);
441     return handle.id;
442   }
443   operation->RemoveDirectory(
444       url,
445       base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(),
446                  handle, callback));
447   return handle.id;
448 }
449
450 OperationID FileSystemOperationRunner::CopyFileLocal(
451     const FileSystemURL& src_url,
452     const FileSystemURL& dest_url,
453     CopyOrMoveOption option,
454     const CopyFileProgressCallback& progress_callback,
455     const StatusCallback& callback) {
456   base::PlatformFileError error = base::PLATFORM_FILE_OK;
457   FileSystemOperation* operation =
458       file_system_context_->CreateFileSystemOperation(src_url, &error);
459   BeginOperationScoper scope;
460   OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr());
461   if (!operation) {
462     DidFinish(handle, callback, error);
463     return handle.id;
464   }
465   operation->CopyFileLocal(
466       src_url, dest_url, option, progress_callback,
467       base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(),
468                  handle, callback));
469   return handle.id;
470 }
471
472 OperationID FileSystemOperationRunner::MoveFileLocal(
473     const FileSystemURL& src_url,
474     const FileSystemURL& dest_url,
475     CopyOrMoveOption option,
476     const StatusCallback& callback) {
477   base::PlatformFileError error = base::PLATFORM_FILE_OK;
478   FileSystemOperation* operation =
479       file_system_context_->CreateFileSystemOperation(src_url, &error);
480   BeginOperationScoper scope;
481   OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr());
482   if (!operation) {
483     DidFinish(handle, callback, error);
484     return handle.id;
485   }
486   operation->MoveFileLocal(
487       src_url, dest_url, option,
488       base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(),
489                  handle, callback));
490   return handle.id;
491 }
492
493 base::PlatformFileError FileSystemOperationRunner::SyncGetPlatformPath(
494     const FileSystemURL& url,
495     base::FilePath* platform_path) {
496   base::PlatformFileError error = base::PLATFORM_FILE_OK;
497   scoped_ptr<FileSystemOperation> operation(
498       file_system_context_->CreateFileSystemOperation(url, &error));
499   if (!operation.get())
500     return error;
501   return operation->SyncGetPlatformPath(url, platform_path);
502 }
503
504 FileSystemOperationRunner::FileSystemOperationRunner(
505     FileSystemContext* file_system_context)
506     : file_system_context_(file_system_context) {}
507
508 void FileSystemOperationRunner::DidFinish(
509     const OperationHandle& handle,
510     const StatusCallback& callback,
511     base::PlatformFileError rv) {
512   if (handle.scope) {
513     finished_operations_.insert(handle.id);
514     base::MessageLoopProxy::current()->PostTask(
515         FROM_HERE, base::Bind(&FileSystemOperationRunner::DidFinish,
516                               AsWeakPtr(), handle, callback, rv));
517     return;
518   }
519   callback.Run(rv);
520   FinishOperation(handle.id);
521 }
522
523 void FileSystemOperationRunner::DidGetMetadata(
524     const OperationHandle& handle,
525     const GetMetadataCallback& callback,
526     base::PlatformFileError rv,
527     const base::PlatformFileInfo& file_info) {
528   if (handle.scope) {
529     finished_operations_.insert(handle.id);
530     base::MessageLoopProxy::current()->PostTask(
531         FROM_HERE, base::Bind(&FileSystemOperationRunner::DidGetMetadata,
532                               AsWeakPtr(), handle, callback, rv, file_info));
533     return;
534   }
535   callback.Run(rv, file_info);
536   FinishOperation(handle.id);
537 }
538
539 void FileSystemOperationRunner::DidReadDirectory(
540     const OperationHandle& handle,
541     const ReadDirectoryCallback& callback,
542     base::PlatformFileError rv,
543     const std::vector<DirectoryEntry>& entries,
544     bool has_more) {
545   if (handle.scope) {
546     finished_operations_.insert(handle.id);
547     base::MessageLoopProxy::current()->PostTask(
548         FROM_HERE, base::Bind(&FileSystemOperationRunner::DidReadDirectory,
549                               AsWeakPtr(), handle, callback, rv,
550                               entries, has_more));
551     return;
552   }
553   callback.Run(rv, entries, has_more);
554   if (rv != base::PLATFORM_FILE_OK || !has_more)
555     FinishOperation(handle.id);
556 }
557
558 void FileSystemOperationRunner::DidWrite(
559     const OperationHandle& handle,
560     const WriteCallback& callback,
561     base::PlatformFileError rv,
562     int64 bytes,
563     bool complete) {
564   if (handle.scope) {
565     finished_operations_.insert(handle.id);
566     base::MessageLoopProxy::current()->PostTask(
567         FROM_HERE, base::Bind(&FileSystemOperationRunner::DidWrite, AsWeakPtr(),
568                               handle, callback, rv, bytes, complete));
569     return;
570   }
571   callback.Run(rv, bytes, complete);
572   if (rv != base::PLATFORM_FILE_OK || complete)
573     FinishOperation(handle.id);
574 }
575
576 void FileSystemOperationRunner::DidOpenFile(
577     const OperationHandle& handle,
578     const OpenFileCallback& callback,
579     base::PlatformFileError rv,
580     base::PlatformFile file,
581     const base::Closure& on_close_callback,
582     base::ProcessHandle peer_handle) {
583   if (handle.scope) {
584     finished_operations_.insert(handle.id);
585     base::MessageLoopProxy::current()->PostTask(
586         FROM_HERE, base::Bind(&FileSystemOperationRunner::DidOpenFile,
587                               AsWeakPtr(), handle, callback, rv, file,
588                               on_close_callback, peer_handle));
589     return;
590   }
591   callback.Run(rv, file, on_close_callback, peer_handle);
592   FinishOperation(handle.id);
593 }
594
595 void FileSystemOperationRunner::DidCreateSnapshot(
596     const OperationHandle& handle,
597     const SnapshotFileCallback& callback,
598     base::PlatformFileError rv,
599     const base::PlatformFileInfo& file_info,
600     const base::FilePath& platform_path,
601     const scoped_refptr<webkit_blob::ShareableFileReference>& file_ref) {
602   if (handle.scope) {
603     finished_operations_.insert(handle.id);
604     base::MessageLoopProxy::current()->PostTask(
605         FROM_HERE, base::Bind(&FileSystemOperationRunner::DidCreateSnapshot,
606                               AsWeakPtr(), handle, callback, rv, file_info,
607                               platform_path, file_ref));
608     return;
609   }
610   callback.Run(rv, file_info, platform_path, file_ref);
611   FinishOperation(handle.id);
612 }
613
614 void FileSystemOperationRunner::OnCopyProgress(
615     const OperationHandle& handle,
616     const CopyProgressCallback& callback,
617     FileSystemOperation::CopyProgressType type,
618     const FileSystemURL& source_url,
619     const FileSystemURL& dest_url,
620     int64 size) {
621   if (handle.scope) {
622     base::MessageLoopProxy::current()->PostTask(
623         FROM_HERE, base::Bind(
624             &FileSystemOperationRunner::OnCopyProgress,
625             AsWeakPtr(), handle, callback, type, source_url, dest_url, size));
626     return;
627   }
628   callback.Run(type, source_url, dest_url, size);
629 }
630
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, MakeTuple(url));
636   }
637   write_target_urls_[id].insert(url);
638 }
639
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, MakeTuple(url));
645   }
646 }
647
648 FileSystemOperationRunner::OperationHandle
649 FileSystemOperationRunner::BeginOperation(
650     FileSystemOperation* operation,
651     base::WeakPtr<BeginOperationScoper> scope) {
652   OperationHandle handle;
653   handle.id = operations_.Add(operation);
654   handle.scope = scope;
655   return handle;
656 }
657
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, MakeTuple(*iter));
667       }
668     }
669     write_target_urls_.erase(found);
670   }
671
672   // IDMap::Lookup fails if the operation is NULL, so we don't check
673   // operations_.Lookup(id) here.
674
675   operations_.Remove(id);
676   finished_operations_.erase(id);
677
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::PLATFORM_FILE_ERROR_INVALID_OPERATION);
685     stray_cancel_callbacks_.erase(found_cancel);
686   }
687 }
688
689 }  // namespace fileapi