cygprofile: increase timeouts to allow showing web contents
[chromium-blink-merge.git] / content / child / fileapi / webfilesystem_impl.cc
blob39f748120ff0a113536311849405880cb84aaac9
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/strings/utf_string_conversions.h"
11 #include "base/synchronization/waitable_event.h"
12 #include "base/thread_task_runner_handle.h"
13 #include "base/threading/thread_local.h"
14 #include "content/child/child_thread_impl.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/common/fileapi/file_system_messages.h"
19 #include "storage/common/fileapi/directory_entry.h"
20 #include "storage/common/fileapi/file_system_util.h"
21 #include "third_party/WebKit/public/platform/WebFileInfo.h"
22 #include "third_party/WebKit/public/platform/WebFileSystemCallbacks.h"
23 #include "third_party/WebKit/public/platform/WebString.h"
24 #include "third_party/WebKit/public/platform/WebURL.h"
25 #include "third_party/WebKit/public/web/WebHeap.h"
26 #include "url/gurl.h"
28 using base::MakeTuple;
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 (ChildThreadImpl::current())
90 ChildThreadImpl::current()->Send(
91 new FileSystemHostMsg_DidReceiveSnapshotFile(request_id));
94 template <typename Method, typename Params>
95 void CallDispatcherOnMainThread(
96 const scoped_refptr<base::SingleThreadTaskRunner>& main_thread_task_runner,
97 Method method, const Params& params,
98 WaitableCallbackResults* waitable_results) {
99 if (!main_thread_task_runner->RunsTasksOnCurrentThread()) {
100 main_thread_task_runner->PostTask(
101 FROM_HERE,
102 base::Bind(&CallDispatcherOnMainThread<Method, Params>,
103 main_thread_task_runner, method, params,
104 scoped_refptr<WaitableCallbackResults>()));
105 if (!waitable_results)
106 return;
107 waitable_results->WaitAndRun();
109 if (!ChildThreadImpl::current() ||
110 !ChildThreadImpl::current()->file_system_dispatcher())
111 return;
113 DCHECK(!waitable_results);
114 DispatchToMethod(ChildThreadImpl::current()->file_system_dispatcher(),
115 method, params);
118 enum CallbacksUnregisterMode {
119 UNREGISTER_CALLBACKS,
120 DO_NOT_UNREGISTER_CALLBACKS,
123 // Bridging functions that convert the arguments into Blink objects
124 // (e.g. WebFileInfo, WebString, WebVector<WebFileSystemEntry>)
125 // and call WebFileSystemCallbacks's methods.
126 // These are called by RunCallbacks after crossing threads to ensure
127 // thread safety, because the Blink objects cannot be passed across
128 // threads by base::Bind().
129 void DidSucceed(WebFileSystemCallbacks* callbacks) {
130 callbacks->didSucceed();
133 void DidReadMetadata(const base::File::Info& file_info,
134 WebFileSystemCallbacks* callbacks) {
135 WebFileInfo web_file_info;
136 FileInfoToWebFileInfo(file_info, &web_file_info);
137 callbacks->didReadMetadata(web_file_info);
140 void DidReadDirectory(const std::vector<storage::DirectoryEntry>& entries,
141 bool has_more,
142 WebFileSystemCallbacks* callbacks) {
143 WebVector<WebFileSystemEntry> file_system_entries(entries.size());
144 for (size_t i = 0; i < entries.size(); ++i) {
145 file_system_entries[i].name =
146 base::FilePath(entries[i].name).AsUTF16Unsafe();
147 file_system_entries[i].isDirectory = entries[i].is_directory;
149 callbacks->didReadDirectory(file_system_entries, has_more);
152 void DidOpenFileSystem(const base::string16& name, const GURL& root,
153 WebFileSystemCallbacks* callbacks) {
154 callbacks->didOpenFileSystem(name, root);
157 void DidResolveURL(const base::string16& name,
158 const GURL& root_url,
159 storage::FileSystemType mount_type,
160 const base::string16& file_path,
161 bool is_directory,
162 WebFileSystemCallbacks* callbacks) {
163 callbacks->didResolveURL(
164 name,
165 root_url,
166 static_cast<blink::WebFileSystemType>(mount_type),
167 file_path,
168 is_directory);
171 void DidFail(base::File::Error error, WebFileSystemCallbacks* callbacks) {
172 callbacks->didFail(storage::FileErrorToWebFileError(error));
175 // Run WebFileSystemCallbacks's |method| with |params|.
176 void RunCallbacks(
177 int callbacks_id,
178 const base::Callback<void(WebFileSystemCallbacks*)>& callback,
179 CallbacksUnregisterMode callbacks_unregister_mode) {
180 WebFileSystemImpl* filesystem =
181 WebFileSystemImpl::ThreadSpecificInstance(NULL);
182 if (!filesystem)
183 return;
184 WebFileSystemCallbacks callbacks = filesystem->GetCallbacks(callbacks_id);
185 if (callbacks_unregister_mode == UNREGISTER_CALLBACKS)
186 filesystem->UnregisterCallbacks(callbacks_id);
187 callback.Run(&callbacks);
190 void DispatchResultsClosure(
191 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
192 int callbacks_id,
193 WaitableCallbackResults* waitable_results,
194 const base::Closure& results_closure) {
195 if (task_runner->BelongsToCurrentThread()) {
196 results_closure.Run();
197 return;
200 if (waitable_results) {
201 // If someone is waiting, this should result in running the closure.
202 waitable_results->AddResultsAndSignal(results_closure);
203 // In case no one is waiting, post a task to run the closure.
204 task_runner->PostTask(FROM_HERE,
205 base::Bind(&WaitableCallbackResults::Run,
206 make_scoped_refptr(waitable_results)));
207 return;
209 task_runner->PostTask(FROM_HERE, results_closure);
212 void CallbackFileSystemCallbacks(
213 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
214 int callbacks_id,
215 WaitableCallbackResults* waitable_results,
216 const base::Callback<void(WebFileSystemCallbacks*)>& callback,
217 CallbacksUnregisterMode callbacksunregister_mode) {
218 DispatchResultsClosure(task_runner, callbacks_id, waitable_results,
219 base::Bind(&RunCallbacks, callbacks_id, callback,
220 callbacksunregister_mode));
223 //-----------------------------------------------------------------------------
224 // Callback adapters. Callbacks must be called on the original calling thread,
225 // so these callback adapters relay back the results to the calling thread
226 // if necessary.
228 void OpenFileSystemCallbackAdapter(
229 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
230 int callbacks_id,
231 WaitableCallbackResults* waitable_results,
232 const std::string& name,
233 const GURL& root) {
234 CallbackFileSystemCallbacks(
235 task_runner, callbacks_id, waitable_results,
236 base::Bind(&DidOpenFileSystem, base::UTF8ToUTF16(name), root),
237 UNREGISTER_CALLBACKS);
240 void ResolveURLCallbackAdapter(
241 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
242 int callbacks_id,
243 WaitableCallbackResults* waitable_results,
244 const storage::FileSystemInfo& info,
245 const base::FilePath& file_path,
246 bool is_directory) {
247 base::FilePath normalized_path(
248 storage::VirtualPath::GetNormalizedFilePath(file_path));
249 CallbackFileSystemCallbacks(
250 task_runner, callbacks_id, waitable_results,
251 base::Bind(&DidResolveURL, base::UTF8ToUTF16(info.name), info.root_url,
252 info.mount_type, normalized_path.AsUTF16Unsafe(),
253 is_directory),
254 UNREGISTER_CALLBACKS);
257 void StatusCallbackAdapter(
258 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
259 int callbacks_id,
260 WaitableCallbackResults* waitable_results,
261 base::File::Error error) {
262 if (error == base::File::FILE_OK) {
263 CallbackFileSystemCallbacks(task_runner, callbacks_id, waitable_results,
264 base::Bind(&DidSucceed), UNREGISTER_CALLBACKS);
265 } else {
266 CallbackFileSystemCallbacks(task_runner, callbacks_id, waitable_results,
267 base::Bind(&DidFail, error),
268 UNREGISTER_CALLBACKS);
272 void ReadMetadataCallbackAdapter(
273 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
274 int callbacks_id,
275 WaitableCallbackResults* waitable_results,
276 const base::File::Info& file_info) {
277 CallbackFileSystemCallbacks(task_runner, callbacks_id, waitable_results,
278 base::Bind(&DidReadMetadata, file_info),
279 UNREGISTER_CALLBACKS);
282 void ReadDirectoryCallbackAdapter(
283 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
284 int callbacks_id,
285 WaitableCallbackResults* waitable_results,
286 const std::vector<storage::DirectoryEntry>& entries,
287 bool has_more) {
288 CallbackFileSystemCallbacks(
289 task_runner, callbacks_id, waitable_results,
290 base::Bind(&DidReadDirectory, entries, has_more),
291 has_more ? DO_NOT_UNREGISTER_CALLBACKS : UNREGISTER_CALLBACKS);
294 void DidCreateFileWriter(
295 int callbacks_id,
296 const GURL& path,
297 blink::WebFileWriterClient* client,
298 const scoped_refptr<base::SingleThreadTaskRunner>& main_thread_task_runner,
299 const base::File::Info& file_info) {
300 WebFileSystemImpl* filesystem =
301 WebFileSystemImpl::ThreadSpecificInstance(NULL);
302 if (!filesystem)
303 return;
305 WebFileSystemCallbacks callbacks = filesystem->GetCallbacks(callbacks_id);
306 filesystem->UnregisterCallbacks(callbacks_id);
308 if (file_info.is_directory || file_info.size < 0) {
309 callbacks.didFail(blink::WebFileErrorInvalidState);
310 return;
312 WebFileWriterImpl::Type type =
313 callbacks.shouldBlockUntilCompletion() ?
314 WebFileWriterImpl::TYPE_SYNC : WebFileWriterImpl::TYPE_ASYNC;
315 callbacks.didCreateFileWriter(
316 new WebFileWriterImpl(path, client, type, main_thread_task_runner),
317 file_info.size);
320 void CreateFileWriterCallbackAdapter(
321 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
322 int callbacks_id,
323 WaitableCallbackResults* waitable_results,
324 const scoped_refptr<base::SingleThreadTaskRunner>& main_thread_task_runner,
325 const GURL& path,
326 blink::WebFileWriterClient* client,
327 const base::File::Info& file_info) {
328 DispatchResultsClosure(
329 task_runner, callbacks_id, waitable_results,
330 base::Bind(&DidCreateFileWriter, callbacks_id, path, client,
331 main_thread_task_runner, file_info));
334 void DidCreateSnapshotFile(
335 int callbacks_id,
336 const scoped_refptr<base::SingleThreadTaskRunner>& main_thread_task_runner,
337 const base::File::Info& file_info,
338 const base::FilePath& platform_path,
339 int request_id) {
340 WebFileSystemImpl* filesystem =
341 WebFileSystemImpl::ThreadSpecificInstance(NULL);
342 if (!filesystem)
343 return;
345 WebFileSystemCallbacks callbacks = filesystem->GetCallbacks(callbacks_id);
346 filesystem->UnregisterCallbacks(callbacks_id);
348 WebFileInfo web_file_info;
349 FileInfoToWebFileInfo(file_info, &web_file_info);
350 web_file_info.platformPath = platform_path.AsUTF16Unsafe();
351 callbacks.didCreateSnapshotFile(web_file_info);
353 // TODO(michaeln,kinuko): Use ThreadSafeSender when Blob becomes
354 // non-bridge model.
355 main_thread_task_runner->PostTask(
356 FROM_HERE, base::Bind(&DidReceiveSnapshotFile, request_id));
359 void CreateSnapshotFileCallbackAdapter(
360 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
361 int callbacks_id,
362 WaitableCallbackResults* waitable_results,
363 const scoped_refptr<base::SingleThreadTaskRunner>& main_thread_task_runner,
364 const base::File::Info& file_info,
365 const base::FilePath& platform_path,
366 int request_id) {
367 DispatchResultsClosure(
368 task_runner, callbacks_id, waitable_results,
369 base::Bind(&DidCreateSnapshotFile, callbacks_id, main_thread_task_runner,
370 file_info, platform_path, request_id));
373 } // namespace
375 //-----------------------------------------------------------------------------
376 // WebFileSystemImpl
378 WebFileSystemImpl* WebFileSystemImpl::ThreadSpecificInstance(
379 const scoped_refptr<base::SingleThreadTaskRunner>&
380 main_thread_task_runner) {
381 if (g_webfilesystem_tls.Pointer()->Get() || !main_thread_task_runner.get())
382 return g_webfilesystem_tls.Pointer()->Get();
383 WebFileSystemImpl* filesystem =
384 new WebFileSystemImpl(main_thread_task_runner);
385 if (WorkerThread::GetCurrentId())
386 WorkerThread::AddObserver(filesystem);
387 return filesystem;
390 void WebFileSystemImpl::DeleteThreadSpecificInstance() {
391 DCHECK(!WorkerThread::GetCurrentId());
392 if (g_webfilesystem_tls.Pointer()->Get())
393 delete g_webfilesystem_tls.Pointer()->Get();
396 WebFileSystemImpl::WebFileSystemImpl(
397 const scoped_refptr<base::SingleThreadTaskRunner>& main_thread_task_runner)
398 : main_thread_task_runner_(main_thread_task_runner),
399 next_callbacks_id_(1) {
400 g_webfilesystem_tls.Pointer()->Set(this);
403 WebFileSystemImpl::~WebFileSystemImpl() {
404 g_webfilesystem_tls.Pointer()->Set(NULL);
407 void WebFileSystemImpl::WillStopCurrentWorkerThread() {
408 delete this;
411 void WebFileSystemImpl::openFileSystem(
412 const blink::WebURL& storage_partition,
413 blink::WebFileSystemType type,
414 WebFileSystemCallbacks callbacks) {
415 int callbacks_id = RegisterCallbacks(callbacks);
416 scoped_refptr<WaitableCallbackResults> waitable_results =
417 MaybeCreateWaitableResults(callbacks, callbacks_id);
418 CallDispatcherOnMainThread(
419 main_thread_task_runner_, &FileSystemDispatcher::OpenFileSystem,
420 MakeTuple(GURL(storage_partition),
421 static_cast<storage::FileSystemType>(type),
422 base::Bind(&OpenFileSystemCallbackAdapter,
423 base::ThreadTaskRunnerHandle::Get(), callbacks_id,
424 waitable_results),
425 base::Bind(&StatusCallbackAdapter,
426 base::ThreadTaskRunnerHandle::Get(), callbacks_id,
427 waitable_results)),
428 waitable_results.get());
431 void WebFileSystemImpl::resolveURL(
432 const blink::WebURL& filesystem_url,
433 WebFileSystemCallbacks callbacks) {
434 int callbacks_id = RegisterCallbacks(callbacks);
435 scoped_refptr<WaitableCallbackResults> waitable_results =
436 MaybeCreateWaitableResults(callbacks, callbacks_id);
437 CallDispatcherOnMainThread(
438 main_thread_task_runner_, &FileSystemDispatcher::ResolveURL,
439 MakeTuple(GURL(filesystem_url),
440 base::Bind(&ResolveURLCallbackAdapter,
441 base::ThreadTaskRunnerHandle::Get(), callbacks_id,
442 waitable_results),
443 base::Bind(&StatusCallbackAdapter,
444 base::ThreadTaskRunnerHandle::Get(), callbacks_id,
445 waitable_results)),
446 waitable_results.get());
449 void WebFileSystemImpl::deleteFileSystem(
450 const blink::WebURL& storage_partition,
451 blink::WebFileSystemType type,
452 WebFileSystemCallbacks callbacks) {
453 int callbacks_id = RegisterCallbacks(callbacks);
454 scoped_refptr<WaitableCallbackResults> waitable_results =
455 MaybeCreateWaitableResults(callbacks, callbacks_id);
456 CallDispatcherOnMainThread(
457 main_thread_task_runner_, &FileSystemDispatcher::DeleteFileSystem,
458 MakeTuple(GURL(storage_partition),
459 static_cast<storage::FileSystemType>(type),
460 base::Bind(&StatusCallbackAdapter,
461 base::ThreadTaskRunnerHandle::Get(), callbacks_id,
462 waitable_results)),
463 waitable_results.get());
466 void WebFileSystemImpl::move(
467 const blink::WebURL& src_path,
468 const blink::WebURL& dest_path,
469 WebFileSystemCallbacks callbacks) {
470 int callbacks_id = RegisterCallbacks(callbacks);
471 scoped_refptr<WaitableCallbackResults> waitable_results =
472 MaybeCreateWaitableResults(callbacks, callbacks_id);
473 CallDispatcherOnMainThread(
474 main_thread_task_runner_, &FileSystemDispatcher::Move,
475 MakeTuple(GURL(src_path), GURL(dest_path),
476 base::Bind(&StatusCallbackAdapter,
477 base::ThreadTaskRunnerHandle::Get(), callbacks_id,
478 waitable_results)),
479 waitable_results.get());
482 void WebFileSystemImpl::copy(
483 const blink::WebURL& src_path,
484 const blink::WebURL& dest_path,
485 WebFileSystemCallbacks callbacks) {
486 int callbacks_id = RegisterCallbacks(callbacks);
487 scoped_refptr<WaitableCallbackResults> waitable_results =
488 MaybeCreateWaitableResults(callbacks, callbacks_id);
489 CallDispatcherOnMainThread(
490 main_thread_task_runner_, &FileSystemDispatcher::Copy,
491 MakeTuple(GURL(src_path), GURL(dest_path),
492 base::Bind(&StatusCallbackAdapter,
493 base::ThreadTaskRunnerHandle::Get(), callbacks_id,
494 waitable_results)),
495 waitable_results.get());
498 void WebFileSystemImpl::remove(
499 const blink::WebURL& path,
500 WebFileSystemCallbacks callbacks) {
501 int callbacks_id = RegisterCallbacks(callbacks);
502 scoped_refptr<WaitableCallbackResults> waitable_results =
503 MaybeCreateWaitableResults(callbacks, callbacks_id);
504 CallDispatcherOnMainThread(
505 main_thread_task_runner_, &FileSystemDispatcher::Remove,
506 MakeTuple(GURL(path), false /* recursive */,
507 base::Bind(&StatusCallbackAdapter,
508 base::ThreadTaskRunnerHandle::Get(), callbacks_id,
509 waitable_results)),
510 waitable_results.get());
513 void WebFileSystemImpl::removeRecursively(
514 const blink::WebURL& path,
515 WebFileSystemCallbacks callbacks) {
516 int callbacks_id = RegisterCallbacks(callbacks);
517 scoped_refptr<WaitableCallbackResults> waitable_results =
518 MaybeCreateWaitableResults(callbacks, callbacks_id);
519 CallDispatcherOnMainThread(
520 main_thread_task_runner_, &FileSystemDispatcher::Remove,
521 MakeTuple(GURL(path), true /* recursive */,
522 base::Bind(&StatusCallbackAdapter,
523 base::ThreadTaskRunnerHandle::Get(), callbacks_id,
524 waitable_results)),
525 waitable_results.get());
528 void WebFileSystemImpl::readMetadata(
529 const blink::WebURL& path,
530 WebFileSystemCallbacks callbacks) {
531 int callbacks_id = RegisterCallbacks(callbacks);
532 scoped_refptr<WaitableCallbackResults> waitable_results =
533 MaybeCreateWaitableResults(callbacks, callbacks_id);
534 CallDispatcherOnMainThread(
535 main_thread_task_runner_, &FileSystemDispatcher::ReadMetadata,
536 MakeTuple(GURL(path), base::Bind(&ReadMetadataCallbackAdapter,
537 base::ThreadTaskRunnerHandle::Get(),
538 callbacks_id, waitable_results),
539 base::Bind(&StatusCallbackAdapter,
540 base::ThreadTaskRunnerHandle::Get(), callbacks_id,
541 waitable_results)),
542 waitable_results.get());
545 void WebFileSystemImpl::createFile(
546 const blink::WebURL& path,
547 bool exclusive,
548 WebFileSystemCallbacks callbacks) {
549 int callbacks_id = RegisterCallbacks(callbacks);
550 scoped_refptr<WaitableCallbackResults> waitable_results =
551 MaybeCreateWaitableResults(callbacks, callbacks_id);
552 CallDispatcherOnMainThread(
553 main_thread_task_runner_, &FileSystemDispatcher::CreateFile,
554 MakeTuple(GURL(path), exclusive,
555 base::Bind(&StatusCallbackAdapter,
556 base::ThreadTaskRunnerHandle::Get(), callbacks_id,
557 waitable_results)),
558 waitable_results.get());
561 void WebFileSystemImpl::createDirectory(
562 const blink::WebURL& path,
563 bool exclusive,
564 WebFileSystemCallbacks callbacks) {
565 int callbacks_id = RegisterCallbacks(callbacks);
566 scoped_refptr<WaitableCallbackResults> waitable_results =
567 MaybeCreateWaitableResults(callbacks, callbacks_id);
568 CallDispatcherOnMainThread(
569 main_thread_task_runner_, &FileSystemDispatcher::CreateDirectory,
570 MakeTuple(GURL(path), exclusive, false /* recursive */,
571 base::Bind(&StatusCallbackAdapter,
572 base::ThreadTaskRunnerHandle::Get(), callbacks_id,
573 waitable_results)),
574 waitable_results.get());
577 void WebFileSystemImpl::fileExists(
578 const blink::WebURL& path,
579 WebFileSystemCallbacks callbacks) {
580 int callbacks_id = RegisterCallbacks(callbacks);
581 scoped_refptr<WaitableCallbackResults> waitable_results =
582 MaybeCreateWaitableResults(callbacks, callbacks_id);
583 CallDispatcherOnMainThread(
584 main_thread_task_runner_, &FileSystemDispatcher::Exists,
585 MakeTuple(GURL(path), false /* directory */,
586 base::Bind(&StatusCallbackAdapter,
587 base::ThreadTaskRunnerHandle::Get(), callbacks_id,
588 waitable_results)),
589 waitable_results.get());
592 void WebFileSystemImpl::directoryExists(
593 const blink::WebURL& path,
594 WebFileSystemCallbacks callbacks) {
595 int callbacks_id = RegisterCallbacks(callbacks);
596 scoped_refptr<WaitableCallbackResults> waitable_results =
597 MaybeCreateWaitableResults(callbacks, callbacks_id);
598 CallDispatcherOnMainThread(
599 main_thread_task_runner_, &FileSystemDispatcher::Exists,
600 MakeTuple(GURL(path), true /* directory */,
601 base::Bind(&StatusCallbackAdapter,
602 base::ThreadTaskRunnerHandle::Get(), callbacks_id,
603 waitable_results)),
604 waitable_results.get());
607 int WebFileSystemImpl::readDirectory(
608 const blink::WebURL& path,
609 WebFileSystemCallbacks callbacks) {
610 int callbacks_id = RegisterCallbacks(callbacks);
611 scoped_refptr<WaitableCallbackResults> waitable_results =
612 MaybeCreateWaitableResults(callbacks, callbacks_id);
613 CallDispatcherOnMainThread(
614 main_thread_task_runner_, &FileSystemDispatcher::ReadDirectory,
615 MakeTuple(GURL(path), base::Bind(&ReadDirectoryCallbackAdapter,
616 base::ThreadTaskRunnerHandle::Get(),
617 callbacks_id, waitable_results),
618 base::Bind(&StatusCallbackAdapter,
619 base::ThreadTaskRunnerHandle::Get(), callbacks_id,
620 waitable_results)),
621 waitable_results.get());
622 return callbacks_id;
625 void WebFileSystemImpl::createFileWriter(
626 const WebURL& path,
627 blink::WebFileWriterClient* client,
628 WebFileSystemCallbacks callbacks) {
629 int callbacks_id = RegisterCallbacks(callbacks);
630 scoped_refptr<WaitableCallbackResults> waitable_results =
631 MaybeCreateWaitableResults(callbacks, callbacks_id);
632 CallDispatcherOnMainThread(
633 main_thread_task_runner_, &FileSystemDispatcher::ReadMetadata,
634 MakeTuple(GURL(path),
635 base::Bind(&CreateFileWriterCallbackAdapter,
636 base::ThreadTaskRunnerHandle::Get(), callbacks_id,
637 waitable_results, main_thread_task_runner_,
638 GURL(path), client),
639 base::Bind(&StatusCallbackAdapter,
640 base::ThreadTaskRunnerHandle::Get(), callbacks_id,
641 waitable_results)),
642 waitable_results.get());
645 void WebFileSystemImpl::createSnapshotFileAndReadMetadata(
646 const blink::WebURL& path,
647 WebFileSystemCallbacks callbacks) {
648 int callbacks_id = RegisterCallbacks(callbacks);
649 scoped_refptr<WaitableCallbackResults> waitable_results =
650 MaybeCreateWaitableResults(callbacks, callbacks_id);
651 CallDispatcherOnMainThread(
652 main_thread_task_runner_, &FileSystemDispatcher::CreateSnapshotFile,
653 MakeTuple(GURL(path),
654 base::Bind(&CreateSnapshotFileCallbackAdapter,
655 base::ThreadTaskRunnerHandle::Get(), callbacks_id,
656 waitable_results, main_thread_task_runner_),
657 base::Bind(&StatusCallbackAdapter,
658 base::ThreadTaskRunnerHandle::Get(), callbacks_id,
659 waitable_results)),
660 waitable_results.get());
663 bool WebFileSystemImpl::waitForAdditionalResult(int callbacksId) {
664 WaitableCallbackResultsMap::iterator found =
665 waitable_results_.find(callbacksId);
666 if (found == waitable_results_.end())
667 return false;
669 found->second->WaitAndRun();
670 return true;
673 int WebFileSystemImpl::RegisterCallbacks(
674 const WebFileSystemCallbacks& callbacks) {
675 DCHECK(CalledOnValidThread());
676 int id = next_callbacks_id_++;
677 callbacks_[id] = callbacks;
678 return id;
681 WebFileSystemCallbacks WebFileSystemImpl::GetCallbacks(int callbacks_id) {
682 DCHECK(CalledOnValidThread());
683 CallbacksMap::iterator found = callbacks_.find(callbacks_id);
684 DCHECK(found != callbacks_.end());
685 return found->second;
688 void WebFileSystemImpl::UnregisterCallbacks(int callbacks_id) {
689 DCHECK(CalledOnValidThread());
690 CallbacksMap::iterator found = callbacks_.find(callbacks_id);
691 DCHECK(found != callbacks_.end());
692 callbacks_.erase(found);
694 waitable_results_.erase(callbacks_id);
697 WaitableCallbackResults* WebFileSystemImpl::MaybeCreateWaitableResults(
698 const WebFileSystemCallbacks& callbacks, int callbacks_id) {
699 if (!callbacks.shouldBlockUntilCompletion())
700 return NULL;
701 WaitableCallbackResults* results = new WaitableCallbackResults();
702 waitable_results_[callbacks_id] = results;
703 return results;
706 } // namespace content