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
<storage::DirectoryEntry
>& entries
,
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
,
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(storage::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(int thread_id
,
241 WaitableCallbackResults
* waitable_results
,
242 const storage::FileSystemInfo
& info
,
243 const base::FilePath
& file_path
,
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
,
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
);
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(
283 WaitableCallbackResults
* waitable_results
,
284 const std::vector
<storage::DirectoryEntry
>& entries
,
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(
295 blink::WebFileWriterClient
* client
,
296 base::MessageLoopProxy
* main_thread_loop
,
297 const base::File::Info
& file_info
) {
298 WebFileSystemImpl
* filesystem
=
299 WebFileSystemImpl::ThreadSpecificInstance(NULL
);
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
);
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
),
318 void CreateFileWriterCallbackAdapter(
319 int thread_id
, int callbacks_id
,
320 WaitableCallbackResults
* waitable_results
,
321 base::MessageLoopProxy
* main_thread_loop
,
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(
333 base::MessageLoopProxy
* main_thread_loop
,
334 const base::File::Info
& file_info
,
335 const base::FilePath
& platform_path
,
337 WebFileSystemImpl
* filesystem
=
338 WebFileSystemImpl::ThreadSpecificInstance(NULL
);
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
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
,
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
));
372 //-----------------------------------------------------------------------------
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
);
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() {
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
,
421 base::Bind(&StatusCallbackAdapter
,
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
,
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
,
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
,
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());
623 void WebFileSystemImpl::createFileWriter(
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
,
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())
666 found
->second
->WaitAndRun();
670 int WebFileSystemImpl::RegisterCallbacks(
671 const WebFileSystemCallbacks
& callbacks
) {
672 DCHECK(CalledOnValidThread());
673 int id
= next_callbacks_id_
++;
674 callbacks_
[id
] = callbacks
;
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())
698 WaitableCallbackResults
* results
= new WaitableCallbackResults();
699 waitable_results_
[callbacks_id
] = results
;
703 } // namespace content