| Index: content/child/fileapi/webfilesystem_impl.cc
|
| diff --git a/content/child/fileapi/webfilesystem_impl.cc b/content/child/fileapi/webfilesystem_impl.cc
|
| index 090bf7d79740e3aed851a4d40ce564b622b45aea..78952b57c702da9d081ef85e2f57f190a42052f2 100644
|
| --- a/content/child/fileapi/webfilesystem_impl.cc
|
| +++ b/content/child/fileapi/webfilesystem_impl.cc
|
| @@ -9,6 +9,7 @@
|
| #include "base/lazy_instance.h"
|
| #include "base/logging.h"
|
| #include "base/message_loop/message_loop_proxy.h"
|
| +#include "base/synchronization/waitable_event.h"
|
| #include "base/threading/thread_local.h"
|
| #include "content/child/child_thread.h"
|
| #include "content/child/fileapi/file_system_dispatcher.h"
|
| @@ -94,6 +95,35 @@ class CallbacksMap : public WorkerTaskRunner::Observer {
|
| DISALLOW_COPY_AND_ASSIGN(CallbacksMap);
|
| };
|
|
|
| +class WaitableCallbackResults {
|
| + public:
|
| + static WaitableCallbackResults* MaybeCreate(
|
| + WebKit::WebFileSystemCallbacks* callbacks) {
|
| + if (callbacks->shouldBlockUntilCompletion())
|
| + return new WaitableCallbackResults;
|
| + return NULL;
|
| + }
|
| + ~WaitableCallbackResults() {}
|
| +
|
| + void SetResultsAndSignal(const base::Closure& results_closure) {
|
| + results_closure_ = results_closure;
|
| + event_->Signal();
|
| + }
|
| +
|
| + void WaitAndRun() {
|
| + event_->Wait();
|
| + DCHECK(!results_closure_.is_null());
|
| + results_closure_.Run();
|
| + }
|
| +
|
| + private:
|
| + WaitableCallbackResults() : event_(new base::WaitableEvent(true, false)) {}
|
| +
|
| + base::WaitableEvent* event_;
|
| + base::Closure results_closure_;
|
| + DISALLOW_COPY_AND_ASSIGN(WaitableCallbackResults);
|
| +};
|
| +
|
| void DidReceiveSnapshotFile(int request_id) {
|
| if (ChildThread::current())
|
| ChildThread::current()->Send(
|
| @@ -107,67 +137,90 @@ int CurrentWorkerId() {
|
| template <typename Method, typename Params>
|
| void CallDispatcherOnMainThread(
|
| base::MessageLoopProxy* loop,
|
| - Method method, const Params& params) {
|
| + Method method, const Params& params,
|
| + scoped_ptr<WaitableCallbackResults> waitable_results) {
|
| + scoped_ptr<WaitableCallbackResults> null_waitable;
|
| if (!loop->RunsTasksOnCurrentThread()) {
|
| loop->PostTask(FROM_HERE,
|
| base::Bind(&CallDispatcherOnMainThread<Method, Params>,
|
| - make_scoped_refptr(loop), method, params));
|
| - return;
|
| + make_scoped_refptr(loop), method, params,
|
| + base::Passed(&null_waitable)));
|
| + if (!waitable_results)
|
| + return;
|
| + waitable_results->WaitAndRun();
|
| }
|
| if (!ChildThread::current() ||
|
| !ChildThread::current()->file_system_dispatcher())
|
| return;
|
|
|
| + DCHECK(!waitable_results);
|
| DispatchToMethod(ChildThread::current()->file_system_dispatcher(),
|
| method, params);
|
| }
|
|
|
| +// Run WebFileSystemCallbacks's |method| with |params|.
|
| template <typename Method, typename Params>
|
| -void CallbackFileSystemCallbacks(
|
| - int thread_id, int callbacks_id,
|
| - Method method, const Params& params) {
|
| - if (thread_id != CurrentWorkerId()) {
|
| - WorkerTaskRunner::Instance()->PostTask(
|
| - thread_id,
|
| - base::Bind(&CallbackFileSystemCallbacks<Method, Params>,
|
| - thread_id, callbacks_id, method, params));
|
| - return;
|
| - }
|
| +void RunCallbacks(int callbacks_id, Method method, const Params& params) {
|
| if (!CallbacksMap::Get())
|
| return;
|
| -
|
| WebFileSystemCallbacks* callbacks =
|
| CallbacksMap::Get()->GetAndUnregisterCallbacks(callbacks_id);
|
| DCHECK(callbacks);
|
| DispatchToMethod(callbacks, method, params);
|
| }
|
|
|
| +void DispatchResultsClosure(int thread_id, int callbacks_id,
|
| + WaitableCallbackResults* waitable_results,
|
| + const base::Closure& results_closure) {
|
| + if (thread_id != CurrentWorkerId()) {
|
| + if (waitable_results) {
|
| + waitable_results->SetResultsAndSignal(results_closure);
|
| + return;
|
| + }
|
| + WorkerTaskRunner::Instance()->PostTask(thread_id, results_closure);
|
| + return;
|
| + }
|
| + results_closure.Run();
|
| +}
|
| +
|
| +template <typename Method, typename Params>
|
| +void CallbackFileSystemCallbacks(
|
| + int thread_id, int callbacks_id,
|
| + WaitableCallbackResults* waitable_results,
|
| + Method method, const Params& params) {
|
| + DispatchResultsClosure(
|
| + thread_id, callbacks_id, waitable_results,
|
| + base::Bind(&RunCallbacks<Method, Params>, callbacks_id, method, params));
|
| +}
|
| +
|
| void StatusCallbackAdapter(int thread_id, int callbacks_id,
|
| + WaitableCallbackResults* waitable_results,
|
| base::PlatformFileError error) {
|
| if (error == base::PLATFORM_FILE_OK) {
|
| CallbackFileSystemCallbacks(
|
| - thread_id, callbacks_id,
|
| + thread_id, callbacks_id, waitable_results,
|
| &WebFileSystemCallbacks::didSucceed, MakeTuple());
|
| } else {
|
| CallbackFileSystemCallbacks(
|
| - thread_id, callbacks_id,
|
| + thread_id, callbacks_id, waitable_results,
|
| &WebFileSystemCallbacks::didFail,
|
| MakeTuple(fileapi::PlatformFileErrorToWebFileError(error)));
|
| }
|
| }
|
|
|
| void ReadMetadataCallbackAdapter(int thread_id, int callbacks_id,
|
| + WaitableCallbackResults* waitable_results,
|
| const base::PlatformFileInfo& file_info) {
|
| WebFileInfo web_file_info;
|
| webkit_glue::PlatformFileInfoToWebFileInfo(file_info, &web_file_info);
|
| CallbackFileSystemCallbacks(
|
| - thread_id, callbacks_id,
|
| + thread_id, callbacks_id, waitable_results,
|
| &WebFileSystemCallbacks::didReadMetadata,
|
| MakeTuple(web_file_info));
|
| }
|
|
|
| void ReadDirectoryCallbackAdapater(
|
| - int thread_id, int callbacks_id,
|
| + int thread_id, int callbacks_id, WaitableCallbackResults* waitable_results,
|
| const std::vector<fileapi::DirectoryEntry>& entries,
|
| bool has_more) {
|
| WebVector<WebFileSystemEntry> file_system_entries(entries.size());
|
| @@ -177,27 +230,17 @@ void ReadDirectoryCallbackAdapater(
|
| file_system_entries[i].isDirectory = entries[i].is_directory;
|
| }
|
| CallbackFileSystemCallbacks(
|
| - thread_id, callbacks_id,
|
| + thread_id, callbacks_id, waitable_results,
|
| &WebFileSystemCallbacks::didReadDirectory,
|
| MakeTuple(file_system_entries, has_more));
|
| }
|
|
|
| -void CreateFileWriterCallbackAdapter(
|
| - int thread_id, int callbacks_id,
|
| - base::MessageLoopProxy* main_thread_loop,
|
| +void DidCreateFileWriter(
|
| + int callbacks_id,
|
| const GURL& path,
|
| WebKit::WebFileWriterClient* client,
|
| + base::MessageLoopProxy* main_thread_loop,
|
| const base::PlatformFileInfo& file_info) {
|
| - if (thread_id != CurrentWorkerId()) {
|
| - WorkerTaskRunner::Instance()->PostTask(
|
| - thread_id,
|
| - base::Bind(&CreateFileWriterCallbackAdapter,
|
| - thread_id, callbacks_id,
|
| - make_scoped_refptr(main_thread_loop),
|
| - path, client, file_info));
|
| - return;
|
| - }
|
| -
|
| if (!CallbacksMap::Get())
|
| return;
|
|
|
| @@ -213,22 +256,25 @@ void CreateFileWriterCallbackAdapter(
|
| new WebFileWriterImpl(path, client, main_thread_loop), file_info.size);
|
| }
|
|
|
| -void CreateSnapshotFileCallbackAdapter(
|
| +void CreateFileWriterCallbackAdapter(
|
| int thread_id, int callbacks_id,
|
| + WaitableCallbackResults* waitable_results,
|
| + base::MessageLoopProxy* main_thread_loop,
|
| + const GURL& path,
|
| + WebKit::WebFileWriterClient* client,
|
| + const base::PlatformFileInfo& file_info) {
|
| + DispatchResultsClosure(
|
| + thread_id, callbacks_id, waitable_results,
|
| + base::Bind(&DidCreateFileWriter, callbacks_id, path, client,
|
| + make_scoped_refptr(main_thread_loop), file_info));
|
| +}
|
| +
|
| +void DidCreateSnapshotFile(
|
| + int callbacks_id,
|
| base::MessageLoopProxy* main_thread_loop,
|
| const base::PlatformFileInfo& file_info,
|
| const base::FilePath& platform_path,
|
| int request_id) {
|
| - if (thread_id != CurrentWorkerId()) {
|
| - WorkerTaskRunner::Instance()->PostTask(
|
| - thread_id,
|
| - base::Bind(&CreateSnapshotFileCallbackAdapter,
|
| - thread_id, callbacks_id,
|
| - make_scoped_refptr(main_thread_loop),
|
| - file_info, platform_path, request_id));
|
| - return;
|
| - }
|
| -
|
| if (!CallbacksMap::Get())
|
| return;
|
|
|
| @@ -247,6 +293,20 @@ void CreateSnapshotFileCallbackAdapter(
|
| FROM_HERE, base::Bind(&DidReceiveSnapshotFile, request_id));
|
| }
|
|
|
| +void CreateSnapshotFileCallbackAdapter(
|
| + int thread_id, int callbacks_id,
|
| + WaitableCallbackResults* waitable_results,
|
| + base::MessageLoopProxy* main_thread_loop,
|
| + const base::PlatformFileInfo& file_info,
|
| + const base::FilePath& platform_path,
|
| + int request_id) {
|
| + DispatchResultsClosure(
|
| + thread_id, callbacks_id, waitable_results,
|
| + base::Bind(&DidCreateSnapshotFile, callbacks_id,
|
| + make_scoped_refptr(main_thread_loop),
|
| + file_info, platform_path, request_id));
|
| +}
|
| +
|
| } // namespace
|
|
|
| WebFileSystemImpl::~WebFileSystemImpl() {
|
| @@ -261,12 +321,16 @@ void WebFileSystemImpl::move(
|
| const WebKit::WebURL& dest_path,
|
| WebKit::WebFileSystemCallbacks* callbacks) {
|
| int callbacks_id = CallbacksMap::GetOrCreate()->RegisterCallbacks(callbacks);
|
| + WaitableCallbackResults* waitable_results =
|
| + WaitableCallbackResults::MaybeCreate(callbacks);
|
| CallDispatcherOnMainThread(
|
| main_thread_loop_.get(),
|
| &FileSystemDispatcher::Move,
|
| MakeTuple(GURL(src_path), GURL(dest_path),
|
| base::Bind(&StatusCallbackAdapter,
|
| - CurrentWorkerId(), callbacks_id)));
|
| + CurrentWorkerId(), callbacks_id,
|
| + base::Unretained(waitable_results))),
|
| + make_scoped_ptr(waitable_results));
|
| }
|
|
|
| void WebFileSystemImpl::copy(
|
| @@ -274,50 +338,67 @@ void WebFileSystemImpl::copy(
|
| const WebKit::WebURL& dest_path,
|
| WebKit::WebFileSystemCallbacks* callbacks) {
|
| int callbacks_id = CallbacksMap::GetOrCreate()->RegisterCallbacks(callbacks);
|
| + WaitableCallbackResults* waitable_results =
|
| + WaitableCallbackResults::MaybeCreate(callbacks);
|
| CallDispatcherOnMainThread(
|
| main_thread_loop_.get(),
|
| &FileSystemDispatcher::Copy,
|
| MakeTuple(GURL(src_path), GURL(dest_path),
|
| base::Bind(&StatusCallbackAdapter,
|
| - CurrentWorkerId(), callbacks_id)));
|
| + CurrentWorkerId(), callbacks_id,
|
| + base::Unretained(waitable_results))),
|
| + make_scoped_ptr(waitable_results));
|
| }
|
|
|
| void WebFileSystemImpl::remove(
|
| const WebKit::WebURL& path,
|
| WebKit::WebFileSystemCallbacks* callbacks) {
|
| int callbacks_id = CallbacksMap::GetOrCreate()->RegisterCallbacks(callbacks);
|
| + WaitableCallbackResults* waitable_results =
|
| + WaitableCallbackResults::MaybeCreate(callbacks);
|
| CallDispatcherOnMainThread(
|
| main_thread_loop_.get(),
|
| &FileSystemDispatcher::Remove,
|
| MakeTuple(GURL(path), false /* recursive */,
|
| base::Bind(&StatusCallbackAdapter,
|
| - CurrentWorkerId(), callbacks_id)));
|
| + CurrentWorkerId(), callbacks_id,
|
| + base::Unretained(waitable_results))),
|
| + make_scoped_ptr(waitable_results));
|
| }
|
|
|
| void WebFileSystemImpl::removeRecursively(
|
| const WebKit::WebURL& path,
|
| WebKit::WebFileSystemCallbacks* callbacks) {
|
| int callbacks_id = CallbacksMap::GetOrCreate()->RegisterCallbacks(callbacks);
|
| + WaitableCallbackResults* waitable_results =
|
| + WaitableCallbackResults::MaybeCreate(callbacks);
|
| CallDispatcherOnMainThread(
|
| main_thread_loop_.get(),
|
| &FileSystemDispatcher::Remove,
|
| MakeTuple(GURL(path), true /* recursive */,
|
| base::Bind(&StatusCallbackAdapter,
|
| - CurrentWorkerId(), callbacks_id)));
|
| + CurrentWorkerId(), callbacks_id,
|
| + base::Unretained(waitable_results))),
|
| + make_scoped_ptr(waitable_results));
|
| }
|
|
|
| void WebFileSystemImpl::readMetadata(
|
| const WebKit::WebURL& path,
|
| WebKit::WebFileSystemCallbacks* callbacks) {
|
| int callbacks_id = CallbacksMap::GetOrCreate()->RegisterCallbacks(callbacks);
|
| + WaitableCallbackResults* waitable_results =
|
| + WaitableCallbackResults::MaybeCreate(callbacks);
|
| CallDispatcherOnMainThread(
|
| main_thread_loop_.get(),
|
| &FileSystemDispatcher::ReadMetadata,
|
| MakeTuple(GURL(path),
|
| base::Bind(&ReadMetadataCallbackAdapter,
|
| - CurrentWorkerId(), callbacks_id),
|
| + CurrentWorkerId(), callbacks_id,
|
| + base::Unretained(waitable_results)),
|
| base::Bind(&StatusCallbackAdapter,
|
| - CurrentWorkerId(), callbacks_id)));
|
| + CurrentWorkerId(), callbacks_id,
|
| + base::Unretained(waitable_results))),
|
| + make_scoped_ptr(waitable_results));
|
| }
|
|
|
| void WebFileSystemImpl::createFile(
|
| @@ -325,12 +406,16 @@ void WebFileSystemImpl::createFile(
|
| bool exclusive,
|
| WebKit::WebFileSystemCallbacks* callbacks) {
|
| int callbacks_id = CallbacksMap::GetOrCreate()->RegisterCallbacks(callbacks);
|
| + WaitableCallbackResults* waitable_results =
|
| + WaitableCallbackResults::MaybeCreate(callbacks);
|
| CallDispatcherOnMainThread(
|
| main_thread_loop_.get(),
|
| &FileSystemDispatcher::CreateFile,
|
| MakeTuple(GURL(path), exclusive,
|
| base::Bind(&StatusCallbackAdapter,
|
| - CurrentWorkerId(), callbacks_id)));
|
| + CurrentWorkerId(), callbacks_id,
|
| + base::Unretained(waitable_results))),
|
| + make_scoped_ptr(waitable_results));
|
| }
|
|
|
| void WebFileSystemImpl::createDirectory(
|
| @@ -338,50 +423,67 @@ void WebFileSystemImpl::createDirectory(
|
| bool exclusive,
|
| WebKit::WebFileSystemCallbacks* callbacks) {
|
| int callbacks_id = CallbacksMap::GetOrCreate()->RegisterCallbacks(callbacks);
|
| + WaitableCallbackResults* waitable_results =
|
| + WaitableCallbackResults::MaybeCreate(callbacks);
|
| CallDispatcherOnMainThread(
|
| main_thread_loop_.get(),
|
| &FileSystemDispatcher::CreateDirectory,
|
| MakeTuple(GURL(path), exclusive, false /* recursive */,
|
| base::Bind(&StatusCallbackAdapter,
|
| - CurrentWorkerId(), callbacks_id)));
|
| + CurrentWorkerId(), callbacks_id,
|
| + base::Unretained(waitable_results))),
|
| + make_scoped_ptr(waitable_results));
|
| }
|
|
|
| void WebFileSystemImpl::fileExists(
|
| const WebKit::WebURL& path,
|
| WebKit::WebFileSystemCallbacks* callbacks) {
|
| int callbacks_id = CallbacksMap::GetOrCreate()->RegisterCallbacks(callbacks);
|
| + WaitableCallbackResults* waitable_results =
|
| + WaitableCallbackResults::MaybeCreate(callbacks);
|
| CallDispatcherOnMainThread(
|
| main_thread_loop_.get(),
|
| &FileSystemDispatcher::Exists,
|
| MakeTuple(GURL(path), false /* directory */,
|
| base::Bind(&StatusCallbackAdapter,
|
| - CurrentWorkerId(), callbacks_id)));
|
| + CurrentWorkerId(), callbacks_id,
|
| +base::Unretained(waitable_results))),
|
| + make_scoped_ptr(waitable_results));
|
| }
|
|
|
| void WebFileSystemImpl::directoryExists(
|
| const WebKit::WebURL& path,
|
| WebKit::WebFileSystemCallbacks* callbacks) {
|
| int callbacks_id = CallbacksMap::GetOrCreate()->RegisterCallbacks(callbacks);
|
| + WaitableCallbackResults* waitable_results =
|
| + WaitableCallbackResults::MaybeCreate(callbacks);
|
| CallDispatcherOnMainThread(
|
| main_thread_loop_.get(),
|
| &FileSystemDispatcher::Exists,
|
| MakeTuple(GURL(path), true /* directory */,
|
| base::Bind(&StatusCallbackAdapter,
|
| - CurrentWorkerId(), callbacks_id)));
|
| + CurrentWorkerId(), callbacks_id,
|
| + base::Unretained(waitable_results))),
|
| + make_scoped_ptr(waitable_results));
|
| }
|
|
|
| void WebFileSystemImpl::readDirectory(
|
| const WebKit::WebURL& path,
|
| WebKit::WebFileSystemCallbacks* callbacks) {
|
| int callbacks_id = CallbacksMap::GetOrCreate()->RegisterCallbacks(callbacks);
|
| + WaitableCallbackResults* waitable_results =
|
| + WaitableCallbackResults::MaybeCreate(callbacks);
|
| CallDispatcherOnMainThread(
|
| main_thread_loop_.get(),
|
| &FileSystemDispatcher::ReadDirectory,
|
| MakeTuple(GURL(path),
|
| base::Bind(&ReadDirectoryCallbackAdapater,
|
| - CurrentWorkerId(), callbacks_id),
|
| + CurrentWorkerId(), callbacks_id,
|
| + base::Unretained(waitable_results)),
|
| base::Bind(&StatusCallbackAdapter,
|
| - CurrentWorkerId(), callbacks_id)));
|
| + CurrentWorkerId(), callbacks_id,
|
| +base::Unretained(waitable_results))),
|
| + make_scoped_ptr(waitable_results));
|
| }
|
|
|
| WebKit::WebFileWriter* WebFileSystemImpl::createFileWriter(
|
| @@ -394,30 +496,40 @@ void WebFileSystemImpl::createFileWriter(
|
| WebKit::WebFileWriterClient* client,
|
| WebKit::WebFileSystemCallbacks* callbacks) {
|
| int callbacks_id = CallbacksMap::GetOrCreate()->RegisterCallbacks(callbacks);
|
| + WaitableCallbackResults* waitable_results =
|
| + WaitableCallbackResults::MaybeCreate(callbacks);
|
| CallDispatcherOnMainThread(
|
| main_thread_loop_.get(),
|
| &FileSystemDispatcher::ReadMetadata,
|
| MakeTuple(GURL(path),
|
| base::Bind(&CreateFileWriterCallbackAdapter,
|
| - CurrentWorkerId(), callbacks_id, main_thread_loop_,
|
| - GURL(path), client),
|
| + CurrentWorkerId(), callbacks_id,
|
| + base::Unretained(waitable_results),
|
| + main_thread_loop_, GURL(path), client),
|
| base::Bind(&StatusCallbackAdapter,
|
| - CurrentWorkerId(), callbacks_id)));
|
| + CurrentWorkerId(), callbacks_id,
|
| + base::Unretained(waitable_results))),
|
| + make_scoped_ptr(waitable_results));
|
| }
|
|
|
| void WebFileSystemImpl::createSnapshotFileAndReadMetadata(
|
| const WebKit::WebURL& path,
|
| WebKit::WebFileSystemCallbacks* callbacks) {
|
| int callbacks_id = CallbacksMap::GetOrCreate()->RegisterCallbacks(callbacks);
|
| + WaitableCallbackResults* waitable_results =
|
| + WaitableCallbackResults::MaybeCreate(callbacks);
|
| CallDispatcherOnMainThread(
|
| main_thread_loop_.get(),
|
| &FileSystemDispatcher::CreateSnapshotFile,
|
| MakeTuple(GURL(path),
|
| base::Bind(&CreateSnapshotFileCallbackAdapter,
|
| CurrentWorkerId(), callbacks_id,
|
| + base::Unretained(waitable_results),
|
| main_thread_loop_),
|
| base::Bind(&StatusCallbackAdapter,
|
| - CurrentWorkerId(), callbacks_id)));
|
| + CurrentWorkerId(), callbacks_id,
|
| + base::Unretained(waitable_results))),
|
| + make_scoped_ptr(waitable_results));
|
| }
|
|
|
| } // namespace content
|
|
|