Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / content / child / fileapi / webfilesystem_impl.cc
blob37c4ca05eefb4347b64beda67ead833f2ada3344
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"
7 #include "base/bind.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"
25 #include "url/gurl.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;
33 using blink::WebURL;
34 using blink::WebVector;
36 namespace content {
38 class WebFileSystemImpl::WaitableCallbackResults
39 : public base::RefCountedThreadSafe<WaitableCallbackResults> {
40 public:
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();
51 void WaitAndRun() {
53 blink::WebHeap::SafePointScope safe_point;
54 results_available_event_.Wait();
56 Run();
59 void Run() {
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)
67 closures[i].Run();
70 private:
71 friend class base::RefCountedThreadSafe<WaitableCallbackResults>;
73 ~WaitableCallbackResults() {}
75 base::Lock lock_;
76 base::WaitableEvent results_available_event_;
77 std::vector<base::Closure> results_closures_;
78 DISALLOW_COPY_AND_ASSIGN(WaitableCallbackResults);
81 namespace {
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)
109 return;
110 waitable_results->WaitAndRun();
112 if (!ChildThread::current() ||
113 !ChildThread::current()->file_system_dispatcher())
114 return;
116 DCHECK(!waitable_results);
117 DispatchToMethod(ChildThread::current()->file_system_dispatcher(),
118 method, params);
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<storage::DirectoryEntry>& entries,
144 bool has_more,
145 WebFileSystemCallbacks* callbacks) {
146 WebVector<WebFileSystemEntry> file_system_entries(entries.size());
147 for (size_t i = 0; i < entries.size(); ++i) {
148 file_system_entries[i].name =
149 base::FilePath(entries[i].name).AsUTF16Unsafe();
150 file_system_entries[i].isDirectory = entries[i].is_directory;
152 callbacks->didReadDirectory(file_system_entries, has_more);
155 void DidOpenFileSystem(const base::string16& name, const GURL& root,
156 WebFileSystemCallbacks* callbacks) {
157 callbacks->didOpenFileSystem(name, root);
160 void DidResolveURL(const base::string16& name,
161 const GURL& root_url,
162 storage::FileSystemType mount_type,
163 const base::string16& file_path,
164 bool is_directory,
165 WebFileSystemCallbacks* callbacks) {
166 callbacks->didResolveURL(
167 name,
168 root_url,
169 static_cast<blink::WebFileSystemType>(mount_type),
170 file_path,
171 is_directory);
174 void DidFail(base::File::Error error, WebFileSystemCallbacks* callbacks) {
175 callbacks->didFail(storage::FileErrorToWebFileError(error));
178 // Run WebFileSystemCallbacks's |method| with |params|.
179 void RunCallbacks(
180 int callbacks_id,
181 const base::Callback<void(WebFileSystemCallbacks*)>& callback,
182 CallbacksUnregisterMode callbacks_unregister_mode) {
183 WebFileSystemImpl* filesystem =
184 WebFileSystemImpl::ThreadSpecificInstance(NULL);
185 if (!filesystem)
186 return;
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(
202 thread_id,
203 base::Bind(&WaitableCallbackResults::Run,
204 make_scoped_refptr(waitable_results)));
205 return;
207 WorkerTaskRunner::Instance()->PostTask(thread_id, results_closure);
208 return;
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
227 // if necessary.
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(int thread_id,
240 int callbacks_id,
241 WaitableCallbackResults* waitable_results,
242 const storage::FileSystemInfo& info,
243 const base::FilePath& file_path,
244 bool is_directory) {
245 base::FilePath normalized_path(
246 storage::VirtualPath::GetNormalizedFilePath(file_path));
247 CallbackFileSystemCallbacks(
248 thread_id, callbacks_id, waitable_results,
249 base::Bind(&DidResolveURL, base::UTF8ToUTF16(info.name), info.root_url,
250 info.mount_type,
251 normalized_path.AsUTF16Unsafe(), is_directory),
252 UNREGISTER_CALLBACKS);
255 void StatusCallbackAdapter(int thread_id, int callbacks_id,
256 WaitableCallbackResults* waitable_results,
257 base::File::Error error) {
258 if (error == base::File::FILE_OK) {
259 CallbackFileSystemCallbacks(
260 thread_id, callbacks_id, waitable_results,
261 base::Bind(&DidSucceed),
262 UNREGISTER_CALLBACKS);
263 } else {
264 CallbackFileSystemCallbacks(
265 thread_id, callbacks_id, waitable_results,
266 base::Bind(&DidFail, error),
267 UNREGISTER_CALLBACKS);
271 void ReadMetadataCallbackAdapter(int thread_id, int callbacks_id,
272 WaitableCallbackResults* waitable_results,
273 const base::File::Info& file_info) {
274 CallbackFileSystemCallbacks(
275 thread_id, callbacks_id, waitable_results,
276 base::Bind(&DidReadMetadata, file_info),
277 UNREGISTER_CALLBACKS);
280 void ReadDirectoryCallbackAdapter(
281 int thread_id,
282 int callbacks_id,
283 WaitableCallbackResults* waitable_results,
284 const std::vector<storage::DirectoryEntry>& entries,
285 bool has_more) {
286 CallbackFileSystemCallbacks(
287 thread_id, callbacks_id, waitable_results,
288 base::Bind(&DidReadDirectory, entries, has_more),
289 has_more ? DO_NOT_UNREGISTER_CALLBACKS : UNREGISTER_CALLBACKS);
292 void DidCreateFileWriter(
293 int callbacks_id,
294 const GURL& path,
295 blink::WebFileWriterClient* client,
296 base::MessageLoopProxy* main_thread_loop,
297 const base::File::Info& file_info) {
298 WebFileSystemImpl* filesystem =
299 WebFileSystemImpl::ThreadSpecificInstance(NULL);
300 if (!filesystem)
301 return;
303 WebFileSystemCallbacks callbacks = filesystem->GetCallbacks(callbacks_id);
304 filesystem->UnregisterCallbacks(callbacks_id);
306 if (file_info.is_directory || file_info.size < 0) {
307 callbacks.didFail(blink::WebFileErrorInvalidState);
308 return;
310 WebFileWriterImpl::Type type =
311 callbacks.shouldBlockUntilCompletion() ?
312 WebFileWriterImpl::TYPE_SYNC : WebFileWriterImpl::TYPE_ASYNC;
313 callbacks.didCreateFileWriter(
314 new WebFileWriterImpl(path, client, type, main_thread_loop),
315 file_info.size);
318 void CreateFileWriterCallbackAdapter(
319 int thread_id, int callbacks_id,
320 WaitableCallbackResults* waitable_results,
321 base::MessageLoopProxy* main_thread_loop,
322 const GURL& path,
323 blink::WebFileWriterClient* client,
324 const base::File::Info& file_info) {
325 DispatchResultsClosure(
326 thread_id, callbacks_id, waitable_results,
327 base::Bind(&DidCreateFileWriter, callbacks_id, path, client,
328 make_scoped_refptr(main_thread_loop), file_info));
331 void DidCreateSnapshotFile(
332 int callbacks_id,
333 base::MessageLoopProxy* main_thread_loop,
334 const base::File::Info& file_info,
335 const base::FilePath& platform_path,
336 int request_id) {
337 WebFileSystemImpl* filesystem =
338 WebFileSystemImpl::ThreadSpecificInstance(NULL);
339 if (!filesystem)
340 return;
342 WebFileSystemCallbacks callbacks = filesystem->GetCallbacks(callbacks_id);
343 filesystem->UnregisterCallbacks(callbacks_id);
345 WebFileInfo web_file_info;
346 FileInfoToWebFileInfo(file_info, &web_file_info);
347 web_file_info.platformPath = platform_path.AsUTF16Unsafe();
348 callbacks.didCreateSnapshotFile(web_file_info);
350 // TODO(michaeln,kinuko): Use ThreadSafeSender when Blob becomes
351 // non-bridge model.
352 main_thread_loop->PostTask(
353 FROM_HERE, base::Bind(&DidReceiveSnapshotFile, request_id));
356 void CreateSnapshotFileCallbackAdapter(
357 int thread_id, int callbacks_id,
358 WaitableCallbackResults* waitable_results,
359 base::MessageLoopProxy* main_thread_loop,
360 const base::File::Info& file_info,
361 const base::FilePath& platform_path,
362 int request_id) {
363 DispatchResultsClosure(
364 thread_id, callbacks_id, waitable_results,
365 base::Bind(&DidCreateSnapshotFile, callbacks_id,
366 make_scoped_refptr(main_thread_loop),
367 file_info, platform_path, request_id));
370 } // namespace
372 //-----------------------------------------------------------------------------
373 // WebFileSystemImpl
375 WebFileSystemImpl* WebFileSystemImpl::ThreadSpecificInstance(
376 base::MessageLoopProxy* main_thread_loop) {
377 if (g_webfilesystem_tls.Pointer()->Get() || !main_thread_loop)
378 return g_webfilesystem_tls.Pointer()->Get();
379 WebFileSystemImpl* filesystem = new WebFileSystemImpl(main_thread_loop);
380 if (WorkerTaskRunner::Instance()->CurrentWorkerId())
381 WorkerTaskRunner::Instance()->AddStopObserver(filesystem);
382 return filesystem;
385 void WebFileSystemImpl::DeleteThreadSpecificInstance() {
386 DCHECK(!WorkerTaskRunner::Instance()->CurrentWorkerId());
387 if (g_webfilesystem_tls.Pointer()->Get())
388 delete g_webfilesystem_tls.Pointer()->Get();
391 WebFileSystemImpl::WebFileSystemImpl(base::MessageLoopProxy* main_thread_loop)
392 : main_thread_loop_(main_thread_loop),
393 next_callbacks_id_(1) {
394 g_webfilesystem_tls.Pointer()->Set(this);
397 WebFileSystemImpl::~WebFileSystemImpl() {
398 g_webfilesystem_tls.Pointer()->Set(NULL);
401 void WebFileSystemImpl::OnWorkerRunLoopStopped() {
402 delete this;
405 void WebFileSystemImpl::openFileSystem(
406 const blink::WebURL& storage_partition,
407 blink::WebFileSystemType type,
408 WebFileSystemCallbacks callbacks) {
409 int callbacks_id = RegisterCallbacks(callbacks);
410 scoped_refptr<WaitableCallbackResults> waitable_results =
411 MaybeCreateWaitableResults(callbacks, callbacks_id);
412 CallDispatcherOnMainThread(
413 main_thread_loop_.get(),
414 &FileSystemDispatcher::OpenFileSystem,
415 MakeTuple(GURL(storage_partition),
416 static_cast<storage::FileSystemType>(type),
417 base::Bind(&OpenFileSystemCallbackAdapter,
418 CurrentWorkerId(),
419 callbacks_id,
420 waitable_results),
421 base::Bind(&StatusCallbackAdapter,
422 CurrentWorkerId(),
423 callbacks_id,
424 waitable_results)),
425 waitable_results.get());
428 void WebFileSystemImpl::resolveURL(
429 const blink::WebURL& filesystem_url,
430 WebFileSystemCallbacks callbacks) {
431 int callbacks_id = RegisterCallbacks(callbacks);
432 scoped_refptr<WaitableCallbackResults> waitable_results =
433 MaybeCreateWaitableResults(callbacks, callbacks_id);
434 CallDispatcherOnMainThread(
435 main_thread_loop_.get(),
436 &FileSystemDispatcher::ResolveURL,
437 MakeTuple(GURL(filesystem_url),
438 base::Bind(&ResolveURLCallbackAdapter,
439 CurrentWorkerId(), callbacks_id, waitable_results),
440 base::Bind(&StatusCallbackAdapter,
441 CurrentWorkerId(), callbacks_id, waitable_results)),
442 waitable_results.get());
445 void WebFileSystemImpl::deleteFileSystem(
446 const blink::WebURL& storage_partition,
447 blink::WebFileSystemType type,
448 WebFileSystemCallbacks callbacks) {
449 int callbacks_id = RegisterCallbacks(callbacks);
450 scoped_refptr<WaitableCallbackResults> waitable_results =
451 MaybeCreateWaitableResults(callbacks, callbacks_id);
452 CallDispatcherOnMainThread(
453 main_thread_loop_.get(),
454 &FileSystemDispatcher::DeleteFileSystem,
455 MakeTuple(GURL(storage_partition),
456 static_cast<storage::FileSystemType>(type),
457 base::Bind(&StatusCallbackAdapter,
458 CurrentWorkerId(),
459 callbacks_id,
460 waitable_results)),
461 waitable_results.get());
464 void WebFileSystemImpl::move(
465 const blink::WebURL& src_path,
466 const blink::WebURL& dest_path,
467 WebFileSystemCallbacks callbacks) {
468 int callbacks_id = RegisterCallbacks(callbacks);
469 scoped_refptr<WaitableCallbackResults> waitable_results =
470 MaybeCreateWaitableResults(callbacks, callbacks_id);
471 CallDispatcherOnMainThread(
472 main_thread_loop_.get(),
473 &FileSystemDispatcher::Move,
474 MakeTuple(GURL(src_path), GURL(dest_path),
475 base::Bind(&StatusCallbackAdapter,
476 CurrentWorkerId(), callbacks_id, waitable_results)),
477 waitable_results.get());
480 void WebFileSystemImpl::copy(
481 const blink::WebURL& src_path,
482 const blink::WebURL& dest_path,
483 WebFileSystemCallbacks callbacks) {
484 int callbacks_id = RegisterCallbacks(callbacks);
485 scoped_refptr<WaitableCallbackResults> waitable_results =
486 MaybeCreateWaitableResults(callbacks, callbacks_id);
487 CallDispatcherOnMainThread(
488 main_thread_loop_.get(),
489 &FileSystemDispatcher::Copy,
490 MakeTuple(GURL(src_path), GURL(dest_path),
491 base::Bind(&StatusCallbackAdapter,
492 CurrentWorkerId(), callbacks_id, waitable_results)),
493 waitable_results.get());
496 void WebFileSystemImpl::remove(
497 const blink::WebURL& path,
498 WebFileSystemCallbacks callbacks) {
499 int callbacks_id = RegisterCallbacks(callbacks);
500 scoped_refptr<WaitableCallbackResults> waitable_results =
501 MaybeCreateWaitableResults(callbacks, callbacks_id);
502 CallDispatcherOnMainThread(
503 main_thread_loop_.get(),
504 &FileSystemDispatcher::Remove,
505 MakeTuple(GURL(path), false /* recursive */,
506 base::Bind(&StatusCallbackAdapter,
507 CurrentWorkerId(), callbacks_id, waitable_results)),
508 waitable_results.get());
511 void WebFileSystemImpl::removeRecursively(
512 const blink::WebURL& path,
513 WebFileSystemCallbacks callbacks) {
514 int callbacks_id = RegisterCallbacks(callbacks);
515 scoped_refptr<WaitableCallbackResults> waitable_results =
516 MaybeCreateWaitableResults(callbacks, callbacks_id);
517 CallDispatcherOnMainThread(
518 main_thread_loop_.get(),
519 &FileSystemDispatcher::Remove,
520 MakeTuple(GURL(path), true /* recursive */,
521 base::Bind(&StatusCallbackAdapter,
522 CurrentWorkerId(), callbacks_id, waitable_results)),
523 waitable_results.get());
526 void WebFileSystemImpl::readMetadata(
527 const blink::WebURL& path,
528 WebFileSystemCallbacks callbacks) {
529 int callbacks_id = RegisterCallbacks(callbacks);
530 scoped_refptr<WaitableCallbackResults> waitable_results =
531 MaybeCreateWaitableResults(callbacks, callbacks_id);
532 CallDispatcherOnMainThread(
533 main_thread_loop_.get(),
534 &FileSystemDispatcher::ReadMetadata,
535 MakeTuple(GURL(path),
536 base::Bind(&ReadMetadataCallbackAdapter,
537 CurrentWorkerId(), callbacks_id, waitable_results),
538 base::Bind(&StatusCallbackAdapter,
539 CurrentWorkerId(), callbacks_id, waitable_results)),
540 waitable_results.get());
543 void WebFileSystemImpl::createFile(
544 const blink::WebURL& path,
545 bool exclusive,
546 WebFileSystemCallbacks callbacks) {
547 int callbacks_id = RegisterCallbacks(callbacks);
548 scoped_refptr<WaitableCallbackResults> waitable_results =
549 MaybeCreateWaitableResults(callbacks, callbacks_id);
550 CallDispatcherOnMainThread(
551 main_thread_loop_.get(),
552 &FileSystemDispatcher::CreateFile,
553 MakeTuple(GURL(path), exclusive,
554 base::Bind(&StatusCallbackAdapter,
555 CurrentWorkerId(), callbacks_id, waitable_results)),
556 waitable_results.get());
559 void WebFileSystemImpl::createDirectory(
560 const blink::WebURL& path,
561 bool exclusive,
562 WebFileSystemCallbacks callbacks) {
563 int callbacks_id = RegisterCallbacks(callbacks);
564 scoped_refptr<WaitableCallbackResults> waitable_results =
565 MaybeCreateWaitableResults(callbacks, callbacks_id);
566 CallDispatcherOnMainThread(
567 main_thread_loop_.get(),
568 &FileSystemDispatcher::CreateDirectory,
569 MakeTuple(GURL(path), exclusive, false /* recursive */,
570 base::Bind(&StatusCallbackAdapter,
571 CurrentWorkerId(), callbacks_id, waitable_results)),
572 waitable_results.get());
575 void WebFileSystemImpl::fileExists(
576 const blink::WebURL& path,
577 WebFileSystemCallbacks callbacks) {
578 int callbacks_id = RegisterCallbacks(callbacks);
579 scoped_refptr<WaitableCallbackResults> waitable_results =
580 MaybeCreateWaitableResults(callbacks, callbacks_id);
581 CallDispatcherOnMainThread(
582 main_thread_loop_.get(),
583 &FileSystemDispatcher::Exists,
584 MakeTuple(GURL(path), false /* directory */,
585 base::Bind(&StatusCallbackAdapter,
586 CurrentWorkerId(), callbacks_id, waitable_results)),
587 waitable_results.get());
590 void WebFileSystemImpl::directoryExists(
591 const blink::WebURL& path,
592 WebFileSystemCallbacks callbacks) {
593 int callbacks_id = RegisterCallbacks(callbacks);
594 scoped_refptr<WaitableCallbackResults> waitable_results =
595 MaybeCreateWaitableResults(callbacks, callbacks_id);
596 CallDispatcherOnMainThread(
597 main_thread_loop_.get(),
598 &FileSystemDispatcher::Exists,
599 MakeTuple(GURL(path), true /* directory */,
600 base::Bind(&StatusCallbackAdapter,
601 CurrentWorkerId(), callbacks_id, waitable_results)),
602 waitable_results.get());
605 int WebFileSystemImpl::readDirectory(
606 const blink::WebURL& path,
607 WebFileSystemCallbacks callbacks) {
608 int callbacks_id = RegisterCallbacks(callbacks);
609 scoped_refptr<WaitableCallbackResults> waitable_results =
610 MaybeCreateWaitableResults(callbacks, callbacks_id);
611 CallDispatcherOnMainThread(
612 main_thread_loop_.get(),
613 &FileSystemDispatcher::ReadDirectory,
614 MakeTuple(GURL(path),
615 base::Bind(&ReadDirectoryCallbackAdapter,
616 CurrentWorkerId(), callbacks_id, waitable_results),
617 base::Bind(&StatusCallbackAdapter,
618 CurrentWorkerId(), callbacks_id, waitable_results)),
619 waitable_results.get());
620 return callbacks_id;
623 void WebFileSystemImpl::createFileWriter(
624 const WebURL& path,
625 blink::WebFileWriterClient* client,
626 WebFileSystemCallbacks callbacks) {
627 int callbacks_id = RegisterCallbacks(callbacks);
628 scoped_refptr<WaitableCallbackResults> waitable_results =
629 MaybeCreateWaitableResults(callbacks, callbacks_id);
630 CallDispatcherOnMainThread(
631 main_thread_loop_.get(),
632 &FileSystemDispatcher::ReadMetadata,
633 MakeTuple(GURL(path),
634 base::Bind(&CreateFileWriterCallbackAdapter,
635 CurrentWorkerId(), callbacks_id, waitable_results,
636 main_thread_loop_, GURL(path), client),
637 base::Bind(&StatusCallbackAdapter,
638 CurrentWorkerId(), callbacks_id, waitable_results)),
639 waitable_results.get());
642 void WebFileSystemImpl::createSnapshotFileAndReadMetadata(
643 const blink::WebURL& path,
644 WebFileSystemCallbacks callbacks) {
645 int callbacks_id = RegisterCallbacks(callbacks);
646 scoped_refptr<WaitableCallbackResults> waitable_results =
647 MaybeCreateWaitableResults(callbacks, callbacks_id);
648 CallDispatcherOnMainThread(
649 main_thread_loop_.get(),
650 &FileSystemDispatcher::CreateSnapshotFile,
651 MakeTuple(GURL(path),
652 base::Bind(&CreateSnapshotFileCallbackAdapter,
653 CurrentWorkerId(), callbacks_id, waitable_results,
654 main_thread_loop_),
655 base::Bind(&StatusCallbackAdapter,
656 CurrentWorkerId(), callbacks_id, waitable_results)),
657 waitable_results.get());
660 bool WebFileSystemImpl::waitForAdditionalResult(int callbacksId) {
661 WaitableCallbackResultsMap::iterator found =
662 waitable_results_.find(callbacksId);
663 if (found == waitable_results_.end())
664 return false;
666 found->second->WaitAndRun();
667 return true;
670 int WebFileSystemImpl::RegisterCallbacks(
671 const WebFileSystemCallbacks& callbacks) {
672 DCHECK(CalledOnValidThread());
673 int id = next_callbacks_id_++;
674 callbacks_[id] = callbacks;
675 return id;
678 WebFileSystemCallbacks WebFileSystemImpl::GetCallbacks(int callbacks_id) {
679 DCHECK(CalledOnValidThread());
680 CallbacksMap::iterator found = callbacks_.find(callbacks_id);
681 DCHECK(found != callbacks_.end());
682 return found->second;
685 void WebFileSystemImpl::UnregisterCallbacks(int callbacks_id) {
686 DCHECK(CalledOnValidThread());
687 CallbacksMap::iterator found = callbacks_.find(callbacks_id);
688 DCHECK(found != callbacks_.end());
689 callbacks_.erase(found);
691 waitable_results_.erase(callbacks_id);
694 WaitableCallbackResults* WebFileSystemImpl::MaybeCreateWaitableResults(
695 const WebFileSystemCallbacks& callbacks, int callbacks_id) {
696 if (!callbacks.shouldBlockUntilCompletion())
697 return NULL;
698 WaitableCallbackResults* results = new WaitableCallbackResults();
699 waitable_results_[callbacks_id] = results;
700 return results;
703 } // namespace content