Index: trunk/src/content/child/fileapi/webfilesystem_impl.cc |
=================================================================== |
--- trunk/src/content/child/fileapi/webfilesystem_impl.cc (revision 214653) |
+++ trunk/src/content/child/fileapi/webfilesystem_impl.cc (working copy) |
@@ -5,14 +5,24 @@ |
#include "content/child/fileapi/webfilesystem_impl.h" |
#include "base/bind.h" |
+#include "base/id_map.h" |
+#include "base/lazy_instance.h" |
+#include "base/logging.h" |
+#include "base/message_loop/message_loop_proxy.h" |
+#include "base/threading/thread_local.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/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/common/fileapi/directory_entry.h" |
+#include "webkit/common/fileapi/file_system_util.h" |
#include "webkit/glue/webkit_glue.h" |
using WebKit::WebFileInfo; |
@@ -21,11 +31,69 @@ |
using WebKit::WebString; |
using WebKit::WebURL; |
using WebKit::WebVector; |
+using webkit_glue::WorkerTaskRunner; |
namespace content { |
namespace { |
+class CallbacksMap; |
+ |
+base::LazyInstance<base::ThreadLocalPointer<CallbacksMap> >::Leaky |
+ g_callbacks_map_tls = LAZY_INSTANCE_INITIALIZER; |
+ |
+// TODO(kinuko): Integrate this into WebFileSystemImpl when blink side |
+// becomes ready to make WebFileSystemImpl thread-local. |
+class CallbacksMap : public WorkerTaskRunner::Observer { |
+ public: |
+ static CallbacksMap* Get() { |
+ return g_callbacks_map_tls.Pointer()->Get(); |
+ } |
+ |
+ static CallbacksMap* GetOrCreate() { |
+ if (g_callbacks_map_tls.Pointer()->Get()) |
+ return g_callbacks_map_tls.Pointer()->Get(); |
+ CallbacksMap* map = new CallbacksMap; |
+ if (WorkerTaskRunner::Instance()->CurrentWorkerId()) |
+ WorkerTaskRunner::Instance()->AddStopObserver(map); |
+ return map; |
+ } |
+ |
+ virtual ~CallbacksMap() { |
+ IDMap<WebFileSystemCallbacks>::iterator iter(&callbacks_); |
+ while (!iter.IsAtEnd()) { |
+ iter.GetCurrentValue()->didFail(WebKit::WebFileErrorAbort); |
+ iter.Advance(); |
+ } |
+ g_callbacks_map_tls.Pointer()->Set(NULL); |
+ } |
+ |
+ // webkit_glue::WorkerTaskRunner::Observer implementation. |
+ virtual void OnWorkerRunLoopStopped() OVERRIDE { |
+ delete this; |
+ } |
+ |
+ int RegisterCallbacks(WebFileSystemCallbacks* callbacks) { |
+ return callbacks_.Add(callbacks); |
+ } |
+ |
+ WebFileSystemCallbacks* GetAndUnregisterCallbacks( |
+ int callbacks_id) { |
+ WebFileSystemCallbacks* callbacks = callbacks_.Lookup(callbacks_id); |
+ callbacks_.Remove(callbacks_id); |
+ return callbacks; |
+ } |
+ |
+ private: |
+ CallbacksMap() { |
+ g_callbacks_map_tls.Pointer()->Set(this); |
+ } |
+ |
+ IDMap<WebFileSystemCallbacks> callbacks_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(CallbacksMap); |
+}; |
+ |
void DidReadMetadataForCreateFileWriter( |
const GURL& path, |
WebKit::WebFileWriterClient* client, |
@@ -39,109 +107,265 @@ |
file_info.size); |
} |
+void DidReceiveSnapshotFile(int request_id) { |
+ if (ChildThread::current()) |
+ ChildThread::current()->Send( |
+ new FileSystemHostMsg_DidReceiveSnapshotFile(request_id)); |
+} |
+ |
+int CurrentWorkerId() { |
+ return WorkerTaskRunner::Instance()->CurrentWorkerId(); |
+} |
+ |
+template <typename Method, typename Params> |
+void CallDispatcherOnMainThread( |
+ base::MessageLoopProxy* loop, |
+ Method method, const Params& params) { |
+ if (!loop->RunsTasksOnCurrentThread()) { |
+ loop->PostTask(FROM_HERE, |
+ base::Bind(&CallDispatcherOnMainThread<Method, Params>, |
+ make_scoped_refptr(loop), method, params)); |
+ return; |
+ } |
+ if (!ChildThread::current() || |
+ !ChildThread::current()->file_system_dispatcher()) |
+ return; |
+ |
+ DispatchToMethod(ChildThread::current()->file_system_dispatcher(), |
+ method, 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; |
+ } |
+ if (!CallbacksMap::Get()) |
+ return; |
+ |
+ WebFileSystemCallbacks* callbacks = |
+ CallbacksMap::Get()->GetAndUnregisterCallbacks(callbacks_id); |
+ DCHECK(callbacks); |
+ DispatchToMethod(callbacks, method, params); |
+} |
+ |
+void StatusCallbackAdapter(int thread_id, int callbacks_id, |
+ base::PlatformFileError error) { |
+ if (error == base::PLATFORM_FILE_OK) { |
+ CallbackFileSystemCallbacks( |
+ thread_id, callbacks_id, |
+ &WebFileSystemCallbacks::didSucceed, MakeTuple()); |
+ } else { |
+ CallbackFileSystemCallbacks( |
+ thread_id, callbacks_id, |
+ &WebFileSystemCallbacks::didFail, |
+ MakeTuple(fileapi::PlatformFileErrorToWebFileError(error))); |
+ } |
+} |
+ |
+void ReadMetadataCallbackAdapter(int thread_id, int callbacks_id, |
+ const base::PlatformFileInfo& file_info) { |
+ WebFileInfo web_file_info; |
+ webkit_glue::PlatformFileInfoToWebFileInfo(file_info, &web_file_info); |
+ CallbackFileSystemCallbacks( |
+ thread_id, callbacks_id, |
+ &WebFileSystemCallbacks::didReadMetadata, |
+ MakeTuple(web_file_info)); |
+} |
+ |
+void ReadDirectoryCallbackAdapater( |
+ int thread_id, int callbacks_id, |
+ const std::vector<fileapi::DirectoryEntry>& entries, |
+ bool has_more) { |
+ WebVector<WebFileSystemEntry> file_system_entries(entries.size()); |
+ for (size_t i = 0; i < entries.size(); i++) { |
+ file_system_entries[i].name = |
+ base::FilePath(entries[i].name).AsUTF16Unsafe(); |
+ file_system_entries[i].isDirectory = entries[i].is_directory; |
+ } |
+ CallbackFileSystemCallbacks( |
+ thread_id, callbacks_id, |
+ &WebFileSystemCallbacks::didReadDirectory, |
+ MakeTuple(file_system_entries, has_more)); |
+} |
+ |
+void CreateSnapshotFileCallbackAdapter( |
+ int thread_id, 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; |
+ |
+ WebFileSystemCallbacks* callbacks = |
+ CallbacksMap::Get()->GetAndUnregisterCallbacks(callbacks_id); |
+ 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); |
+ |
+ // TODO(michaeln,kinuko): Use ThreadSafeSender when Blob becomes |
+ // non-bridge model. |
+ main_thread_loop->PostTask( |
+ FROM_HERE, base::Bind(&DidReceiveSnapshotFile, request_id)); |
+} |
+ |
} // namespace |
-WebFileSystemImpl::WebFileSystemImpl() { |
+WebFileSystemImpl::~WebFileSystemImpl() { |
} |
-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(base::MessageLoopProxy* main_thread_loop) |
+ : main_thread_loop_(main_thread_loop) { |
} |
-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)); |
+void WebFileSystemImpl::move( |
+ const WebKit::WebURL& src_path, |
+ const WebKit::WebURL& dest_path, |
+ WebKit::WebFileSystemCallbacks* callbacks) { |
+ int callbacks_id = CallbacksMap::GetOrCreate()->RegisterCallbacks(callbacks); |
+ CallDispatcherOnMainThread( |
+ main_thread_loop_.get(), |
+ &FileSystemDispatcher::Move, |
+ MakeTuple(GURL(src_path), GURL(dest_path), |
+ base::Bind(&StatusCallbackAdapter, |
+ CurrentWorkerId(), callbacks_id))); |
} |
-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) { |
+ int callbacks_id = CallbacksMap::GetOrCreate()->RegisterCallbacks(callbacks); |
+ CallDispatcherOnMainThread( |
+ main_thread_loop_.get(), |
+ &FileSystemDispatcher::Copy, |
+ MakeTuple(GURL(src_path), GURL(dest_path), |
+ base::Bind(&StatusCallbackAdapter, |
+ CurrentWorkerId(), callbacks_id))); |
} |
-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) { |
+ int callbacks_id = CallbacksMap::GetOrCreate()->RegisterCallbacks(callbacks); |
+ CallDispatcherOnMainThread( |
+ main_thread_loop_.get(), |
+ &FileSystemDispatcher::Remove, |
+ MakeTuple(GURL(path), false /* recursive */, |
+ base::Bind(&StatusCallbackAdapter, |
+ CurrentWorkerId(), callbacks_id))); |
} |
-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) { |
+ int callbacks_id = CallbacksMap::GetOrCreate()->RegisterCallbacks(callbacks); |
+ CallDispatcherOnMainThread( |
+ main_thread_loop_.get(), |
+ &FileSystemDispatcher::Remove, |
+ MakeTuple(GURL(path), true /* recursive */, |
+ base::Bind(&StatusCallbackAdapter, |
+ CurrentWorkerId(), callbacks_id))); |
} |
-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) { |
+ int callbacks_id = CallbacksMap::GetOrCreate()->RegisterCallbacks(callbacks); |
+ CallDispatcherOnMainThread( |
+ main_thread_loop_.get(), |
+ &FileSystemDispatcher::ReadMetadata, |
+ MakeTuple(GURL(path), |
+ base::Bind(&ReadMetadataCallbackAdapter, |
+ CurrentWorkerId(), callbacks_id), |
+ base::Bind(&StatusCallbackAdapter, |
+ CurrentWorkerId(), callbacks_id))); |
} |
-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) { |
+ int callbacks_id = CallbacksMap::GetOrCreate()->RegisterCallbacks(callbacks); |
+ CallDispatcherOnMainThread( |
+ main_thread_loop_.get(), |
+ &FileSystemDispatcher::CreateFile, |
+ MakeTuple(GURL(path), exclusive, |
+ base::Bind(&StatusCallbackAdapter, |
+ CurrentWorkerId(), callbacks_id))); |
} |
-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) { |
+ int callbacks_id = CallbacksMap::GetOrCreate()->RegisterCallbacks(callbacks); |
+ CallDispatcherOnMainThread( |
+ main_thread_loop_.get(), |
+ &FileSystemDispatcher::CreateDirectory, |
+ MakeTuple(GURL(path), exclusive, false /* recursive */, |
+ base::Bind(&StatusCallbackAdapter, |
+ CurrentWorkerId(), callbacks_id))); |
} |
-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) { |
+ int callbacks_id = CallbacksMap::GetOrCreate()->RegisterCallbacks(callbacks); |
+ CallDispatcherOnMainThread( |
+ main_thread_loop_.get(), |
+ &FileSystemDispatcher::Exists, |
+ MakeTuple(GURL(path), false /* directory */, |
+ base::Bind(&StatusCallbackAdapter, |
+ CurrentWorkerId(), callbacks_id))); |
} |
-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) { |
+ int callbacks_id = CallbacksMap::GetOrCreate()->RegisterCallbacks(callbacks); |
+ CallDispatcherOnMainThread( |
+ main_thread_loop_.get(), |
+ &FileSystemDispatcher::Exists, |
+ MakeTuple(GURL(path), true /* directory */, |
+ base::Bind(&StatusCallbackAdapter, |
+ CurrentWorkerId(), callbacks_id))); |
} |
+void WebFileSystemImpl::readDirectory( |
+ const WebKit::WebURL& path, |
+ WebKit::WebFileSystemCallbacks* callbacks) { |
+ int callbacks_id = CallbacksMap::GetOrCreate()->RegisterCallbacks(callbacks); |
+ CallDispatcherOnMainThread( |
+ main_thread_loop_.get(), |
+ &FileSystemDispatcher::ReadDirectory, |
+ MakeTuple(GURL(path), |
+ base::Bind(&ReadDirectoryCallbackAdapater, |
+ CurrentWorkerId(), callbacks_id), |
+ base::Bind(&StatusCallbackAdapter, |
+ CurrentWorkerId(), callbacks_id))); |
+} |
+ |
WebKit::WebFileWriter* WebFileSystemImpl::createFileWriter( |
const WebURL& path, WebKit::WebFileWriterClient* client) { |
return new WebFileWriterImpl(GURL(path), client); |
@@ -151,6 +375,8 @@ |
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 +389,16 @@ |
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)); |
+ int callbacks_id = CallbacksMap::GetOrCreate()->RegisterCallbacks(callbacks); |
+ CallDispatcherOnMainThread( |
+ main_thread_loop_.get(), |
+ &FileSystemDispatcher::CreateSnapshotFile, |
+ MakeTuple(GURL(path), |
+ base::Bind(&CreateSnapshotFileCallbackAdapter, |
+ CurrentWorkerId(), callbacks_id, |
+ main_thread_loop_), |
+ base::Bind(&StatusCallbackAdapter, |
+ CurrentWorkerId(), callbacks_id))); |
} |
} // namespace content |
Property changes on: trunk/src/content/child/fileapi/webfilesystem_impl.cc |
___________________________________________________________________ |
Deleted: svn:mergeinfo |