diff options
author | Ben Murdoch <benm@google.com> | 2010-10-22 13:02:20 +0100 |
---|---|---|
committer | Ben Murdoch <benm@google.com> | 2010-10-26 15:21:41 +0100 |
commit | a94275402997c11dd2e778633dacf4b7e630a35d (patch) | |
tree | e66f56c67e3b01f22c9c23cd932271ee9ac558ed /WebKit/chromium/src/WorkerFileSystemCallbacksBridge.cpp | |
parent | 09e26c78506587b3f5d930d7bc72a23287ffbec0 (diff) | |
download | external_webkit-a94275402997c11dd2e778633dacf4b7e630a35d.zip external_webkit-a94275402997c11dd2e778633dacf4b7e630a35d.tar.gz external_webkit-a94275402997c11dd2e778633dacf4b7e630a35d.tar.bz2 |
Merge WebKit at r70209: Initial merge by Git
Change-Id: Id23a68efa36e9d1126bcce0b137872db00892c8e
Diffstat (limited to 'WebKit/chromium/src/WorkerFileSystemCallbacksBridge.cpp')
-rw-r--r-- | WebKit/chromium/src/WorkerFileSystemCallbacksBridge.cpp | 258 |
1 files changed, 230 insertions, 28 deletions
diff --git a/WebKit/chromium/src/WorkerFileSystemCallbacksBridge.cpp b/WebKit/chromium/src/WorkerFileSystemCallbacksBridge.cpp index d112886..6c31221 100644 --- a/WebKit/chromium/src/WorkerFileSystemCallbacksBridge.cpp +++ b/WebKit/chromium/src/WorkerFileSystemCallbacksBridge.cpp @@ -35,7 +35,9 @@ #include "CrossThreadTask.h" #include "WebCommonWorkerClient.h" +#include "WebFileInfo.h" #include "WebFileSystemCallbacks.h" +#include "WebFileSystemEntry.h" #include "WebString.h" #include "WebWorkerBase.h" #include "WorkerContext.h" @@ -44,6 +46,37 @@ #include <wtf/MainThread.h> #include <wtf/Threading.h> +namespace WebCore { + +template<> struct CrossThreadCopierBase<false, false, WebKit::WebFileInfo> { + typedef WebKit::WebFileInfo Type; + static Type copy(const WebKit::WebFileInfo& info) + { + // Perform per-field copy to make sure we don't do any (unexpected) non-thread safe copy here. + struct WebKit::WebFileInfo newInfo; + newInfo.modificationTime = info.modificationTime; + newInfo.length = info.length; + newInfo.type = info.type; + return newInfo; + } +}; + +template<> struct CrossThreadCopierBase<false, false, WebKit::WebVector<WebKit::WebFileSystemEntry> > { + typedef WebKit::WebVector<WebKit::WebFileSystemEntry> Type; + static Type copy(const WebKit::WebVector<WebKit::WebFileSystemEntry>& entries) + { + WebKit::WebVector<WebKit::WebFileSystemEntry> newEntries(entries.size()); + for (size_t i = 0; i < entries.size(); ++i) { + String name = entries[i].name; + newEntries[i].isDirectory = entries[i].isDirectory; + newEntries[i].name = name.crossThreadString(); + } + return newEntries; + } +}; + +} + using namespace WebCore; namespace WebKit { @@ -51,9 +84,11 @@ namespace WebKit { // FileSystemCallbacks that are to be dispatched on the main thread. class MainThreadFileSystemCallbacks : public WebFileSystemCallbacks { public: - static PassOwnPtr<MainThreadFileSystemCallbacks> create(PassRefPtr<WorkerFileSystemCallbacksBridge> bridge, const String& mode) + // Callbacks are self-destructed and we always return leaked pointer here. + static MainThreadFileSystemCallbacks* createLeakedPtr(PassRefPtr<WorkerFileSystemCallbacksBridge> bridge, const String& mode) { - return adoptPtr(new MainThreadFileSystemCallbacks(bridge, mode)); + OwnPtr<MainThreadFileSystemCallbacks> callbacks = adoptPtr(new MainThreadFileSystemCallbacks(bridge, mode)); + return callbacks.leakPtr(); } virtual ~MainThreadFileSystemCallbacks() @@ -74,17 +109,20 @@ public: virtual void didSucceed() { - WEBKIT_ASSERT_NOT_REACHED(); + m_bridge->didSucceedOnMainThread(m_mode); + delete this; } virtual void didReadMetadata(const WebFileInfo& info) { - WEBKIT_ASSERT_NOT_REACHED(); + m_bridge->didReadMetadataOnMainThread(info, m_mode); + delete this; } virtual void didReadDirectory(const WebVector<WebFileSystemEntry>& entries, bool hasMore) { - WEBKIT_ASSERT_NOT_REACHED(); + m_bridge->didReadDirectoryOnMainThread(entries, hasMore, m_mode); + delete this; } private: @@ -114,33 +152,148 @@ void WorkerFileSystemCallbacksBridge::stop() void WorkerFileSystemCallbacksBridge::postOpenFileSystemToMainThread(WebCommonWorkerClient* commonClient, WebFileSystem::Type type, long long size, const String& mode) { - m_selfRef = this; - ASSERT(m_workerContext->isContextThread()); - ASSERT(m_worker); - m_worker->dispatchTaskToMainThread(createCallbackTask(&openFileSystemOnMainThread, commonClient, type, size, this, mode)); + dispatchTaskToMainThread(createCallbackTask(&openFileSystemOnMainThread, commonClient, type, size, this, mode)); +} + +void WorkerFileSystemCallbacksBridge::postMoveToMainThread(WebFileSystem* fileSystem, const String& sourcePath, const String& destinationPath, const String& mode) +{ + dispatchTaskToMainThread(createCallbackTask(&moveOnMainThread, fileSystem, sourcePath, destinationPath, this, mode)); +} + +void WorkerFileSystemCallbacksBridge::postCopyToMainThread(WebFileSystem* fileSystem, const String& sourcePath, const String& destinationPath, const String& mode) +{ + dispatchTaskToMainThread(createCallbackTask(©OnMainThread, fileSystem, sourcePath, destinationPath, this, mode)); +} + +void WorkerFileSystemCallbacksBridge::postRemoveToMainThread(WebFileSystem* fileSystem, const String& path, const String& mode) +{ + ASSERT(fileSystem); + dispatchTaskToMainThread(createCallbackTask(&removeOnMainThread, fileSystem, path, this, mode)); +} + +void WorkerFileSystemCallbacksBridge::postRemoveRecursivelyToMainThread(WebFileSystem* fileSystem, const String& path, const String& mode) +{ + ASSERT(fileSystem); + dispatchTaskToMainThread(createCallbackTask(&removeRecursivelyOnMainThread, fileSystem, path, this, mode)); +} + +void WorkerFileSystemCallbacksBridge::postReadMetadataToMainThread(WebFileSystem* fileSystem, const String& path, const String& mode) +{ + ASSERT(fileSystem); + dispatchTaskToMainThread(createCallbackTask(&readMetadataOnMainThread, fileSystem, path, this, mode)); +} + +void WorkerFileSystemCallbacksBridge::postCreateFileToMainThread(WebFileSystem* fileSystem, const String& path, bool exclusive, const String& mode) +{ + dispatchTaskToMainThread(createCallbackTask(&createFileOnMainThread, fileSystem, path, exclusive, this, mode)); +} + +void WorkerFileSystemCallbacksBridge::postCreateDirectoryToMainThread(WebFileSystem* fileSystem, const String& path, bool exclusive, const String& mode) +{ + ASSERT(fileSystem); + dispatchTaskToMainThread(createCallbackTask(&createDirectoryOnMainThread, fileSystem, path, exclusive, this, mode)); +} + +void WorkerFileSystemCallbacksBridge::postFileExistsToMainThread(WebFileSystem* fileSystem, const String& path, const String& mode) +{ + ASSERT(fileSystem); + dispatchTaskToMainThread(createCallbackTask(&fileExistsOnMainThread, fileSystem, path, this, mode)); +} + +void WorkerFileSystemCallbacksBridge::postDirectoryExistsToMainThread(WebFileSystem* fileSystem, const String& path, const String& mode) +{ + ASSERT(fileSystem); + dispatchTaskToMainThread(createCallbackTask(&directoryExistsOnMainThread, fileSystem, path, this, mode)); +} + +void WorkerFileSystemCallbacksBridge::postReadDirectoryToMainThread(WebFileSystem* fileSystem, const String& path, const String& mode) +{ + ASSERT(fileSystem); + dispatchTaskToMainThread(createCallbackTask(&readDirectoryOnMainThread, fileSystem, path, this, mode)); } void WorkerFileSystemCallbacksBridge::openFileSystemOnMainThread(ScriptExecutionContext*, WebCommonWorkerClient* commonClient, WebFileSystem::Type type, long long size, WorkerFileSystemCallbacksBridge* bridge, const String& mode) { - ASSERT(isMainThread()); if (!commonClient) bridge->didFailOnMainThread(WebFileErrorAbort, mode); else { - // MainThreadFileSystemCallbacks is self-destructed, so we leak ptr here. - commonClient->openFileSystem(type, size, MainThreadFileSystemCallbacks::create(bridge, mode).leakPtr()); + commonClient->openFileSystem(type, size, MainThreadFileSystemCallbacks::createLeakedPtr(bridge, mode)); } } +void WorkerFileSystemCallbacksBridge::moveOnMainThread(WebCore::ScriptExecutionContext*, WebFileSystem* fileSystem, const String& sourcePath, const String& destinationPath, WorkerFileSystemCallbacksBridge* bridge, const String& mode) +{ + fileSystem->move(sourcePath, destinationPath, MainThreadFileSystemCallbacks::createLeakedPtr(bridge, mode)); +} + +void WorkerFileSystemCallbacksBridge::copyOnMainThread(WebCore::ScriptExecutionContext*, WebFileSystem* fileSystem, const String& sourcePath, const String& destinationPath, WorkerFileSystemCallbacksBridge* bridge, const String& mode) +{ + fileSystem->copy(sourcePath, destinationPath, MainThreadFileSystemCallbacks::createLeakedPtr(bridge, mode)); +} + +void WorkerFileSystemCallbacksBridge::removeOnMainThread(WebCore::ScriptExecutionContext*, WebFileSystem* fileSystem, const String& path, WorkerFileSystemCallbacksBridge* bridge, const String& mode) +{ + fileSystem->remove(path, MainThreadFileSystemCallbacks::createLeakedPtr(bridge, mode)); +} + +void WorkerFileSystemCallbacksBridge::removeRecursivelyOnMainThread(WebCore::ScriptExecutionContext*, WebFileSystem* fileSystem, const String& path, WorkerFileSystemCallbacksBridge* bridge, const String& mode) +{ + fileSystem->removeRecursively(path, MainThreadFileSystemCallbacks::createLeakedPtr(bridge, mode)); +} + +void WorkerFileSystemCallbacksBridge::readMetadataOnMainThread(WebCore::ScriptExecutionContext*, WebFileSystem* fileSystem, const String& path, WorkerFileSystemCallbacksBridge* bridge, const String& mode) +{ + fileSystem->readMetadata(path, MainThreadFileSystemCallbacks::createLeakedPtr(bridge, mode)); +} + +void WorkerFileSystemCallbacksBridge::createFileOnMainThread(WebCore::ScriptExecutionContext*, WebFileSystem* fileSystem, const String& path, bool exclusive, WorkerFileSystemCallbacksBridge* bridge, const String& mode) +{ + fileSystem->createFile(path, exclusive, MainThreadFileSystemCallbacks::createLeakedPtr(bridge, mode)); +} + +void WorkerFileSystemCallbacksBridge::createDirectoryOnMainThread(WebCore::ScriptExecutionContext*, WebFileSystem* fileSystem, const String& path, bool exclusive, WorkerFileSystemCallbacksBridge* bridge, const String& mode) +{ + fileSystem->createDirectory(path, exclusive, MainThreadFileSystemCallbacks::createLeakedPtr(bridge, mode)); +} + +void WorkerFileSystemCallbacksBridge::fileExistsOnMainThread(WebCore::ScriptExecutionContext*, WebFileSystem* fileSystem, const String& path, WorkerFileSystemCallbacksBridge* bridge, const String& mode) +{ + fileSystem->fileExists(path, MainThreadFileSystemCallbacks::createLeakedPtr(bridge, mode)); +} + +void WorkerFileSystemCallbacksBridge::directoryExistsOnMainThread(WebCore::ScriptExecutionContext*, WebFileSystem* fileSystem, const String& path, WorkerFileSystemCallbacksBridge* bridge, const String& mode) +{ + fileSystem->directoryExists(path, MainThreadFileSystemCallbacks::createLeakedPtr(bridge, mode)); +} + +void WorkerFileSystemCallbacksBridge::readDirectoryOnMainThread(WebCore::ScriptExecutionContext*, WebFileSystem* fileSystem, const String& path, WorkerFileSystemCallbacksBridge* bridge, const String& mode) +{ + fileSystem->readDirectory(path, MainThreadFileSystemCallbacks::createLeakedPtr(bridge, mode)); +} + void WorkerFileSystemCallbacksBridge::didFailOnMainThread(WebFileError error, const String& mode) { - ASSERT(isMainThread()); - mayPostTaskToWorker(createCallbackTask(&didFailOnWorkerThread, m_selfRef, error), mode); + mayPostTaskToWorker(createCallbackTask(&didFailOnWorkerThread, this, error), mode); } void WorkerFileSystemCallbacksBridge::didOpenFileSystemOnMainThread(const String& name, const String& rootPath, const String& mode) { - ASSERT(isMainThread()); - mayPostTaskToWorker(createCallbackTask(&didOpenFileSystemOnWorkerThread, m_selfRef, name, rootPath), mode); + mayPostTaskToWorker(createCallbackTask(&didOpenFileSystemOnWorkerThread, this, name, rootPath), mode); +} + +void WorkerFileSystemCallbacksBridge::didSucceedOnMainThread(const String& mode) +{ + mayPostTaskToWorker(createCallbackTask(&didSucceedOnWorkerThread, this), mode); +} + +void WorkerFileSystemCallbacksBridge::didReadMetadataOnMainThread(const WebFileInfo& info, const String& mode) +{ + mayPostTaskToWorker(createCallbackTask(&didReadMetadataOnWorkerThread, this, info), mode); +} + +void WorkerFileSystemCallbacksBridge::didReadDirectoryOnMainThread(const WebVector<WebFileSystemEntry>& entries, bool hasMore, const String& mode) +{ + mayPostTaskToWorker(createCallbackTask(&didReadDirectoryOnWorkerThread, this, entries, hasMore), mode); } WorkerFileSystemCallbacksBridge::WorkerFileSystemCallbacksBridge(WebWorkerBase* worker, ScriptExecutionContext* scriptExecutionContext, WebFileSystemCallbacks* callbacks) @@ -157,30 +310,79 @@ WorkerFileSystemCallbacksBridge::~WorkerFileSystemCallbacksBridge() ASSERT(!m_callbacksOnWorkerThread); } -void WorkerFileSystemCallbacksBridge::didFailOnWorkerThread(ScriptExecutionContext*, PassRefPtr<WorkerFileSystemCallbacksBridge> bridge, WebFileError error) +void WorkerFileSystemCallbacksBridge::didFailOnWorkerThread(ScriptExecutionContext*, WorkerFileSystemCallbacksBridge* bridge, WebFileError error) { - if (bridge->m_callbacksOnWorkerThread) { - ASSERT(bridge->m_workerContext->isContextThread()); - bridge->m_callbacksOnWorkerThread->didFail(error); - bridge->m_callbacksOnWorkerThread = 0; - } + bridge->m_callbacksOnWorkerThread->didFail(error); } -void WorkerFileSystemCallbacksBridge::didOpenFileSystemOnWorkerThread(ScriptExecutionContext*, PassRefPtr<WorkerFileSystemCallbacksBridge> bridge, const String& name, const String& rootPath) +void WorkerFileSystemCallbacksBridge::didOpenFileSystemOnWorkerThread(ScriptExecutionContext*, WorkerFileSystemCallbacksBridge* bridge, const String& name, const String& rootPath) { - if (bridge->m_callbacksOnWorkerThread) { - ASSERT(bridge->m_workerContext->isContextThread()); - bridge->m_callbacksOnWorkerThread->didOpenFileSystem(name, rootPath); - bridge->m_callbacksOnWorkerThread = 0; + bridge->m_callbacksOnWorkerThread->didOpenFileSystem(name, rootPath); +} + +void WorkerFileSystemCallbacksBridge::didSucceedOnWorkerThread(ScriptExecutionContext*, WorkerFileSystemCallbacksBridge* bridge) +{ + bridge->m_callbacksOnWorkerThread->didSucceed(); +} + +void WorkerFileSystemCallbacksBridge::didReadMetadataOnWorkerThread(ScriptExecutionContext*, WorkerFileSystemCallbacksBridge* bridge, const WebFileInfo& info) +{ + bridge->m_callbacksOnWorkerThread->didReadMetadata(info); +} + +void WorkerFileSystemCallbacksBridge::didReadDirectoryOnWorkerThread(ScriptExecutionContext*, WorkerFileSystemCallbacksBridge* bridge, const WebVector<WebFileSystemEntry>& entries, bool hasMore) +{ + bridge->m_callbacksOnWorkerThread->didReadDirectory(entries, hasMore); +} + +bool WorkerFileSystemCallbacksBridge::derefIfWorkerIsStopped() +{ + WebWorkerBase* worker = 0; + { + MutexLocker locker(m_mutex); + worker = m_worker; + } + + if (!worker) { + m_selfRef.clear(); + return true; } + return false; +} + +void WorkerFileSystemCallbacksBridge::runTaskOnMainThread(WebCore::ScriptExecutionContext* scriptExecutionContext, WorkerFileSystemCallbacksBridge* bridge, PassOwnPtr<WebCore::ScriptExecutionContext::Task> taskToRun) +{ + ASSERT(isMainThread()); + if (bridge->derefIfWorkerIsStopped()) + return; + taskToRun->performTask(scriptExecutionContext); +} + +void WorkerFileSystemCallbacksBridge::runTaskOnWorkerThread(WebCore::ScriptExecutionContext* scriptExecutionContext, PassRefPtr<WorkerFileSystemCallbacksBridge> bridge, PassOwnPtr<WebCore::ScriptExecutionContext::Task> taskToRun) +{ + if (!bridge->m_callbacksOnWorkerThread) + return; + ASSERT(bridge->m_workerContext->isContextThread()); + taskToRun->performTask(scriptExecutionContext); + bridge->m_callbacksOnWorkerThread = 0; +} + +void WorkerFileSystemCallbacksBridge::dispatchTaskToMainThread(PassOwnPtr<WebCore::ScriptExecutionContext::Task> task) +{ + ASSERT(!m_selfRef); + ASSERT(m_worker); + ASSERT(m_workerContext->isContextThread()); + m_selfRef = this; + m_worker->dispatchTaskToMainThread(createCallbackTask(&runTaskOnMainThread, this, task)); } void WorkerFileSystemCallbacksBridge::mayPostTaskToWorker(PassOwnPtr<ScriptExecutionContext::Task> task, const String& mode) { + ASSERT(isMainThread()); { // Let go of the mutex before possibly deleting this due to m_selfRef.clear(). MutexLocker locker(m_mutex); if (m_worker) - m_worker->postTaskForModeToWorkerContext(task, mode); + m_worker->postTaskForModeToWorkerContext(createCallbackTask(&runTaskOnWorkerThread, m_selfRef, task), mode); } m_selfRef.clear(); } |