From 89b2e712e85559ceb5b7df4f9bde7d64fb72c590 Mon Sep 17 00:00:00 2001 From: "kinuko@chromium.org" Date: Thu, 1 Aug 2013 13:51:03 +0000 Subject: Support synchronous mode for FileSystem/FileWriter API BUG=257349 TEST=no behavioral changes (until we switch blink code) R=michaeln@chromium.org Review URL: https://codereview.chromium.org/21091007 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@215024 0039d316-1c4b-4281-b951-d872f2087c98 --- content/child/fileapi/webfilesystem_impl.cc | 230 +++++++++++++++++++++------- 1 file changed, 171 insertions(+), 59 deletions(-) (limited to 'content/child/fileapi') diff --git a/content/child/fileapi/webfilesystem_impl.cc b/content/child/fileapi/webfilesystem_impl.cc index 090bf7d..78952b5 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 void CallDispatcherOnMainThread( base::MessageLoopProxy* loop, - Method method, const Params& params) { + Method method, const Params& params, + scoped_ptr waitable_results) { + scoped_ptr null_waitable; if (!loop->RunsTasksOnCurrentThread()) { loop->PostTask(FROM_HERE, base::Bind(&CallDispatcherOnMainThread, - 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 -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, - 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 +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, 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& entries, bool has_more) { WebVector 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 -- cgit v1.1