summaryrefslogtreecommitdiffstats
path: root/WebKit/chromium/src/WorkerFileSystemCallbacksBridge.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'WebKit/chromium/src/WorkerFileSystemCallbacksBridge.cpp')
-rw-r--r--WebKit/chromium/src/WorkerFileSystemCallbacksBridge.cpp392
1 files changed, 392 insertions, 0 deletions
diff --git a/WebKit/chromium/src/WorkerFileSystemCallbacksBridge.cpp b/WebKit/chromium/src/WorkerFileSystemCallbacksBridge.cpp
new file mode 100644
index 0000000..6c31221
--- /dev/null
+++ b/WebKit/chromium/src/WorkerFileSystemCallbacksBridge.cpp
@@ -0,0 +1,392 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "WorkerFileSystemCallbacksBridge.h"
+
+#if ENABLE(FILE_SYSTEM)
+
+#include "CrossThreadTask.h"
+#include "WebCommonWorkerClient.h"
+#include "WebFileInfo.h"
+#include "WebFileSystemCallbacks.h"
+#include "WebFileSystemEntry.h"
+#include "WebString.h"
+#include "WebWorkerBase.h"
+#include "WorkerContext.h"
+#include "WorkerScriptController.h"
+#include "WorkerThread.h"
+#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 {
+
+// FileSystemCallbacks that are to be dispatched on the main thread.
+class MainThreadFileSystemCallbacks : public WebFileSystemCallbacks {
+public:
+ // Callbacks are self-destructed and we always return leaked pointer here.
+ static MainThreadFileSystemCallbacks* createLeakedPtr(PassRefPtr<WorkerFileSystemCallbacksBridge> bridge, const String& mode)
+ {
+ OwnPtr<MainThreadFileSystemCallbacks> callbacks = adoptPtr(new MainThreadFileSystemCallbacks(bridge, mode));
+ return callbacks.leakPtr();
+ }
+
+ virtual ~MainThreadFileSystemCallbacks()
+ {
+ }
+
+ virtual void didOpenFileSystem(const WebString& name, const WebString& path)
+ {
+ m_bridge->didOpenFileSystemOnMainThread(name, path, m_mode);
+ delete this;
+ }
+
+ virtual void didFail(WebFileError error)
+ {
+ m_bridge->didFailOnMainThread(error, m_mode);
+ delete this;
+ }
+
+ virtual void didSucceed()
+ {
+ m_bridge->didSucceedOnMainThread(m_mode);
+ delete this;
+ }
+
+ virtual void didReadMetadata(const WebFileInfo& info)
+ {
+ m_bridge->didReadMetadataOnMainThread(info, m_mode);
+ delete this;
+ }
+
+ virtual void didReadDirectory(const WebVector<WebFileSystemEntry>& entries, bool hasMore)
+ {
+ m_bridge->didReadDirectoryOnMainThread(entries, hasMore, m_mode);
+ delete this;
+ }
+
+private:
+ MainThreadFileSystemCallbacks(PassRefPtr<WorkerFileSystemCallbacksBridge> bridge, const String& mode)
+ : m_bridge(bridge)
+ , m_mode(mode)
+ {
+ ASSERT(m_bridge.get());
+ }
+
+ friend class WorkerFileSystemCallbacksBridge;
+ RefPtr<WorkerFileSystemCallbacksBridge> m_bridge;
+ const String m_mode;
+};
+
+void WorkerFileSystemCallbacksBridge::stop()
+{
+ ASSERT(m_workerContext->isContextThread());
+ MutexLocker locker(m_mutex);
+ m_worker = 0;
+
+ if (m_callbacksOnWorkerThread) {
+ m_callbacksOnWorkerThread->didFail(WebFileErrorAbort);
+ m_callbacksOnWorkerThread = 0;
+ }
+}
+
+void WorkerFileSystemCallbacksBridge::postOpenFileSystemToMainThread(WebCommonWorkerClient* commonClient, WebFileSystem::Type type, long long size, const String& 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(&copyOnMainThread, 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)
+{
+ if (!commonClient)
+ bridge->didFailOnMainThread(WebFileErrorAbort, mode);
+ else {
+ 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)
+{
+ mayPostTaskToWorker(createCallbackTask(&didFailOnWorkerThread, this, error), mode);
+}
+
+void WorkerFileSystemCallbacksBridge::didOpenFileSystemOnMainThread(const String& name, const String& rootPath, const String& 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)
+ : WorkerContext::Observer(static_cast<WorkerContext*>(scriptExecutionContext))
+ , m_worker(worker)
+ , m_workerContext(scriptExecutionContext)
+ , m_callbacksOnWorkerThread(callbacks)
+{
+ ASSERT(m_workerContext->isContextThread());
+}
+
+WorkerFileSystemCallbacksBridge::~WorkerFileSystemCallbacksBridge()
+{
+ ASSERT(!m_callbacksOnWorkerThread);
+}
+
+void WorkerFileSystemCallbacksBridge::didFailOnWorkerThread(ScriptExecutionContext*, WorkerFileSystemCallbacksBridge* bridge, WebFileError error)
+{
+ bridge->m_callbacksOnWorkerThread->didFail(error);
+}
+
+void WorkerFileSystemCallbacksBridge::didOpenFileSystemOnWorkerThread(ScriptExecutionContext*, WorkerFileSystemCallbacksBridge* bridge, const String& name, const String& rootPath)
+{
+ 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(createCallbackTask(&runTaskOnWorkerThread, m_selfRef, task), mode);
+ }
+ m_selfRef.clear();
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(FILE_SYSTEM)