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 "content/child/fileapi/webfilesystem_impl.h"
8 #include "base/lazy_instance.h"
9 #include "base/logging.h"
10 #include "base/message_loop/message_loop_proxy.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "base/synchronization/waitable_event.h"
13 #include "base/threading/thread_local.h"
14 #include "content/child/child_thread.h"
15 #include "content/child/file_info_util.h"
16 #include "content/child/fileapi/file_system_dispatcher.h"
17 #include "content/child/fileapi/webfilewriter_impl.h"
18 #include "content/child/worker_task_runner.h"
19 #include "content/common/fileapi/file_system_messages.h"
20 #include "third_party/WebKit/public/platform/WebFileInfo.h"
21 #include "third_party/WebKit/public/platform/WebFileSystemCallbacks.h"
22 #include "third_party/WebKit/public/platform/WebString.h"
23 #include "third_party/WebKit/public/platform/WebURL.h"
24 #include "third_party/WebKit/public/web/WebHeap.h"
26 #include "webkit/common/fileapi/directory_entry.h"
27 #include "webkit/common/fileapi/file_system_util.h"
29 using blink::WebFileInfo;
30 using blink::WebFileSystemCallbacks;
31 using blink::WebFileSystemEntry;
32 using blink::WebString;
34 using blink::WebVector;
38 class WebFileSystemImpl::WaitableCallbackResults
39 : public base::RefCountedThreadSafe<WaitableCallbackResults> {
41 WaitableCallbackResults()
42 : results_available_event_(true /* manual_reset */,
43 false /* initially_signaled */) {}
45 void AddResultsAndSignal(const base::Closure& results_closure) {
46 base::AutoLock lock(lock_);
47 results_closures_.push_back(results_closure);
48 results_available_event_.Signal();
53 blink::WebHeap::SafePointScope safe_point;
54 results_available_event_.Wait();
60 std::vector<base::Closure> closures;
62 base::AutoLock lock(lock_);
63 results_closures_.swap(closures);
64 results_available_event_.Reset();
66 for (size_t i = 0; i < closures.size(); ++i)
71 friend class base::RefCountedThreadSafe<WaitableCallbackResults>;
73 ~WaitableCallbackResults() {}
76 base::WaitableEvent results_available_event_;
77 std::vector<base::Closure> results_closures_;
78 DISALLOW_COPY_AND_ASSIGN(WaitableCallbackResults);
83 typedef WebFileSystemImpl::WaitableCallbackResults WaitableCallbackResults;
85 base::LazyInstance<base::ThreadLocalPointer<WebFileSystemImpl> >::Leaky
86 g_webfilesystem_tls = LAZY_INSTANCE_INITIALIZER;
88 void DidReceiveSnapshotFile(int request_id) {
89 if (ChildThread::current())
90 ChildThread::current()->Send(
91 new FileSystemHostMsg_DidReceiveSnapshotFile(request_id));
94 int CurrentWorkerId() {
95 return WorkerTaskRunner::Instance()->CurrentWorkerId();
98 template <typename Method, typename Params>
99 void CallDispatcherOnMainThread(
100 base::MessageLoopProxy* loop,
101 Method method, const Params& params,
102 WaitableCallbackResults* waitable_results) {
103 if (!loop->RunsTasksOnCurrentThread()) {
104 loop->PostTask(FROM_HERE,
105 base::Bind(&CallDispatcherOnMainThread<Method, Params>,
106 make_scoped_refptr(loop), method, params,
107 scoped_refptr<WaitableCallbackResults>()));
108 if (!waitable_results)
110 waitable_results->WaitAndRun();
112 if (!ChildThread::current() ||
113 !ChildThread::current()->file_system_dispatcher())
116 DCHECK(!waitable_results);
117 DispatchToMethod(ChildThread::current()->file_system_dispatcher(),
121 enum CallbacksUnregisterMode {
122 UNREGISTER_CALLBACKS,
123 DO_NOT_UNREGISTER_CALLBACKS,
126 // Bridging functions that convert the arguments into Blink objects
127 // (e.g. WebFileInfo, WebString, WebVector<WebFileSystemEntry>)
128 // and call WebFileSystemCallbacks's methods.
129 // These are called by RunCallbacks after crossing threads to ensure
130 // thread safety, because the Blink objects cannot be passed across
131 // threads by base::Bind().
132 void DidSucceed(WebFileSystemCallbacks* callbacks) {
133 callbacks->didSucceed();
136 void DidReadMetadata(const base::File::Info& file_info,
137 WebFileSystemCallbacks* callbacks) {
138 WebFileInfo web_file_info;
139 FileInfoToWebFileInfo(file_info, &web_file_info);
140 callbacks->didReadMetadata(web_file_info);
143 void DidReadDirectory(const std::vector<fileapi::DirectoryEntry>& entries,
144 bool has_more, WebFileSystemCallbacks* callbacks) {
145 WebVector<WebFileSystemEntry> file_system_entries(entries.size());
146 for (size_t i = 0; i < entries.size(); ++i) {
147 file_system_entries[i].name =
148 base::FilePath(entries[i].name).AsUTF16Unsafe();
149 file_system_entries[i].isDirectory = entries[i].is_directory;
151 callbacks->didReadDirectory(file_system_entries, has_more);
154 void DidOpenFileSystem(const base::string16& name, const GURL& root,
155 WebFileSystemCallbacks* callbacks) {
156 callbacks->didOpenFileSystem(name, root);
160 const base::string16& name,
161 const GURL& root_url,
162 fileapi::FileSystemType mount_type,
163 const base::string16& file_path,
165 WebFileSystemCallbacks* callbacks) {
166 callbacks->didResolveURL(
169 static_cast<blink::WebFileSystemType>(mount_type),
174 void DidFail(base::File::Error error, WebFileSystemCallbacks* callbacks) {
175 callbacks->didFail(fileapi::FileErrorToWebFileError(error));
178 // Run WebFileSystemCallbacks's |method| with |params|.
181 const base::Callback<void(WebFileSystemCallbacks*)>& callback,
182 CallbacksUnregisterMode callbacks_unregister_mode) {
183 WebFileSystemImpl* filesystem =
184 WebFileSystemImpl::ThreadSpecificInstance(NULL);
187 WebFileSystemCallbacks callbacks = filesystem->GetCallbacks(callbacks_id);
188 if (callbacks_unregister_mode == UNREGISTER_CALLBACKS)
189 filesystem->UnregisterCallbacks(callbacks_id);
190 callback.Run(&callbacks);
193 void DispatchResultsClosure(int thread_id, int callbacks_id,
194 WaitableCallbackResults* waitable_results,
195 const base::Closure& results_closure) {
196 if (thread_id != CurrentWorkerId()) {
197 if (waitable_results) {
198 // If someone is waiting, this should result in running the closure.
199 waitable_results->AddResultsAndSignal(results_closure);
200 // In case no one is waiting, post a task to run the closure.
201 WorkerTaskRunner::Instance()->PostTask(
203 base::Bind(&WaitableCallbackResults::Run,
204 make_scoped_refptr(waitable_results)));
207 WorkerTaskRunner::Instance()->PostTask(thread_id, results_closure);
210 results_closure.Run();
213 void CallbackFileSystemCallbacks(
214 int thread_id, int callbacks_id,
215 WaitableCallbackResults* waitable_results,
216 const base::Callback<void(WebFileSystemCallbacks*)>& callback,
217 CallbacksUnregisterMode callbacksunregister_mode) {
218 DispatchResultsClosure(
219 thread_id, callbacks_id, waitable_results,
220 base::Bind(&RunCallbacks, callbacks_id, callback,
221 callbacksunregister_mode));
224 //-----------------------------------------------------------------------------
225 // Callback adapters. Callbacks must be called on the original calling thread,
226 // so these callback adapters relay back the results to the calling thread
229 void OpenFileSystemCallbackAdapter(
230 int thread_id, int callbacks_id,
231 WaitableCallbackResults* waitable_results,
232 const std::string& name, const GURL& root) {
233 CallbackFileSystemCallbacks(
234 thread_id, callbacks_id, waitable_results,
235 base::Bind(&DidOpenFileSystem, base::UTF8ToUTF16(name), root),
236 UNREGISTER_CALLBACKS);
239 void ResolveURLCallbackAdapter(
240 int thread_id, int callbacks_id,
241 WaitableCallbackResults* waitable_results,
242 const fileapi::FileSystemInfo& info,
243 const base::FilePath& file_path, bool is_directory) {
244 base::FilePath normalized_path(
245 fileapi::VirtualPath::GetNormalizedFilePath(file_path));
246 CallbackFileSystemCallbacks(
247 thread_id, callbacks_id, waitable_results,
248 base::Bind(&DidResolveURL, base::UTF8ToUTF16(info.name), info.root_url,
250 normalized_path.AsUTF16Unsafe(), is_directory),
251 UNREGISTER_CALLBACKS);
254 void StatusCallbackAdapter(int thread_id, int callbacks_id,
255 WaitableCallbackResults* waitable_results,
256 base::File::Error error) {
257 if (error == base::File::FILE_OK) {
258 CallbackFileSystemCallbacks(
259 thread_id, callbacks_id, waitable_results,
260 base::Bind(&DidSucceed),
261 UNREGISTER_CALLBACKS);
263 CallbackFileSystemCallbacks(
264 thread_id, callbacks_id, waitable_results,
265 base::Bind(&DidFail, error),
266 UNREGISTER_CALLBACKS);
270 void ReadMetadataCallbackAdapter(int thread_id, int callbacks_id,
271 WaitableCallbackResults* waitable_results,
272 const base::File::Info& file_info) {
273 CallbackFileSystemCallbacks(
274 thread_id, callbacks_id, waitable_results,
275 base::Bind(&DidReadMetadata, file_info),
276 UNREGISTER_CALLBACKS);
279 void ReadDirectoryCallbackAdapter(
280 int thread_id, int callbacks_id, WaitableCallbackResults* waitable_results,
281 const std::vector<fileapi::DirectoryEntry>& entries,
283 CallbackFileSystemCallbacks(
284 thread_id, callbacks_id, waitable_results,
285 base::Bind(&DidReadDirectory, entries, has_more),
286 has_more ? DO_NOT_UNREGISTER_CALLBACKS : UNREGISTER_CALLBACKS);
289 void DidCreateFileWriter(
292 blink::WebFileWriterClient* client,
293 base::MessageLoopProxy* main_thread_loop,
294 const base::File::Info& file_info) {
295 WebFileSystemImpl* filesystem =
296 WebFileSystemImpl::ThreadSpecificInstance(NULL);
300 WebFileSystemCallbacks callbacks = filesystem->GetCallbacks(callbacks_id);
301 filesystem->UnregisterCallbacks(callbacks_id);
303 if (file_info.is_directory || file_info.size < 0) {
304 callbacks.didFail(blink::WebFileErrorInvalidState);
307 WebFileWriterImpl::Type type =
308 callbacks.shouldBlockUntilCompletion() ?
309 WebFileWriterImpl::TYPE_SYNC : WebFileWriterImpl::TYPE_ASYNC;
310 callbacks.didCreateFileWriter(
311 new WebFileWriterImpl(path, client, type, main_thread_loop),
315 void CreateFileWriterCallbackAdapter(
316 int thread_id, int callbacks_id,
317 WaitableCallbackResults* waitable_results,
318 base::MessageLoopProxy* main_thread_loop,
320 blink::WebFileWriterClient* client,
321 const base::File::Info& file_info) {
322 DispatchResultsClosure(
323 thread_id, callbacks_id, waitable_results,
324 base::Bind(&DidCreateFileWriter, callbacks_id, path, client,
325 make_scoped_refptr(main_thread_loop), file_info));
328 void DidCreateSnapshotFile(
330 base::MessageLoopProxy* main_thread_loop,
331 const base::File::Info& file_info,
332 const base::FilePath& platform_path,
334 WebFileSystemImpl* filesystem =
335 WebFileSystemImpl::ThreadSpecificInstance(NULL);
339 WebFileSystemCallbacks callbacks = filesystem->GetCallbacks(callbacks_id);
340 filesystem->UnregisterCallbacks(callbacks_id);
342 WebFileInfo web_file_info;
343 FileInfoToWebFileInfo(file_info, &web_file_info);
344 web_file_info.platformPath = platform_path.AsUTF16Unsafe();
345 callbacks.didCreateSnapshotFile(web_file_info);
347 // TODO(michaeln,kinuko): Use ThreadSafeSender when Blob becomes
349 main_thread_loop->PostTask(
350 FROM_HERE, base::Bind(&DidReceiveSnapshotFile, request_id));
353 void CreateSnapshotFileCallbackAdapter(
354 int thread_id, int callbacks_id,
355 WaitableCallbackResults* waitable_results,
356 base::MessageLoopProxy* main_thread_loop,
357 const base::File::Info& file_info,
358 const base::FilePath& platform_path,
360 DispatchResultsClosure(
361 thread_id, callbacks_id, waitable_results,
362 base::Bind(&DidCreateSnapshotFile, callbacks_id,
363 make_scoped_refptr(main_thread_loop),
364 file_info, platform_path, request_id));
369 //-----------------------------------------------------------------------------
372 WebFileSystemImpl* WebFileSystemImpl::ThreadSpecificInstance(
373 base::MessageLoopProxy* main_thread_loop) {
374 if (g_webfilesystem_tls.Pointer()->Get() || !main_thread_loop)
375 return g_webfilesystem_tls.Pointer()->Get();
376 WebFileSystemImpl* filesystem = new WebFileSystemImpl(main_thread_loop);
377 if (WorkerTaskRunner::Instance()->CurrentWorkerId())
378 WorkerTaskRunner::Instance()->AddStopObserver(filesystem);
382 void WebFileSystemImpl::DeleteThreadSpecificInstance() {
383 DCHECK(!WorkerTaskRunner::Instance()->CurrentWorkerId());
384 if (g_webfilesystem_tls.Pointer()->Get())
385 delete g_webfilesystem_tls.Pointer()->Get();
388 WebFileSystemImpl::WebFileSystemImpl(base::MessageLoopProxy* main_thread_loop)
389 : main_thread_loop_(main_thread_loop),
390 next_callbacks_id_(1) {
391 g_webfilesystem_tls.Pointer()->Set(this);
394 WebFileSystemImpl::~WebFileSystemImpl() {
395 g_webfilesystem_tls.Pointer()->Set(NULL);
398 void WebFileSystemImpl::OnWorkerRunLoopStopped() {
402 void WebFileSystemImpl::openFileSystem(
403 const blink::WebURL& storage_partition,
404 blink::WebFileSystemType type,
405 WebFileSystemCallbacks callbacks) {
406 int callbacks_id = RegisterCallbacks(callbacks);
407 scoped_refptr<WaitableCallbackResults> waitable_results =
408 MaybeCreateWaitableResults(callbacks, callbacks_id);
409 CallDispatcherOnMainThread(
410 main_thread_loop_.get(),
411 &FileSystemDispatcher::OpenFileSystem,
412 MakeTuple(GURL(storage_partition),
413 static_cast<fileapi::FileSystemType>(type),
414 base::Bind(&OpenFileSystemCallbackAdapter,
415 CurrentWorkerId(), callbacks_id, waitable_results),
416 base::Bind(&StatusCallbackAdapter,
417 CurrentWorkerId(), callbacks_id, waitable_results)),
418 waitable_results.get());
421 void WebFileSystemImpl::resolveURL(
422 const blink::WebURL& filesystem_url,
423 WebFileSystemCallbacks callbacks) {
424 int callbacks_id = RegisterCallbacks(callbacks);
425 scoped_refptr<WaitableCallbackResults> waitable_results =
426 MaybeCreateWaitableResults(callbacks, callbacks_id);
427 CallDispatcherOnMainThread(
428 main_thread_loop_.get(),
429 &FileSystemDispatcher::ResolveURL,
430 MakeTuple(GURL(filesystem_url),
431 base::Bind(&ResolveURLCallbackAdapter,
432 CurrentWorkerId(), callbacks_id, waitable_results),
433 base::Bind(&StatusCallbackAdapter,
434 CurrentWorkerId(), callbacks_id, waitable_results)),
435 waitable_results.get());
438 void WebFileSystemImpl::deleteFileSystem(
439 const blink::WebURL& storage_partition,
440 blink::WebFileSystemType type,
441 WebFileSystemCallbacks callbacks) {
442 int callbacks_id = RegisterCallbacks(callbacks);
443 scoped_refptr<WaitableCallbackResults> waitable_results =
444 MaybeCreateWaitableResults(callbacks, callbacks_id);
445 CallDispatcherOnMainThread(
446 main_thread_loop_.get(),
447 &FileSystemDispatcher::DeleteFileSystem,
448 MakeTuple(GURL(storage_partition),
449 static_cast<fileapi::FileSystemType>(type),
450 base::Bind(&StatusCallbackAdapter,
451 CurrentWorkerId(), callbacks_id, waitable_results)),
452 waitable_results.get());
455 void WebFileSystemImpl::move(
456 const blink::WebURL& src_path,
457 const blink::WebURL& dest_path,
458 WebFileSystemCallbacks callbacks) {
459 int callbacks_id = RegisterCallbacks(callbacks);
460 scoped_refptr<WaitableCallbackResults> waitable_results =
461 MaybeCreateWaitableResults(callbacks, callbacks_id);
462 CallDispatcherOnMainThread(
463 main_thread_loop_.get(),
464 &FileSystemDispatcher::Move,
465 MakeTuple(GURL(src_path), GURL(dest_path),
466 base::Bind(&StatusCallbackAdapter,
467 CurrentWorkerId(), callbacks_id, waitable_results)),
468 waitable_results.get());
471 void WebFileSystemImpl::copy(
472 const blink::WebURL& src_path,
473 const blink::WebURL& dest_path,
474 WebFileSystemCallbacks callbacks) {
475 int callbacks_id = RegisterCallbacks(callbacks);
476 scoped_refptr<WaitableCallbackResults> waitable_results =
477 MaybeCreateWaitableResults(callbacks, callbacks_id);
478 CallDispatcherOnMainThread(
479 main_thread_loop_.get(),
480 &FileSystemDispatcher::Copy,
481 MakeTuple(GURL(src_path), GURL(dest_path),
482 base::Bind(&StatusCallbackAdapter,
483 CurrentWorkerId(), callbacks_id, waitable_results)),
484 waitable_results.get());
487 void WebFileSystemImpl::remove(
488 const blink::WebURL& path,
489 WebFileSystemCallbacks callbacks) {
490 int callbacks_id = RegisterCallbacks(callbacks);
491 scoped_refptr<WaitableCallbackResults> waitable_results =
492 MaybeCreateWaitableResults(callbacks, callbacks_id);
493 CallDispatcherOnMainThread(
494 main_thread_loop_.get(),
495 &FileSystemDispatcher::Remove,
496 MakeTuple(GURL(path), false /* recursive */,
497 base::Bind(&StatusCallbackAdapter,
498 CurrentWorkerId(), callbacks_id, waitable_results)),
499 waitable_results.get());
502 void WebFileSystemImpl::removeRecursively(
503 const blink::WebURL& path,
504 WebFileSystemCallbacks callbacks) {
505 int callbacks_id = RegisterCallbacks(callbacks);
506 scoped_refptr<WaitableCallbackResults> waitable_results =
507 MaybeCreateWaitableResults(callbacks, callbacks_id);
508 CallDispatcherOnMainThread(
509 main_thread_loop_.get(),
510 &FileSystemDispatcher::Remove,
511 MakeTuple(GURL(path), true /* recursive */,
512 base::Bind(&StatusCallbackAdapter,
513 CurrentWorkerId(), callbacks_id, waitable_results)),
514 waitable_results.get());
517 void WebFileSystemImpl::readMetadata(
518 const blink::WebURL& path,
519 WebFileSystemCallbacks callbacks) {
520 int callbacks_id = RegisterCallbacks(callbacks);
521 scoped_refptr<WaitableCallbackResults> waitable_results =
522 MaybeCreateWaitableResults(callbacks, callbacks_id);
523 CallDispatcherOnMainThread(
524 main_thread_loop_.get(),
525 &FileSystemDispatcher::ReadMetadata,
526 MakeTuple(GURL(path),
527 base::Bind(&ReadMetadataCallbackAdapter,
528 CurrentWorkerId(), callbacks_id, waitable_results),
529 base::Bind(&StatusCallbackAdapter,
530 CurrentWorkerId(), callbacks_id, waitable_results)),
531 waitable_results.get());
534 void WebFileSystemImpl::createFile(
535 const blink::WebURL& path,
537 WebFileSystemCallbacks callbacks) {
538 int callbacks_id = RegisterCallbacks(callbacks);
539 scoped_refptr<WaitableCallbackResults> waitable_results =
540 MaybeCreateWaitableResults(callbacks, callbacks_id);
541 CallDispatcherOnMainThread(
542 main_thread_loop_.get(),
543 &FileSystemDispatcher::CreateFile,
544 MakeTuple(GURL(path), exclusive,
545 base::Bind(&StatusCallbackAdapter,
546 CurrentWorkerId(), callbacks_id, waitable_results)),
547 waitable_results.get());
550 void WebFileSystemImpl::createDirectory(
551 const blink::WebURL& path,
553 WebFileSystemCallbacks callbacks) {
554 int callbacks_id = RegisterCallbacks(callbacks);
555 scoped_refptr<WaitableCallbackResults> waitable_results =
556 MaybeCreateWaitableResults(callbacks, callbacks_id);
557 CallDispatcherOnMainThread(
558 main_thread_loop_.get(),
559 &FileSystemDispatcher::CreateDirectory,
560 MakeTuple(GURL(path), exclusive, false /* recursive */,
561 base::Bind(&StatusCallbackAdapter,
562 CurrentWorkerId(), callbacks_id, waitable_results)),
563 waitable_results.get());
566 void WebFileSystemImpl::fileExists(
567 const blink::WebURL& path,
568 WebFileSystemCallbacks callbacks) {
569 int callbacks_id = RegisterCallbacks(callbacks);
570 scoped_refptr<WaitableCallbackResults> waitable_results =
571 MaybeCreateWaitableResults(callbacks, callbacks_id);
572 CallDispatcherOnMainThread(
573 main_thread_loop_.get(),
574 &FileSystemDispatcher::Exists,
575 MakeTuple(GURL(path), false /* directory */,
576 base::Bind(&StatusCallbackAdapter,
577 CurrentWorkerId(), callbacks_id, waitable_results)),
578 waitable_results.get());
581 void WebFileSystemImpl::directoryExists(
582 const blink::WebURL& path,
583 WebFileSystemCallbacks callbacks) {
584 int callbacks_id = RegisterCallbacks(callbacks);
585 scoped_refptr<WaitableCallbackResults> waitable_results =
586 MaybeCreateWaitableResults(callbacks, callbacks_id);
587 CallDispatcherOnMainThread(
588 main_thread_loop_.get(),
589 &FileSystemDispatcher::Exists,
590 MakeTuple(GURL(path), true /* directory */,
591 base::Bind(&StatusCallbackAdapter,
592 CurrentWorkerId(), callbacks_id, waitable_results)),
593 waitable_results.get());
596 int WebFileSystemImpl::readDirectory(
597 const blink::WebURL& path,
598 WebFileSystemCallbacks callbacks) {
599 int callbacks_id = RegisterCallbacks(callbacks);
600 scoped_refptr<WaitableCallbackResults> waitable_results =
601 MaybeCreateWaitableResults(callbacks, callbacks_id);
602 CallDispatcherOnMainThread(
603 main_thread_loop_.get(),
604 &FileSystemDispatcher::ReadDirectory,
605 MakeTuple(GURL(path),
606 base::Bind(&ReadDirectoryCallbackAdapter,
607 CurrentWorkerId(), callbacks_id, waitable_results),
608 base::Bind(&StatusCallbackAdapter,
609 CurrentWorkerId(), callbacks_id, waitable_results)),
610 waitable_results.get());
614 void WebFileSystemImpl::createFileWriter(
616 blink::WebFileWriterClient* client,
617 WebFileSystemCallbacks callbacks) {
618 int callbacks_id = RegisterCallbacks(callbacks);
619 scoped_refptr<WaitableCallbackResults> waitable_results =
620 MaybeCreateWaitableResults(callbacks, callbacks_id);
621 CallDispatcherOnMainThread(
622 main_thread_loop_.get(),
623 &FileSystemDispatcher::ReadMetadata,
624 MakeTuple(GURL(path),
625 base::Bind(&CreateFileWriterCallbackAdapter,
626 CurrentWorkerId(), callbacks_id, waitable_results,
627 main_thread_loop_, GURL(path), client),
628 base::Bind(&StatusCallbackAdapter,
629 CurrentWorkerId(), callbacks_id, waitable_results)),
630 waitable_results.get());
633 void WebFileSystemImpl::createSnapshotFileAndReadMetadata(
634 const blink::WebURL& path,
635 WebFileSystemCallbacks callbacks) {
636 int callbacks_id = RegisterCallbacks(callbacks);
637 scoped_refptr<WaitableCallbackResults> waitable_results =
638 MaybeCreateWaitableResults(callbacks, callbacks_id);
639 CallDispatcherOnMainThread(
640 main_thread_loop_.get(),
641 &FileSystemDispatcher::CreateSnapshotFile,
642 MakeTuple(GURL(path),
643 base::Bind(&CreateSnapshotFileCallbackAdapter,
644 CurrentWorkerId(), callbacks_id, waitable_results,
646 base::Bind(&StatusCallbackAdapter,
647 CurrentWorkerId(), callbacks_id, waitable_results)),
648 waitable_results.get());
651 bool WebFileSystemImpl::waitForAdditionalResult(int callbacksId) {
652 WaitableCallbackResultsMap::iterator found =
653 waitable_results_.find(callbacksId);
654 if (found == waitable_results_.end())
657 found->second->WaitAndRun();
661 int WebFileSystemImpl::RegisterCallbacks(
662 const WebFileSystemCallbacks& callbacks) {
663 DCHECK(CalledOnValidThread());
664 int id = next_callbacks_id_++;
665 callbacks_[id] = callbacks;
669 WebFileSystemCallbacks WebFileSystemImpl::GetCallbacks(int callbacks_id) {
670 DCHECK(CalledOnValidThread());
671 CallbacksMap::iterator found = callbacks_.find(callbacks_id);
672 DCHECK(found != callbacks_.end());
673 return found->second;
676 void WebFileSystemImpl::UnregisterCallbacks(int callbacks_id) {
677 DCHECK(CalledOnValidThread());
678 CallbacksMap::iterator found = callbacks_.find(callbacks_id);
679 DCHECK(found != callbacks_.end());
680 callbacks_.erase(found);
682 waitable_results_.erase(callbacks_id);
685 WaitableCallbackResults* WebFileSystemImpl::MaybeCreateWaitableResults(
686 const WebFileSystemCallbacks& callbacks, int callbacks_id) {
687 if (!callbacks.shouldBlockUntilCompletion())
689 WaitableCallbackResults* results = new WaitableCallbackResults();
690 waitable_results_[callbacks_id] = results;
694 } // namespace content