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..30f7fd0309104a522c563c97a2d1c8f94ca5f6c8 100644 |
--- a/content/child/fileapi/webfilesystem_impl.cc |
+++ b/content/child/fileapi/webfilesystem_impl.cc |
@@ -5,14 +5,20 @@ |
#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" |
#include "content/child/fileapi/webfilewriter_impl.h" |
-#include "third_party/WebKit/public/web/WebFileSystemCallbacks.h" |
+#include "content/child/thread_safe_sender.h" |
+#include "content/common/fileapi/file_system_messages.h" |
#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 "third_party/WebKit/public/web/WebFileSystemCallbacks.h" |
+#include "url/gurl.h" |
+#include "webkit/child/worker_task_runner.h" |
#include "webkit/glue/webkit_glue.h" |
using WebKit::WebFileInfo; |
@@ -21,6 +27,7 @@ using WebKit::WebFileSystemEntry; |
using WebKit::WebString; |
using WebKit::WebURL; |
using WebKit::WebVector; |
+using webkit_glue::WorkerTaskRunner; |
namespace content { |
@@ -39,107 +46,265 @@ void DidReadMetadataForCreateFileWriter( |
file_info.size); |
} |
+int CurrentWorkerId() { |
+ return WorkerTaskRunner::Instance()->CurrentWorkerId(); |
+} |
+ |
+class CallbacksWrapper |
+ : public WebFileSystemCallbacks, |
+ public WorkerTaskRunner::Observer { |
+ public: |
+ CallbacksWrapper(WebFileSystemCallbacks* original_callbacks, |
+ ThreadSafeSender* thread_safe_sender) |
+ : callbacks_(original_callbacks), |
+ thread_safe_sender_(thread_safe_sender), |
+ worker_id_(CurrentWorkerId()) { |
+ if (worker_id_) |
+ WorkerTaskRunner::Instance()->AddStopObserver(this); |
+ } |
+ |
+ virtual ~CallbacksWrapper() { |
+ if (CurrentWorkerId()) |
+ WorkerTaskRunner::Instance()->RemoveStopObserver(this); |
+ } |
+ |
+ // WorkerTaskRunner::Observer overrides. |
+ virtual void OnWorkerRunLoopStopped() OVERRIDE { |
+ callbacks_->didFail(WebKit::WebFileErrorAbort); |
+ callbacks_ = NULL; |
+ } |
+ |
+ // 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, |
+ int request_id) { |
+ if (worker_id_ != CurrentWorkerId()) { |
+ PostTaskToWorker( |
+ base::Bind(&CallbacksWrapper::DidCreateSnapshotFile, |
+ base::Unretained(this), file_info, platform_path, |
+ request_id)); |
+ return; |
+ } |
+ scoped_ptr<CallbacksWrapper> deleter(this); |
+ DCHECK(callbacks_); |
+ WebFileInfo web_file_info; |
+ webkit_glue::PlatformFileInfoToWebFileInfo(file_info, &web_file_info); |
+ web_file_info.platformPath = platform_path.AsUTF16Unsafe(); |
+ callbacks_->didCreateSnapshotFile(web_file_info); |
+ |
+ thread_safe_sender_->Send( |
+ new FileSystemHostMsg_DidReceiveSnapshotFile(request_id)); |
michaeln
2013/07/24 22:21:12
Drat, I think i gave you a bum steer, very sorry :
kinuko
2013/07/25 04:32:41
Yup... I vaguely remember that's how I decided to
|
+ } |
+ |
+ private: |
+ void RunCallback(const base::Closure& callback) { |
+ if (worker_id_ != CurrentWorkerId()) { |
+ PostTaskToWorker(base::Bind(&CallbacksWrapper::RunCallback, |
+ base::Unretained(this), callback)); |
+ return; |
+ } |
+ scoped_ptr<CallbacksWrapper> deleter(this); |
+ DCHECK(callbacks_); |
+ callback.Run(); |
+ } |
+ |
+ void PostTaskToWorker(const base::Closure& closure) { |
+ if (!WorkerTaskRunner::Instance()->PostTask(worker_id_, closure)) |
+ delete this; |
michaeln
2013/07/24 22:21:12
I'm really not sure about 'delete this' correctnes
kinuko
2013/07/25 04:32:41
Right. I overlooked PostTask returns false when Wo
michaeln
2013/07/25 21:39:08
For a process shutdown leaks, who cares, but these
kinuko
2013/07/26 12:29:55
My initial implementation was exactlly following I
|
+ } |
+ |
+ WebFileSystemCallbacks* callbacks_; |
+ scoped_refptr<ThreadSafeSender> thread_safe_sender_; |
+ int worker_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); |
+ return; |
+ } |
+ DispatchToMethod(ChildThread::current()->file_system_dispatcher(), |
+ method, params); |
+} |
+ |
} // namespace |
-WebFileSystemImpl::WebFileSystemImpl() { |
+WebFileSystemImpl::WebFileSystemImpl( |
+ base::MessageLoopProxy* main_thread_loop, |
+ ThreadSafeSender* sender) |
+ : main_thread_loop_(main_thread_loop), |
+ sender_(sender) { |
+ // 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, sender_.get()); |
+ 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, sender_.get()); |
+ 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, sender_.get()); |
+ 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, sender_.get()); |
+ 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, sender_.get()); |
+ 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, sender_.get()); |
+ 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, sender_.get()); |
+ 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, sender_.get()); |
+ 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, sender_.get()); |
+ 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, sender_.get()); |
+ 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 +316,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 +330,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, sender_.get()); |
+ CallDispatcherOnMainThread( |
+ main_thread_loop_.get(), |
+ &FileSystemDispatcher::CreateSnapshotFile, |
+ MakeTuple(GURL(path), |
+ base::Bind(&CallbacksWrapper::DidCreateSnapshotFile, |
+ base::Unretained(wrapper)), |
+ base::Bind(&FileStatusCallbackAdapter, wrapper)), |
+ wrapper); |
} |
} // namespace content |