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/thread_task_runner_handle.h"
14 #include "base/threading/thread_local.h"
15 #include "content/child/child_thread_impl.h"
16 #include "content/child/file_info_util.h"
17 #include "content/child/fileapi/file_system_dispatcher.h"
18 #include "content/child/fileapi/webfilewriter_impl.h"
19 #include "content/common/fileapi/file_system_messages.h"
20 #include "storage/common/fileapi/directory_entry.h"
21 #include "storage/common/fileapi/file_system_util.h"
22 #include "third_party/WebKit/public/platform/WebFileInfo.h"
23 #include "third_party/WebKit/public/platform/WebFileSystemCallbacks.h"
24 #include "third_party/WebKit/public/platform/WebString.h"
25 #include "third_party/WebKit/public/platform/WebURL.h"
26 #include "third_party/WebKit/public/web/WebHeap.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 (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(
102 base::Bind(&CallDispatcherOnMainThread
<Method
, Params
>,
103 main_thread_task_runner
, method
, params
,
104 scoped_refptr
<WaitableCallbackResults
>()));
105 if (!waitable_results
)
107 waitable_results
->WaitAndRun();
109 if (!ChildThreadImpl::current() ||
110 !ChildThreadImpl::current()->file_system_dispatcher())
113 DCHECK(!waitable_results
);
114 DispatchToMethod(ChildThreadImpl::current()->file_system_dispatcher(),
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
,
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
,
162 WebFileSystemCallbacks
* callbacks
) {
163 callbacks
->didResolveURL(
166 static_cast<blink::WebFileSystemType
>(mount_type
),
171 void DidFail(base::File::Error error
, WebFileSystemCallbacks
* callbacks
) {
172 callbacks
->didFail(storage::FileErrorToWebFileError(error
));
175 // Run WebFileSystemCallbacks's |method| with |params|.
178 const base::Callback
<void(WebFileSystemCallbacks
*)>& callback
,
179 CallbacksUnregisterMode callbacks_unregister_mode
) {
180 WebFileSystemImpl
* filesystem
=
181 WebFileSystemImpl::ThreadSpecificInstance(NULL
);
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
,
193 WaitableCallbackResults
* waitable_results
,
194 const base::Closure
& results_closure
) {
195 if (task_runner
->BelongsToCurrentThread()) {
196 results_closure
.Run();
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
)));
209 task_runner
->PostTask(FROM_HERE
, results_closure
);
212 void CallbackFileSystemCallbacks(
213 const scoped_refptr
<base::SingleThreadTaskRunner
>& task_runner
,
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
228 void OpenFileSystemCallbackAdapter(
229 const scoped_refptr
<base::SingleThreadTaskRunner
>& task_runner
,
231 WaitableCallbackResults
* waitable_results
,
232 const std::string
& name
,
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
,
243 WaitableCallbackResults
* waitable_results
,
244 const storage::FileSystemInfo
& info
,
245 const base::FilePath
& file_path
,
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(),
254 UNREGISTER_CALLBACKS
);
257 void StatusCallbackAdapter(
258 const scoped_refptr
<base::SingleThreadTaskRunner
>& task_runner
,
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
);
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
,
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
,
285 WaitableCallbackResults
* waitable_results
,
286 const std::vector
<storage::DirectoryEntry
>& entries
,
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(
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
);
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
);
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
),
320 void CreateFileWriterCallbackAdapter(
321 const scoped_refptr
<base::SingleThreadTaskRunner
>& task_runner
,
323 WaitableCallbackResults
* waitable_results
,
324 const scoped_refptr
<base::SingleThreadTaskRunner
>& main_thread_task_runner
,
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(
336 const scoped_refptr
<base::SingleThreadTaskRunner
>& main_thread_task_runner
,
337 const base::File::Info
& file_info
,
338 const base::FilePath
& platform_path
,
340 WebFileSystemImpl
* filesystem
=
341 WebFileSystemImpl::ThreadSpecificInstance(NULL
);
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
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
,
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
,
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
));
375 //-----------------------------------------------------------------------------
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 (WorkerTaskRunner::Instance()->CurrentWorkerId())
386 WorkerTaskRunner::Instance()->AddStopObserver(filesystem
);
390 void WebFileSystemImpl::DeleteThreadSpecificInstance() {
391 DCHECK(!WorkerTaskRunner::Instance()->CurrentWorkerId());
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::OnWorkerRunLoopStopped() {
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
,
425 base::Bind(&StatusCallbackAdapter
,
426 base::ThreadTaskRunnerHandle::Get(), callbacks_id
,
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
,
443 base::Bind(&StatusCallbackAdapter
,
444 base::ThreadTaskRunnerHandle::Get(), callbacks_id
,
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
,
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
,
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
,
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
,
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
,
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
,
542 waitable_results
.get());
545 void WebFileSystemImpl::createFile(
546 const blink::WebURL
& path
,
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
,
558 waitable_results
.get());
561 void WebFileSystemImpl::createDirectory(
562 const blink::WebURL
& path
,
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
,
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
,
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
,
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
,
621 waitable_results
.get());
625 void WebFileSystemImpl::createFileWriter(
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_
,
639 base::Bind(&StatusCallbackAdapter
,
640 base::ThreadTaskRunnerHandle::Get(), callbacks_id
,
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
,
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())
669 found
->second
->WaitAndRun();
673 int WebFileSystemImpl::RegisterCallbacks(
674 const WebFileSystemCallbacks
& callbacks
) {
675 DCHECK(CalledOnValidThread());
676 int id
= next_callbacks_id_
++;
677 callbacks_
[id
] = callbacks
;
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())
701 WaitableCallbackResults
* results
= new WaitableCallbackResults();
702 waitable_results_
[callbacks_id
] = results
;
706 } // namespace content