/*
 * Copyright (C) 2013 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 "modules/filesystem/LocalFileSystem.h"

#include "core/dom/CrossThreadTask.h"
#include "core/dom/Document.h"
#include "core/dom/ExceptionCode.h"
#include "core/dom/ExecutionContext.h"
#include "core/fileapi/FileError.h"
#include "core/frame/LocalFrame.h"
#include "core/workers/WorkerGlobalScope.h"
#include "modules/filesystem/FileSystemClient.h"
#include "platform/AsyncFileSystemCallbacks.h"
#include "platform/PermissionCallbacks.h"
#include "public/platform/Platform.h"
#include "public/platform/WebFileSystem.h"
#include "wtf/Functional.h"
#include "wtf/RefCounted.h"

namespace blink {

namespace {

void reportFailure(ExecutionContext*, PassOwnPtr<AsyncFileSystemCallbacks> callbacks, FileError::ErrorCode error)
{
    callbacks->didFail(error);
}

} // namespace

class CallbackWrapper final : public GarbageCollectedFinalized<CallbackWrapper> {
public:
    CallbackWrapper(PassOwnPtr<AsyncFileSystemCallbacks> c)
        : m_callbacks(c)
    {
    }
    virtual ~CallbackWrapper() { }
    PassOwnPtr<AsyncFileSystemCallbacks> release()
    {
        return m_callbacks.release();
    }

    void trace(Visitor*) { }

private:
    OwnPtr<AsyncFileSystemCallbacks> m_callbacks;
};

PassOwnPtrWillBeRawPtr<LocalFileSystem> LocalFileSystem::create(PassOwnPtr<FileSystemClient> client)
{
    return adoptPtrWillBeNoop(new LocalFileSystem(client));
}

LocalFileSystem::~LocalFileSystem()
{
}

void LocalFileSystem::resolveURL(ExecutionContext* context, const KURL& fileSystemURL, PassOwnPtr<AsyncFileSystemCallbacks> callbacks)
{
    RefPtrWillBeRawPtr<ExecutionContext> contextPtr(context);
    CallbackWrapper* wrapper = new CallbackWrapper(callbacks);
    requestFileSystemAccessInternal(context,
        bind(&LocalFileSystem::resolveURLInternal, this, contextPtr, fileSystemURL, wrapper),
        bind(&LocalFileSystem::fileSystemNotAllowedInternal, this, contextPtr, wrapper));
}

void LocalFileSystem::requestFileSystem(ExecutionContext* context, FileSystemType type, long long size, PassOwnPtr<AsyncFileSystemCallbacks> callbacks)
{
    RefPtrWillBeRawPtr<ExecutionContext> contextPtr(context);
    CallbackWrapper* wrapper = new CallbackWrapper(callbacks);
    requestFileSystemAccessInternal(context,
        bind(&LocalFileSystem::fileSystemAllowedInternal, this, contextPtr, type, wrapper),
        bind(&LocalFileSystem::fileSystemNotAllowedInternal, this, contextPtr, wrapper));
}

void LocalFileSystem::deleteFileSystem(ExecutionContext* context, FileSystemType type, PassOwnPtr<AsyncFileSystemCallbacks> callbacks)
{
    RefPtrWillBeRawPtr<ExecutionContext> contextPtr(context);
    ASSERT(context);
    ASSERT_WITH_SECURITY_IMPLICATION(context->isDocument());

    CallbackWrapper* wrapper = new CallbackWrapper(callbacks);
    requestFileSystemAccessInternal(context,
        bind(&LocalFileSystem::deleteFileSystemInternal, this, contextPtr, type, wrapper),
        bind(&LocalFileSystem::fileSystemNotAllowedInternal, this, contextPtr, wrapper));
}

WebFileSystem* LocalFileSystem::fileSystem() const
{
    Platform* platform = Platform::current();
    if (!platform)
        return nullptr;
    return Platform::current()->fileSystem();
}

void LocalFileSystem::requestFileSystemAccessInternal(ExecutionContext* context, const Closure& allowed, const Closure& denied)
{
    if (!client()) {
        denied();
        return;
    }
    if (!context->isDocument()) {
        if (!client()->requestFileSystemAccessSync(context)) {
            denied();
            return;
        }
        allowed();
        return;
    }
    client()->requestFileSystemAccessAsync(context, PermissionCallbacks::create(allowed, denied));
}

void LocalFileSystem::fileSystemNotAvailable(
    PassRefPtrWillBeRawPtr<ExecutionContext> context,
    CallbackWrapper* callbacks)
{
    context->postTask(createCrossThreadTask(&reportFailure, callbacks->release(), FileError::ABORT_ERR));
}

void LocalFileSystem::fileSystemNotAllowedInternal(
    PassRefPtrWillBeRawPtr<ExecutionContext> context,
    CallbackWrapper* callbacks)
{
    context->postTask(createCrossThreadTask(&reportFailure, callbacks->release(), FileError::ABORT_ERR));
}

void LocalFileSystem::fileSystemAllowedInternal(
    PassRefPtrWillBeRawPtr<ExecutionContext> context,
    FileSystemType type,
    CallbackWrapper* callbacks)
{
    if (!fileSystem()) {
        fileSystemNotAvailable(context, callbacks);
        return;
    }

    KURL storagePartition = KURL(KURL(), context->securityOrigin()->toString());
    fileSystem()->openFileSystem(storagePartition, static_cast<WebFileSystemType>(type), callbacks->release());
}

void LocalFileSystem::resolveURLInternal(
    PassRefPtrWillBeRawPtr<ExecutionContext> context,
    const KURL& fileSystemURL,
    CallbackWrapper* callbacks)
{
    if (!fileSystem()) {
        fileSystemNotAvailable(context, callbacks);
        return;
    }
    fileSystem()->resolveURL(fileSystemURL, callbacks->release());
}

void LocalFileSystem::deleteFileSystemInternal(
    PassRefPtrWillBeRawPtr<ExecutionContext> context,
    FileSystemType type,
    CallbackWrapper* callbacks)
{
    if (!fileSystem()) {
        fileSystemNotAvailable(context, callbacks);
        return;
    }
    KURL storagePartition = KURL(KURL(), context->securityOrigin()->toString());
    fileSystem()->deleteFileSystem(storagePartition, static_cast<WebFileSystemType>(type), callbacks->release());
}

LocalFileSystem::LocalFileSystem(PassOwnPtr<FileSystemClient> client)
    : m_client(client)
{
}

const char* LocalFileSystem::supplementName()
{
    return "LocalFileSystem";
}

LocalFileSystem* LocalFileSystem::from(ExecutionContext& context)
{
    if (context.isDocument()) {
        return static_cast<LocalFileSystem*>(WillBeHeapSupplement<LocalFrame>::from(toDocument(context).frame(), supplementName()));
    }
    ASSERT(context.isWorkerGlobalScope());
    return static_cast<LocalFileSystem*>(WillBeHeapSupplement<WorkerClients>::from(toWorkerGlobalScope(context).clients(), supplementName()));
}

void provideLocalFileSystemTo(LocalFrame& frame, PassOwnPtr<FileSystemClient> client)
{
    frame.provideSupplement(LocalFileSystem::supplementName(), LocalFileSystem::create(client));
}

void provideLocalFileSystemToWorker(WorkerClients* clients, PassOwnPtr<FileSystemClient> client)
{
    clients->provideSupplement(LocalFileSystem::supplementName(), LocalFileSystem::create(client));
}

} // namespace blink
