/*
 * Copyright (C) 2010, 2012 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) && ENABLE(WORKERS)

#include "CrossThreadTask.h"
#include "KURL.h"
#include "WebCommonWorkerClient.h"
#include "WebFileInfo.h"
#include "WebFileSystemCallbacks.h"
#include "WebFileSystemEntry.h"
#include "platform/WebString.h"
#include "platform/WebURL.h"
#include "WebWorkerBase.h"
#include "WorkerContext.h"
#include "WorkerLoaderProxy.h"
#include "WorkerScriptController.h"
#include "WorkerThread.h"
#include <wtf/MainThread.h>
#include <wtf/Threading.h>
#include <wtf/UnusedParam.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;
        newInfo.platformPath.assign(info.platformPath.data(), info.platformPath.length());
        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.isolatedCopy();
        }
        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 WebURL& rootURL)
    {
        m_bridge->didOpenFileSystemOnMainThread(name, rootURL, 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);
    }

    RefPtr<WorkerFileSystemCallbacksBridge> m_bridge;
    const String m_mode;
};

// Observes the worker context. By keeping this separate, it is easier to verify
// that it only gets deleted on the worker context thread which is verified by ~Observer.
class WorkerFileSystemContextObserver : public WebCore::WorkerContext::Observer {
public:
    static PassOwnPtr<WorkerFileSystemContextObserver> create(WorkerContext* context, PassRefPtr<WorkerFileSystemCallbacksBridge> bridge)
    {
        return adoptPtr(new WorkerFileSystemContextObserver(context, bridge));
    }

    // WorkerContext::Observer method.
    virtual void notifyStop()
    {
        m_bridge->stop();
    }

private:
    WorkerFileSystemContextObserver(WorkerContext* context, PassRefPtr<WorkerFileSystemCallbacksBridge> bridge)
        : WebCore::WorkerContext::Observer(context)
        , m_bridge(bridge)
    {
    }

    RefPtr<WorkerFileSystemCallbacksBridge> m_bridge;
};

void WorkerFileSystemCallbacksBridge::stop()
{
    ASSERT(m_workerContext->isContextThread());
    {
        MutexLocker locker(m_loaderProxyMutex);
        m_workerLoaderProxy = 0;
    }

    if (m_callbacksOnWorkerThread)
        m_callbacksOnWorkerThread->didFail(WebFileErrorAbort);

    cleanUpAfterCallback();
}

void WorkerFileSystemCallbacksBridge::cleanUpAfterCallback()
{
    ASSERT(m_workerContext->isContextThread());

    m_callbacksOnWorkerThread = 0;
    if (m_workerContextObserver) {
        WorkerFileSystemContextObserver* observer = m_workerContextObserver;
        m_workerContextObserver = 0;
        // The next line may delete this.
        delete observer;
    }
}

void WorkerFileSystemCallbacksBridge::postOpenFileSystemToMainThread(WebCommonWorkerClient* commonClient, WebFileSystem::Type type, long long size, bool create, const String& mode)
{
    dispatchTaskToMainThread(
        createCallbackTask(&openFileSystemOnMainThread,
                           AllowCrossThreadAccess(commonClient), type, size, create,
                           this, mode));
}

void WorkerFileSystemCallbacksBridge::postMoveToMainThread(WebFileSystem* fileSystem, const KURL& sourcePath, const KURL& destinationPath, const String& mode)
{
    dispatchTaskToMainThread(
        createCallbackTask(&moveOnMainThread,
                           AllowCrossThreadAccess(fileSystem), sourcePath, destinationPath,
                           this, mode));
}

void WorkerFileSystemCallbacksBridge::postCopyToMainThread(WebFileSystem* fileSystem, const KURL& sourcePath, const KURL& destinationPath, const String& mode)
{
    dispatchTaskToMainThread(
        createCallbackTask(&copyOnMainThread,
                           AllowCrossThreadAccess(fileSystem), sourcePath, destinationPath,
                           this, mode));
}

void WorkerFileSystemCallbacksBridge::postRemoveToMainThread(WebFileSystem* fileSystem, const KURL& path, const String& mode)
{
    ASSERT(fileSystem);
    dispatchTaskToMainThread(
        createCallbackTask(&removeOnMainThread,
                           AllowCrossThreadAccess(fileSystem), path,
                           this, mode));
}

void WorkerFileSystemCallbacksBridge::postRemoveRecursivelyToMainThread(WebFileSystem* fileSystem, const KURL& path, const String& mode)
{
    ASSERT(fileSystem);
    dispatchTaskToMainThread(
        createCallbackTask(&removeRecursivelyOnMainThread,
                           AllowCrossThreadAccess(fileSystem), path,
                           this, mode));
}

void WorkerFileSystemCallbacksBridge::postReadMetadataToMainThread(WebFileSystem* fileSystem, const KURL& path, const String& mode)
{
    ASSERT(fileSystem);
    dispatchTaskToMainThread(
        createCallbackTask(&readMetadataOnMainThread,
                           AllowCrossThreadAccess(fileSystem), path,
                           this, mode));
}

void WorkerFileSystemCallbacksBridge::postCreateFileToMainThread(WebFileSystem* fileSystem, const KURL& path, bool exclusive, const String& mode)
{
    dispatchTaskToMainThread(
        createCallbackTask(&createFileOnMainThread,
                           AllowCrossThreadAccess(fileSystem), path, exclusive,
                           this, mode));
}

void WorkerFileSystemCallbacksBridge::postCreateDirectoryToMainThread(WebFileSystem* fileSystem, const KURL& path, bool exclusive, const String& mode)
{
    ASSERT(fileSystem);
    dispatchTaskToMainThread(
        createCallbackTask(&createDirectoryOnMainThread,
                           AllowCrossThreadAccess(fileSystem), path, exclusive,
                           this, mode));
}

void WorkerFileSystemCallbacksBridge::postFileExistsToMainThread(WebFileSystem* fileSystem, const KURL& path, const String& mode)
{
    ASSERT(fileSystem);
    dispatchTaskToMainThread(
        createCallbackTask(&fileExistsOnMainThread,
                           AllowCrossThreadAccess(fileSystem), path,
                           this, mode));
}

void WorkerFileSystemCallbacksBridge::postDirectoryExistsToMainThread(WebFileSystem* fileSystem, const KURL& path, const String& mode)
{
    ASSERT(fileSystem);
    dispatchTaskToMainThread(
        createCallbackTask(&directoryExistsOnMainThread,
                           AllowCrossThreadAccess(fileSystem), path,
                           this, mode));
}

void WorkerFileSystemCallbacksBridge::postReadDirectoryToMainThread(WebFileSystem* fileSystem, const KURL& path, const String& mode)
{
    ASSERT(fileSystem);
    dispatchTaskToMainThread(
        createCallbackTask(&readDirectoryOnMainThread,
                           AllowCrossThreadAccess(fileSystem), path,
                           this, mode));
}

void WorkerFileSystemCallbacksBridge::postCreateSnapshotFileToMainThread(WebFileSystem* fileSystem, const KURL& internalBlobURL, const KURL& path, const String& mode)
{
    ASSERT(fileSystem);
    dispatchTaskToMainThread(
        createCallbackTask(&createSnapshotFileOnMainThread,
                           AllowCrossThreadAccess(fileSystem),
                           internalBlobURL, path, this, mode));
}

void WorkerFileSystemCallbacksBridge::openFileSystemOnMainThread(ScriptExecutionContext*, WebCommonWorkerClient* commonClient, WebFileSystem::Type type, long long size, bool create, PassRefPtr<WorkerFileSystemCallbacksBridge> bridge, const String& mode)
{
    if (!commonClient)
        bridge->didFailOnMainThread(WebFileErrorAbort, mode);
    else {
        commonClient->openFileSystem(type, size, create, MainThreadFileSystemCallbacks::createLeakedPtr(bridge, mode));
    }
}

void WorkerFileSystemCallbacksBridge::moveOnMainThread(WebCore::ScriptExecutionContext*, WebFileSystem* fileSystem, const KURL& sourcePath, const KURL& destinationPath, PassRefPtr<WorkerFileSystemCallbacksBridge> bridge, const String& mode)
{
    fileSystem->move(sourcePath, destinationPath, MainThreadFileSystemCallbacks::createLeakedPtr(bridge, mode));
}

void WorkerFileSystemCallbacksBridge::copyOnMainThread(WebCore::ScriptExecutionContext*, WebFileSystem* fileSystem, const KURL& sourcePath, const KURL& destinationPath, PassRefPtr<WorkerFileSystemCallbacksBridge> bridge, const String& mode)
{
    fileSystem->copy(sourcePath, destinationPath, MainThreadFileSystemCallbacks::createLeakedPtr(bridge, mode));
}

void WorkerFileSystemCallbacksBridge::removeOnMainThread(WebCore::ScriptExecutionContext*, WebFileSystem* fileSystem, const KURL& path, PassRefPtr<WorkerFileSystemCallbacksBridge> bridge, const String& mode)
{
    fileSystem->remove(path, MainThreadFileSystemCallbacks::createLeakedPtr(bridge, mode));
}

void WorkerFileSystemCallbacksBridge::removeRecursivelyOnMainThread(WebCore::ScriptExecutionContext*, WebFileSystem* fileSystem, const KURL& path, PassRefPtr<WorkerFileSystemCallbacksBridge> bridge, const String& mode)
{
    fileSystem->removeRecursively(path, MainThreadFileSystemCallbacks::createLeakedPtr(bridge, mode));
}

void WorkerFileSystemCallbacksBridge::readMetadataOnMainThread(WebCore::ScriptExecutionContext*, WebFileSystem* fileSystem, const KURL& path, PassRefPtr<WorkerFileSystemCallbacksBridge> bridge, const String& mode)
{
    fileSystem->readMetadata(path, MainThreadFileSystemCallbacks::createLeakedPtr(bridge, mode));
}

void WorkerFileSystemCallbacksBridge::createFileOnMainThread(WebCore::ScriptExecutionContext*, WebFileSystem* fileSystem, const KURL& path, bool exclusive, PassRefPtr<WorkerFileSystemCallbacksBridge> bridge, const String& mode)
{
    fileSystem->createFile(path, exclusive, MainThreadFileSystemCallbacks::createLeakedPtr(bridge, mode));
}

void WorkerFileSystemCallbacksBridge::createDirectoryOnMainThread(WebCore::ScriptExecutionContext*, WebFileSystem* fileSystem, const KURL& path, bool exclusive, PassRefPtr<WorkerFileSystemCallbacksBridge> bridge, const String& mode)
{
    fileSystem->createDirectory(path, exclusive, MainThreadFileSystemCallbacks::createLeakedPtr(bridge, mode));
}

void WorkerFileSystemCallbacksBridge::fileExistsOnMainThread(WebCore::ScriptExecutionContext*, WebFileSystem* fileSystem, const KURL& path, PassRefPtr<WorkerFileSystemCallbacksBridge> bridge, const String& mode)
{
    fileSystem->fileExists(path, MainThreadFileSystemCallbacks::createLeakedPtr(bridge, mode));
}

void WorkerFileSystemCallbacksBridge::directoryExistsOnMainThread(WebCore::ScriptExecutionContext*, WebFileSystem* fileSystem, const KURL& path, PassRefPtr<WorkerFileSystemCallbacksBridge> bridge, const String& mode)
{
    fileSystem->directoryExists(path, MainThreadFileSystemCallbacks::createLeakedPtr(bridge, mode));
}

void WorkerFileSystemCallbacksBridge::readDirectoryOnMainThread(WebCore::ScriptExecutionContext*, WebFileSystem* fileSystem, const KURL& path, PassRefPtr<WorkerFileSystemCallbacksBridge> bridge, const String& mode)
{
    fileSystem->readDirectory(path, MainThreadFileSystemCallbacks::createLeakedPtr(bridge, mode));
}

void WorkerFileSystemCallbacksBridge::createSnapshotFileOnMainThread(WebCore::ScriptExecutionContext*, WebFileSystem* fileSystem, const KURL& internalBlobURL, const KURL& path, PassRefPtr<WorkerFileSystemCallbacksBridge> bridge, const String& mode)
{
    fileSystem->createSnapshotFileAndReadMetadata(internalBlobURL, 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 KURL& rootURL, const String& mode)
{
    mayPostTaskToWorker(createCallbackTask(&didOpenFileSystemOnWorkerThread,
                                           this, name, rootURL), 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(WebCore::WorkerLoaderProxy* workerLoaderProxy, ScriptExecutionContext* scriptExecutionContext, WebFileSystemCallbacks* callbacks)
    : m_workerLoaderProxy(workerLoaderProxy)
    , m_workerContext(scriptExecutionContext)
    , m_workerContextObserver(WorkerFileSystemContextObserver::create(static_cast<WorkerContext*>(m_workerContext), this).leakPtr())
    , m_callbacksOnWorkerThread(callbacks)
{
    ASSERT(m_workerContext->isContextThread());
}

WorkerFileSystemCallbacksBridge::~WorkerFileSystemCallbacksBridge()
{
    ASSERT(!m_callbacksOnWorkerThread);
}

void WorkerFileSystemCallbacksBridge::didFailOnWorkerThread(ScriptExecutionContext*, PassRefPtr<WorkerFileSystemCallbacksBridge> bridge, WebFileError error)
{
    bridge->m_callbacksOnWorkerThread->didFail(error);
}

void WorkerFileSystemCallbacksBridge::didOpenFileSystemOnWorkerThread(ScriptExecutionContext*, PassRefPtr<WorkerFileSystemCallbacksBridge> bridge, const String& name, const KURL& rootURL)
{
    bridge->m_callbacksOnWorkerThread->didOpenFileSystem(name, rootURL);
}

void WorkerFileSystemCallbacksBridge::didSucceedOnWorkerThread(ScriptExecutionContext*, PassRefPtr<WorkerFileSystemCallbacksBridge> bridge)
{
    bridge->m_callbacksOnWorkerThread->didSucceed();
}

void WorkerFileSystemCallbacksBridge::didReadMetadataOnWorkerThread(ScriptExecutionContext*, PassRefPtr<WorkerFileSystemCallbacksBridge> bridge, const WebFileInfo& info)
{
    bridge->m_callbacksOnWorkerThread->didReadMetadata(info);
}

void WorkerFileSystemCallbacksBridge::didReadDirectoryOnWorkerThread(ScriptExecutionContext*, PassRefPtr<WorkerFileSystemCallbacksBridge> bridge, const WebVector<WebFileSystemEntry>& entries, bool hasMore)
{
    bridge->m_callbacksOnWorkerThread->didReadDirectory(entries, hasMore);
}


void WorkerFileSystemCallbacksBridge::runTaskOnMainThread(WebCore::ScriptExecutionContext* scriptExecutionContext, PassRefPtr<WorkerFileSystemCallbacksBridge> bridge, PassOwnPtr<WebCore::ScriptExecutionContext::Task> taskToRun)
{
    ASSERT(isMainThread());
    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);

    // taskToRun does the callback.
    bridge->cleanUpAfterCallback();

    // WorkerFileSystemCallbacksBridge may be deleted here when bridge goes out of scope.
}

void WorkerFileSystemCallbacksBridge::dispatchTaskToMainThread(PassOwnPtr<WebCore::ScriptExecutionContext::Task> task)
{
    ASSERT(m_workerLoaderProxy);
    ASSERT(m_workerContext->isContextThread());
    WebWorkerBase::dispatchTaskToMainThread(createCallbackTask(&runTaskOnMainThread, RefPtr<WorkerFileSystemCallbacksBridge>(this).release(), task));
}

void WorkerFileSystemCallbacksBridge::mayPostTaskToWorker(PassOwnPtr<ScriptExecutionContext::Task> task, const String& mode)
{
    // Relies on its caller (MainThreadFileSystemCallbacks:did*) to keep WorkerFileSystemCallbacksBridge alive.
    ASSERT(isMainThread());

    MutexLocker locker(m_loaderProxyMutex);
    if (m_workerLoaderProxy)
        m_workerLoaderProxy->postTaskForModeToWorkerContext(createCallbackTask(&runTaskOnWorkerThread, this, task), mode);
}

} // namespace WebCore

#endif // ENABLE(FILE_SYSTEM)
