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 |