Chromium Code Reviews| Index: content/child/fileapi/webfilesystem_impl.cc |
| diff --git a/content/child/fileapi/webfilesystem_impl.cc b/content/child/fileapi/webfilesystem_impl.cc |
| index 9bb8664f9bcd3debf0d755ec8811c0665079c2df..013715d72f31503b2d1bfdbf8f589536279b47e3 100644 |
| --- a/content/child/fileapi/webfilesystem_impl.cc |
| +++ b/content/child/fileapi/webfilesystem_impl.cc |
| @@ -5,6 +5,8 @@ |
| #include "content/child/fileapi/webfilesystem_impl.h" |
| #include "base/bind.h" |
| +#include "base/logging.h" |
| +#include "base/message_loop/message_loop_proxy.h" |
| #include "content/child/child_thread.h" |
| #include "content/child/fileapi/file_system_dispatcher.h" |
| #include "content/child/fileapi/webfilesystem_callback_adapters.h" |
| @@ -13,6 +15,8 @@ |
| #include "third_party/WebKit/public/platform/WebFileInfo.h" |
| #include "third_party/WebKit/public/platform/WebString.h" |
| #include "third_party/WebKit/public/platform/WebURL.h" |
| +#include "url/gurl.h" |
| +#include "webkit/child/worker_task_runner.h" |
| #include "webkit/glue/webkit_glue.h" |
| using WebKit::WebFileInfo; |
| @@ -21,6 +25,7 @@ using WebKit::WebFileSystemEntry; |
| using WebKit::WebString; |
| using WebKit::WebURL; |
| using WebKit::WebVector; |
| +using webkit_glue::WorkerTaskRunner; |
| namespace content { |
| @@ -39,107 +44,254 @@ void DidReadMetadataForCreateFileWriter( |
| file_info.size); |
| } |
| +int CurrentWorkerId() { |
| + return WorkerTaskRunner::Instance()->CurrentWorkerId(); |
| +} |
| + |
| +class CallbacksWrapper |
| + : public WebFileSystemCallbacks, |
| + public WorkerTaskRunner::Observer { |
| + public: |
| + explicit CallbacksWrapper(WebFileSystemCallbacks* original_callbacks) |
| + : callbacks_(original_callbacks), |
| + thread_id_(CurrentWorkerId()) { |
| + if (thread_id_) |
| + WorkerTaskRunner::Instance()->AddStopObserver(this); |
| + } |
| + |
| + virtual ~CallbacksWrapper() { |
| + if (CurrentWorkerId()) |
| + WorkerTaskRunner::Instance()->RemoveStopObserver(this); |
| + } |
| + |
| + // WorkerTaskRunner::Observer overrides. |
| + virtual void OnWorkerRunLoopStopped() OVERRIDE { |
|
michaeln
2013/07/24 00:54:08
At this point the worker run loop is wound down an
michaeln
2013/07/24 01:38:58
Or i guess what i meant to say was, maybe just {
kinuko
2013/07/24 09:29:09
Current API is designed as 1. the callback is self
kinuko
2013/07/24 11:03:29
Well... on the second look the current API seems t
kinuko
2013/07/24 11:15:41
Oops, callbacks can't be deleted from outside sinc
|
| + callbacks_->didFail(WebKit::WebFileErrorAbort); |
| + delete this; |
|
michaeln
2013/07/24 06:19:13
Oh, I have another question about this method?
Po
kinuko
2013/07/24 09:29:09
Ah, in the main thread side-- yes, good catch. Fi
|
| + } |
| + |
| + // WebFileSystemCallbacks overrides. |
| + virtual void didSucceed() OVERRIDE { |
| + RunCallback(base::Bind(&WebFileSystemCallbacks::didSucceed, |
| + base::Unretained(callbacks_))); |
| + } |
| + virtual void didReadMetadata(const WebFileInfo& info) OVERRIDE { |
| + RunCallback(base::Bind(&WebFileSystemCallbacks::didReadMetadata, |
| + base::Unretained(callbacks_), info)); |
| + } |
| + virtual void didReadDirectory(const WebVector<WebFileSystemEntry>& entries, |
| + bool hasMore) OVERRIDE { |
| + RunCallback(base::Bind(&WebFileSystemCallbacks::didReadDirectory, |
| + base::Unretained(callbacks_), entries, hasMore)); |
| + } |
| + virtual void didOpenFileSystem(const WebString& name, |
| + const WebURL& rootURL) OVERRIDE { |
| + RunCallback(base::Bind(&WebFileSystemCallbacks::didOpenFileSystem, |
| + base::Unretained(callbacks_), name, rootURL)); |
| + } |
| + virtual void didFail(WebKit::WebFileError error) OVERRIDE { |
| + RunCallback(base::Bind(&WebFileSystemCallbacks::didFail, |
| + base::Unretained(callbacks_), error)); |
| + } |
| + virtual bool shouldBlockUntilCompletion() const OVERRIDE { |
| + return callbacks_->shouldBlockUntilCompletion(); |
| + } |
| + |
| + void DidCreateSnapshotFile(const base::PlatformFileInfo& file_info, |
| + const base::FilePath& platform_path, |
| + const base::Closure& did_receive_snapshot) { |
| + if (thread_id_ != CurrentWorkerId()) { |
| + WorkerTaskRunner::Instance()->PostTask( |
| + thread_id_, |
| + base::Bind(&CallbacksWrapper::DidCreateSnapshotFile, |
| + base::Unretained(this), file_info, platform_path, |
| + did_receive_snapshot)); |
| + return; |
| + } |
| + scoped_ptr<CallbacksWrapper> deleter(this); |
| + WebFileInfo web_file_info; |
| + webkit_glue::PlatformFileInfoToWebFileInfo(file_info, &web_file_info); |
| + web_file_info.platformPath = platform_path.AsUTF16Unsafe(); |
| + callbacks_->didCreateSnapshotFile(web_file_info); |
| + did_receive_snapshot.Run(); |
| + } |
| + |
| + private: |
| + void RunCallback(const base::Closure& callback) { |
| + if (thread_id_ != CurrentWorkerId()) { |
| + WorkerTaskRunner::Instance()->PostTask( |
| + thread_id_, |
| + base::Bind(&CallbacksWrapper::RunCallback, |
| + base::Unretained(this), callback)); |
| + return; |
| + } |
| + scoped_ptr<CallbacksWrapper> deleter(this); |
| + callback.Run(); |
| + } |
| + |
| + WebFileSystemCallbacks* callbacks_; |
| + int thread_id_; |
| +}; |
| + |
| +template <typename Method, typename Params> |
| +void CallDispatcherOnMainThread( |
| + base::MessageLoopProxy* loop, |
| + Method method, const Params& params, |
| + WebFileSystemCallbacks* callbacks) { |
| + if (!loop->RunsTasksOnCurrentThread()) { |
| + loop->PostTask(FROM_HERE, |
| + base::Bind(&CallDispatcherOnMainThread<Method, Params>, |
| + make_scoped_refptr(loop), |
| + method, params, callbacks)); |
| + return; |
| + } |
| + if (!ChildThread::current() || |
| + !ChildThread::current()->file_system_dispatcher()) { |
| + callbacks->didFail(WebKit::WebFileErrorAbort); |
|
michaeln
2013/07/24 00:54:08
It looks like didFail() can be called on the main
kinuko
2013/07/24 09:29:09
Done.
|
| + return; |
| + } |
| + DispatchToMethod(ChildThread::current()->file_system_dispatcher(), |
| + method, params); |
| +} |
| + |
| } // namespace |
| -WebFileSystemImpl::WebFileSystemImpl() { |
| +WebFileSystemImpl::WebFileSystemImpl( |
| + base::MessageLoopProxy* main_thread_loop) |
| + : main_thread_loop_(main_thread_loop) { |
| + // TODO(kinuko): Support creating and accessing WebFileSystemImpl on |
| + // non-main thread. (crbug.com/257349) |
| + DCHECK(main_thread_loop_->RunsTasksOnCurrentThread()); |
| } |
| -void WebFileSystemImpl::move(const WebURL& src_path, |
| - const WebURL& dest_path, |
| - WebFileSystemCallbacks* callbacks) { |
| - FileSystemDispatcher* dispatcher = |
| - ChildThread::current()->file_system_dispatcher(); |
| - dispatcher->Move(GURL(src_path), |
| - GURL(dest_path), |
| - base::Bind(&FileStatusCallbackAdapter, callbacks)); |
| +WebFileSystemImpl::~WebFileSystemImpl() { |
| } |
| -void WebFileSystemImpl::copy(const WebURL& src_path, |
| - const WebURL& dest_path, |
| - WebFileSystemCallbacks* callbacks) { |
| - FileSystemDispatcher* dispatcher = |
| - ChildThread::current()->file_system_dispatcher(); |
| - dispatcher->Copy(GURL(src_path), |
| - GURL(dest_path), |
| - base::Bind(&FileStatusCallbackAdapter, callbacks)); |
| +// WebFileSystem implementation. |
| +void WebFileSystemImpl::move( |
| + const WebKit::WebURL& src_path, |
| + const WebKit::WebURL& dest_path, |
| + WebKit::WebFileSystemCallbacks* callbacks) { |
| + CallbacksWrapper* wrapper = new CallbacksWrapper(callbacks); |
| + CallDispatcherOnMainThread( |
| + main_thread_loop_.get(), |
| + &FileSystemDispatcher::Move, |
| + MakeTuple(GURL(src_path), GURL(dest_path), |
| + base::Bind(&FileStatusCallbackAdapter, wrapper)), |
| + wrapper); |
| } |
| -void WebFileSystemImpl::remove(const WebURL& path, |
| - WebFileSystemCallbacks* callbacks) { |
| - FileSystemDispatcher* dispatcher = |
| - ChildThread::current()->file_system_dispatcher(); |
| - dispatcher->Remove( |
| - GURL(path), |
| - false /* recursive */, |
| - base::Bind(&FileStatusCallbackAdapter, callbacks)); |
| +void WebFileSystemImpl::copy( |
| + const WebKit::WebURL& src_path, |
| + const WebKit::WebURL& dest_path, |
| + WebKit::WebFileSystemCallbacks* callbacks) { |
| + CallbacksWrapper* wrapper = new CallbacksWrapper(callbacks); |
| + CallDispatcherOnMainThread( |
| + main_thread_loop_.get(), |
| + &FileSystemDispatcher::Copy, |
| + MakeTuple(GURL(src_path), GURL(dest_path), |
| + base::Bind(&FileStatusCallbackAdapter, wrapper)), |
| + wrapper); |
| } |
| -void WebFileSystemImpl::removeRecursively(const WebURL& path, |
| - WebFileSystemCallbacks* callbacks) { |
| - FileSystemDispatcher* dispatcher = |
| - ChildThread::current()->file_system_dispatcher(); |
| - dispatcher->Remove( |
| - GURL(path), |
| - true /* recursive */, |
| - base::Bind(&FileStatusCallbackAdapter, callbacks)); |
| +void WebFileSystemImpl::remove( |
| + const WebKit::WebURL& path, |
| + WebKit::WebFileSystemCallbacks* callbacks) { |
| + CallbacksWrapper* wrapper = new CallbacksWrapper(callbacks); |
| + CallDispatcherOnMainThread( |
| + main_thread_loop_.get(), |
| + &FileSystemDispatcher::Remove, |
| + MakeTuple(GURL(path), false /* recursive */, |
| + base::Bind(&FileStatusCallbackAdapter, wrapper)), |
| + wrapper); |
| } |
| -void WebFileSystemImpl::readMetadata(const WebURL& path, |
| - WebFileSystemCallbacks* callbacks) { |
| - FileSystemDispatcher* dispatcher = |
| - ChildThread::current()->file_system_dispatcher(); |
| - dispatcher->ReadMetadata( |
| - GURL(path), |
| - base::Bind(&ReadMetadataCallbackAdapter, callbacks), |
| - base::Bind(&FileStatusCallbackAdapter, callbacks)); |
| +void WebFileSystemImpl::removeRecursively( |
| + const WebKit::WebURL& path, |
| + WebKit::WebFileSystemCallbacks* callbacks) { |
| + CallbacksWrapper* wrapper = new CallbacksWrapper(callbacks); |
| + CallDispatcherOnMainThread( |
| + main_thread_loop_.get(), |
| + &FileSystemDispatcher::Remove, |
| + MakeTuple(GURL(path), true /* recursive */, |
| + base::Bind(&FileStatusCallbackAdapter, wrapper)), |
| + wrapper); |
| } |
| -void WebFileSystemImpl::createFile(const WebURL& path, |
| - bool exclusive, |
| - WebFileSystemCallbacks* callbacks) { |
| - FileSystemDispatcher* dispatcher = |
| - ChildThread::current()->file_system_dispatcher(); |
| - dispatcher->CreateFile( |
| - GURL(path), exclusive, |
| - base::Bind(&FileStatusCallbackAdapter, callbacks)); |
| +void WebFileSystemImpl::readMetadata( |
| + const WebKit::WebURL& path, |
| + WebKit::WebFileSystemCallbacks* callbacks) { |
| + CallbacksWrapper* wrapper = new CallbacksWrapper(callbacks); |
| + CallDispatcherOnMainThread( |
| + main_thread_loop_.get(), |
| + &FileSystemDispatcher::ReadMetadata, |
| + MakeTuple(GURL(path), |
| + base::Bind(&ReadMetadataCallbackAdapter, wrapper), |
| + base::Bind(&FileStatusCallbackAdapter, wrapper)), |
| + wrapper); |
| } |
| -void WebFileSystemImpl::createDirectory(const WebURL& path, |
| - bool exclusive, |
| - WebFileSystemCallbacks* callbacks) { |
| - FileSystemDispatcher* dispatcher = |
| - ChildThread::current()->file_system_dispatcher(); |
| - dispatcher->CreateDirectory( |
| - GURL(path), exclusive, false /* recursive */, |
| - base::Bind(&FileStatusCallbackAdapter, callbacks)); |
| +void WebFileSystemImpl::createFile( |
| + const WebKit::WebURL& path, |
| + bool exclusive, |
| + WebKit::WebFileSystemCallbacks* callbacks) { |
| + CallbacksWrapper* wrapper = new CallbacksWrapper(callbacks); |
| + CallDispatcherOnMainThread( |
| + main_thread_loop_.get(), |
| + &FileSystemDispatcher::CreateFile, |
| + MakeTuple(GURL(path), exclusive, |
| + base::Bind(&FileStatusCallbackAdapter, wrapper)), |
| + wrapper); |
| } |
| -void WebFileSystemImpl::fileExists(const WebURL& path, |
| - WebFileSystemCallbacks* callbacks) { |
| - FileSystemDispatcher* dispatcher = |
| - ChildThread::current()->file_system_dispatcher(); |
| - dispatcher->Exists( |
| - GURL(path), false /* directory */, |
| - base::Bind(&FileStatusCallbackAdapter, callbacks)); |
| +void WebFileSystemImpl::createDirectory( |
| + const WebKit::WebURL& path, |
| + bool exclusive, |
| + WebKit::WebFileSystemCallbacks* callbacks) { |
| + CallbacksWrapper* wrapper = new CallbacksWrapper(callbacks); |
| + CallDispatcherOnMainThread( |
| + main_thread_loop_.get(), |
| + &FileSystemDispatcher::CreateDirectory, |
| + MakeTuple(GURL(path), exclusive, false /* recursive */, |
| + base::Bind(&FileStatusCallbackAdapter, wrapper)), |
| + wrapper); |
| } |
| -void WebFileSystemImpl::directoryExists(const WebURL& path, |
| - WebFileSystemCallbacks* callbacks) { |
| - FileSystemDispatcher* dispatcher = |
| - ChildThread::current()->file_system_dispatcher(); |
| - dispatcher->Exists( |
| - GURL(path), true /* directory */, |
| - base::Bind(&FileStatusCallbackAdapter, callbacks)); |
| +void WebFileSystemImpl::fileExists( |
| + const WebKit::WebURL& path, |
| + WebKit::WebFileSystemCallbacks* callbacks) { |
| + CallbacksWrapper* wrapper = new CallbacksWrapper(callbacks); |
| + CallDispatcherOnMainThread( |
| + main_thread_loop_.get(), |
| + &FileSystemDispatcher::Exists, |
| + MakeTuple(GURL(path), false /* directory */, |
| + base::Bind(&FileStatusCallbackAdapter, wrapper)), |
| + wrapper); |
| } |
| -void WebFileSystemImpl::readDirectory(const WebURL& path, |
| - WebFileSystemCallbacks* callbacks) { |
| - FileSystemDispatcher* dispatcher = |
| - ChildThread::current()->file_system_dispatcher(); |
| - dispatcher->ReadDirectory( |
| - GURL(path), |
| - base::Bind(&ReadDirectoryCallbackAdapater, callbacks), |
| - base::Bind(&FileStatusCallbackAdapter, callbacks)); |
| +void WebFileSystemImpl::directoryExists( |
| + const WebKit::WebURL& path, |
| + WebKit::WebFileSystemCallbacks* callbacks) { |
| + CallbacksWrapper* wrapper = new CallbacksWrapper(callbacks); |
| + CallDispatcherOnMainThread( |
| + main_thread_loop_.get(), |
| + &FileSystemDispatcher::Exists, |
| + MakeTuple(GURL(path), true /* directory */, |
| + base::Bind(&FileStatusCallbackAdapter, wrapper)), |
| + wrapper); |
| +} |
| + |
| +void WebFileSystemImpl::readDirectory( |
| + const WebKit::WebURL& path, |
| + WebKit::WebFileSystemCallbacks* callbacks) { |
| + CallbacksWrapper* wrapper = new CallbacksWrapper(callbacks); |
| + CallDispatcherOnMainThread( |
| + main_thread_loop_.get(), |
| + &FileSystemDispatcher::ReadDirectory, |
| + MakeTuple(GURL(path), |
| + base::Bind(&ReadDirectoryCallbackAdapater, wrapper), |
| + base::Bind(&FileStatusCallbackAdapter, wrapper)), |
| + wrapper); |
| } |
| WebKit::WebFileWriter* WebFileSystemImpl::createFileWriter( |
| @@ -151,6 +303,8 @@ void WebFileSystemImpl::createFileWriter( |
| const WebURL& path, |
| WebKit::WebFileWriterClient* client, |
| WebKit::WebFileSystemCallbacks* callbacks) { |
| + // TODO(kinuko): Convert this method to use bridge model. (crbug.com/257349) |
| + DCHECK(main_thread_loop_->RunsTasksOnCurrentThread()); |
| FileSystemDispatcher* dispatcher = |
| ChildThread::current()->file_system_dispatcher(); |
| dispatcher->ReadMetadata( |
| @@ -163,12 +317,15 @@ void WebFileSystemImpl::createFileWriter( |
| void WebFileSystemImpl::createSnapshotFileAndReadMetadata( |
| const WebKit::WebURL& path, |
| WebKit::WebFileSystemCallbacks* callbacks) { |
| - FileSystemDispatcher* dispatcher = |
| - ChildThread::current()->file_system_dispatcher(); |
| - dispatcher->CreateSnapshotFile( |
| - GURL(path), |
| - base::Bind(&CreateSnapshotFileCallbackAdapter, callbacks), |
| - base::Bind(&FileStatusCallbackAdapter, callbacks)); |
| + CallbacksWrapper* wrapper = new CallbacksWrapper(callbacks); |
| + CallDispatcherOnMainThread( |
| + main_thread_loop_.get(), |
| + &FileSystemDispatcher::CreateSnapshotFile, |
| + MakeTuple(GURL(path), |
| + base::Bind(&CallbacksWrapper::DidCreateSnapshotFile, |
| + base::Unretained(wrapper)), |
| + base::Bind(&FileStatusCallbackAdapter, wrapper)), |
| + wrapper); |
| } |
| } // namespace content |