/*
 * 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:
 *
 * 1.  Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 * 2.  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.
 * 3.  Neither the name of Apple Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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 "IDBRequest.h"

#if ENABLE(INDEXED_DATABASE)

#include "EventException.h"
#include "EventListener.h"
#include "EventNames.h"
#include "EventQueue.h"
#include "ExceptionCodePlaceholder.h"
#include "IDBBindingUtilities.h"
#include "IDBCursorBackend.h"
#include "IDBCursorWithValue.h"
#include "IDBDatabase.h"
#include "IDBEventDispatcher.h"
#include "IDBTransaction.h"
#include "Logging.h"
#include "ScriptExecutionContext.h"
#include "SharedBuffer.h"

namespace WebCore {

Ref<IDBRequest> IDBRequest::create(ScriptExecutionContext* context, PassRefPtr<IDBAny> source, IDBTransaction* transaction)
{
    Ref<IDBRequest> request(adoptRef(*new IDBRequest(context, source, IDBDatabaseBackend::NormalTask, transaction)));
    request->suspendIfNeeded();
    // Requests associated with IDBFactory (open/deleteDatabase/getDatabaseNames) are not associated with transactions.
    if (transaction)
        transaction->registerRequest(request.ptr());
    return request;
}

Ref<IDBRequest> IDBRequest::create(ScriptExecutionContext* context, PassRefPtr<IDBAny> source, IDBDatabaseBackend::TaskType taskType, IDBTransaction* transaction)
{
    Ref<IDBRequest> request(adoptRef(*new IDBRequest(context, source, taskType, transaction)));
    request->suspendIfNeeded();
    // Requests associated with IDBFactory (open/deleteDatabase/getDatabaseNames) are not associated with transactions.
    if (transaction)
        transaction->registerRequest(request.ptr());
    return request;
}

IDBRequest::IDBRequest(ScriptExecutionContext* context, PassRefPtr<IDBAny> source, IDBDatabaseBackend::TaskType taskType, IDBTransaction* transaction)
    : ActiveDOMObject(context)
    , m_result(0)
    , m_errorCode(0)
    , m_contextStopped(false)
    , m_transaction(transaction)
    , m_readyState(PENDING)
    , m_requestAborted(false)
    , m_source(source)
    , m_taskType(taskType)
    , m_hasPendingActivity(true)
    , m_cursorType(IndexedDB::CursorType::KeyAndValue)
    , m_cursorDirection(IndexedDB::CursorDirection::Next)
    , m_cursorFinished(false)
    , m_pendingCursor(0)
    , m_didFireUpgradeNeededEvent(false)
    , m_preventPropagation(false)
    , m_requestState(context)
{
}

IDBRequest::~IDBRequest()
{
}

PassRefPtr<IDBAny> IDBRequest::result(ExceptionCode& ec) const
{
    if (m_readyState != DONE) {
        ec = IDBDatabaseException::InvalidStateError;
        return 0;
    }
    return m_result;
}

PassRefPtr<DOMError> IDBRequest::error(ExceptionCode& ec) const
{
    if (m_readyState != DONE) {
        ec = IDBDatabaseException::InvalidStateError;
        return 0;
    }
    return m_error;
}

unsigned short IDBRequest::errorCode(ExceptionCode& ec) const
{
    if (m_readyState != DONE) {
        ec = IDBDatabaseException::InvalidStateError;
        return 0;
    }
    return m_errorCode;
}

PassRefPtr<IDBAny> IDBRequest::source() const
{
    return m_source;
}

PassRefPtr<IDBTransaction> IDBRequest::transaction() const
{
    return m_transaction;
}

const String& IDBRequest::readyState() const
{
    ASSERT(m_readyState == PENDING || m_readyState == DONE);
    DEPRECATED_DEFINE_STATIC_LOCAL(AtomicString, pending, ("pending", AtomicString::ConstructFromLiteral));
    DEPRECATED_DEFINE_STATIC_LOCAL(AtomicString, done, ("done", AtomicString::ConstructFromLiteral));

    if (m_readyState == PENDING)
        return pending;

    return done;
}

void IDBRequest::markEarlyDeath()
{
    ASSERT(m_readyState == PENDING);
    m_readyState = EarlyDeath;
    if (m_transaction)
        m_transaction->unregisterRequest(this);
}

void IDBRequest::abort()
{
    ASSERT(!m_requestAborted);
    if (m_contextStopped || !scriptExecutionContext())
        return;
    ASSERT(m_readyState == PENDING || m_readyState == DONE);
    if (m_readyState == DONE)
        return;

    // Enqueued events may be the only reference to this object.
    RefPtr<IDBRequest> self(this);

    EventQueue& eventQueue = scriptExecutionContext()->eventQueue();
    for (auto& event : m_enqueuedEvents) {
        bool removed = eventQueue.cancelEvent(*event);
        ASSERT_UNUSED(removed, removed);
    }
    m_enqueuedEvents.clear();

    m_errorCode = 0;
    m_error.clear();
    m_errorMessage = String();
    m_result.clear();
    onError(IDBDatabaseError::create(IDBDatabaseException::AbortError));
    m_requestAborted = true;
}

void IDBRequest::setCursorDetails(IndexedDB::CursorType cursorType, IndexedDB::CursorDirection direction)
{
    ASSERT(m_readyState == PENDING);
    ASSERT(!m_pendingCursor);
    m_cursorType = cursorType;
    m_cursorDirection = direction;
}

void IDBRequest::setPendingCursor(PassRefPtr<IDBCursor> cursor)
{
    ASSERT(m_readyState == DONE);
    ASSERT(scriptExecutionContext());
    ASSERT(m_transaction);
    ASSERT(!m_pendingCursor);
    ASSERT(cursor == getResultCursor());

    m_pendingCursor = cursor;
    m_result.clear();
    m_readyState = PENDING;
    m_errorCode = 0;
    m_error.clear();
    m_errorMessage = String();
    m_transaction->registerRequest(this);
}

RefPtr<IDBCursor> IDBRequest::getResultCursor()
{
    if (!m_result)
        return nullptr;
    if (m_result->type() == IDBAny::IDBCursorType)
        return m_result->idbCursor();
    if (m_result->type() == IDBAny::IDBCursorWithValueType)
        return m_result->idbCursorWithValue();
    return nullptr;
}

void IDBRequest::setResultCursor(PassRefPtr<IDBCursor> cursor, PassRefPtr<IDBKey> key, PassRefPtr<IDBKey> primaryKey, const Deprecated::ScriptValue& value)
{
    ASSERT(m_readyState == PENDING);
    m_cursorKey = key;
    m_cursorPrimaryKey = primaryKey;
    m_cursorValue = value;

    if (m_cursorType == IndexedDB::CursorType::KeyOnly) {
        m_result = IDBAny::create(cursor);
        return;
    }

    m_result = IDBAny::create(IDBCursorWithValue::fromCursor(cursor));
}

void IDBRequest::finishCursor()
{
    m_cursorFinished = true;
    if (m_readyState != PENDING)
        m_hasPendingActivity = false;
}

bool IDBRequest::shouldEnqueueEvent() const
{
    if (m_contextStopped || !scriptExecutionContext())
        return false;
    ASSERT(m_readyState == PENDING || m_readyState == DONE);
    if (m_requestAborted)
        return false;
    ASSERT(m_readyState == PENDING);
    ASSERT(!m_errorCode && m_errorMessage.isNull() && !m_error && !m_result);
    return true;
}

void IDBRequest::onError(PassRefPtr<IDBDatabaseError> error)
{
    LOG(StorageAPI, "IDBRequest::onError() (%s) '%s'", error->name().utf8().data(), error->message().utf8().data());
    if (!shouldEnqueueEvent())
        return;

    m_errorCode = error->code();
    m_errorMessage = error->message();
    m_error = DOMError::create(IDBDatabaseException::getErrorName(error->idbCode()));
    m_pendingCursor.clear();
    enqueueEvent(Event::create(eventNames().errorEvent, true, true));
}

static PassRefPtr<Event> createSuccessEvent()
{
    return Event::create(eventNames().successEvent, false, false);
}

void IDBRequest::onSuccess(PassRefPtr<DOMStringList> domStringList)
{
    LOG(StorageAPI, "IDBRequest::onSuccess(DOMStringList)");
    if (!shouldEnqueueEvent())
        return;

    m_result = IDBAny::create(domStringList);
    enqueueEvent(createSuccessEvent());
}

void IDBRequest::onSuccess(PassRefPtr<IDBCursorBackend> prpBackend)
{
    LOG(StorageAPI, "IDBRequest::onSuccess(IDBCursor)");
    if (!shouldEnqueueEvent())
        return;

    DOMRequestState::Scope scope(m_requestState);

    RefPtr<IDBCursorBackend> backend = prpBackend;
    RefPtr<IDBKey> key = backend->key();
    RefPtr<IDBKey> primaryKey = backend->primaryKey();

    Deprecated::ScriptValue value = deserializeIDBValueBuffer(requestState(), backend->valueBuffer(), !!key);

    ASSERT(!m_pendingCursor);
    RefPtr<IDBCursor> cursor;
    switch (m_cursorType) {
    case IndexedDB::CursorType::KeyOnly:
        cursor = IDBCursor::create(backend.release(), m_cursorDirection, this, m_source.get(), m_transaction.get());
        break;
    case IndexedDB::CursorType::KeyAndValue:
        cursor = IDBCursorWithValue::create(backend.release(), m_cursorDirection, this, m_source.get(), m_transaction.get());
        break;
    default:
        ASSERT_NOT_REACHED();
    }
    setResultCursor(cursor, key.release(), primaryKey.release(), value);

    enqueueEvent(createSuccessEvent());
}

void IDBRequest::onSuccess(PassRefPtr<IDBKey> idbKey)
{
    LOG(StorageAPI, "IDBRequest::onSuccess(IDBKey)");
    if (!shouldEnqueueEvent())
        return;

    if (idbKey && idbKey->isValid()) {
        DOMRequestState::Scope scope(m_requestState);
        m_result = IDBAny::create(idbKeyToScriptValue(requestState(), idbKey));
    } else
        m_result = IDBAny::createInvalid();
    enqueueEvent(createSuccessEvent());
}

void IDBRequest::onSuccess(PassRefPtr<SharedBuffer> valueBuffer)
{
    LOG(StorageAPI, "IDBRequest::onSuccess(SharedBuffer)");
    if (!shouldEnqueueEvent())
        return;

    DOMRequestState::Scope scope(m_requestState);

    // FIXME: By not knowing whether or not the key is defined here, we don't know
    // if a null valueBuffer means the value is null or the value is undefined.
    Deprecated::ScriptValue value = deserializeIDBValueBuffer(requestState(), valueBuffer, true);
    onSuccessInternal(value);
}

#ifndef NDEBUG
static PassRefPtr<IDBObjectStore> effectiveObjectStore(PassRefPtr<IDBAny> source)
{
    if (source->type() == IDBAny::IDBObjectStoreType)
        return source->idbObjectStore();
    if (source->type() == IDBAny::IDBIndexType)
        return source->idbIndex()->objectStore();

    ASSERT_NOT_REACHED();
    return 0;
}
#endif

void IDBRequest::onSuccess(PassRefPtr<SharedBuffer> valueBuffer, PassRefPtr<IDBKey> prpPrimaryKey, const IDBKeyPath& keyPath)
{
    LOG(StorageAPI, "IDBRequest::onSuccess(SharedBuffer, IDBKey, IDBKeyPath)");
    if (!shouldEnqueueEvent())
        return;

#ifndef NDEBUG
    ASSERT(keyPath == effectiveObjectStore(m_source)->keyPath());
#endif
    DOMRequestState::Scope scope(m_requestState);

    // FIXME: By not knowing whether or not the key is defined here, we don't know
    // if a null valueBuffer means the value is null or the value is undefined.
    Deprecated::ScriptValue value = deserializeIDBValueBuffer(requestState(), valueBuffer, true);

    RefPtr<IDBKey> primaryKey = prpPrimaryKey;

    if (!keyPath.isNull()) {
#ifndef NDEBUG
        RefPtr<IDBKey> expectedKey = createIDBKeyFromScriptValueAndKeyPath(requestState()->exec(), value, keyPath);
        ASSERT(!expectedKey || expectedKey->isEqual(primaryKey.get()));
#endif
        bool injected = injectIDBKeyIntoScriptValue(requestState(), primaryKey, value, keyPath);
        ASSERT_UNUSED(injected, injected);
    }

    onSuccessInternal(value);
}

void IDBRequest::onSuccess(int64_t value)
{
    LOG(StorageAPI, "IDBRequest::onSuccess(int64_t)");
    if (!shouldEnqueueEvent())
        return;
    return onSuccessInternal(SerializedScriptValue::numberValue(value));
}

void IDBRequest::onSuccess()
{
    LOG(StorageAPI, "IDBRequest::onSuccess()");
    if (!shouldEnqueueEvent())
        return;
    return onSuccessInternal(SerializedScriptValue::undefinedValue());
}

void IDBRequest::onSuccessInternal(PassRefPtr<SerializedScriptValue> value)
{
    ASSERT(!m_contextStopped);
    DOMRequestState::Scope scope(m_requestState);
    return onSuccessInternal(deserializeIDBValue(requestState(), value));
}

void IDBRequest::onSuccessInternal(const Deprecated::ScriptValue& value)
{
    m_result = IDBAny::create(value);
    if (m_pendingCursor) {
        m_pendingCursor->close();
        m_pendingCursor.clear();
    }
    enqueueEvent(createSuccessEvent());
}

void IDBRequest::onSuccess(PassRefPtr<IDBKey> key, PassRefPtr<IDBKey> primaryKey, PassRefPtr<SharedBuffer> buffer)
{
    LOG(StorageAPI, "IDBRequest::onSuccess(key, primaryKey, valueBuffer)");
    if (!shouldEnqueueEvent())
        return;

    DOMRequestState::Scope scope(m_requestState);

    Deprecated::ScriptValue value = deserializeIDBValueBuffer(requestState(), buffer, !!key);

    ASSERT(m_pendingCursor);
    setResultCursor(m_pendingCursor.release(), key, primaryKey, value);
    enqueueEvent(createSuccessEvent());
}

bool IDBRequest::hasPendingActivity() const
{
    // FIXME: In an ideal world, we should return true as long as anyone has a or can
    //        get a handle to us and we have event listeners. This is order to handle
    //        user generated events properly.
    return m_hasPendingActivity && !m_contextStopped;
}

void IDBRequest::stop()
{
    if (m_contextStopped)
        return;

    m_contextStopped = true;
    m_requestState.clear();
    if (m_readyState == PENDING)
        markEarlyDeath();
}

bool IDBRequest::canSuspendForPageCache() const
{
    return !m_hasPendingActivity;
}

const char* IDBRequest::activeDOMObjectName() const
{
    return "IDBRequest";
}

EventTargetInterface IDBRequest::eventTargetInterface() const
{
    return IDBRequestEventTargetInterfaceType;
}

bool IDBRequest::dispatchEvent(PassRefPtr<Event> event)
{
    LOG(StorageAPI, "IDBRequest::dispatchEvent");
    ASSERT(m_readyState == PENDING);
    ASSERT(!m_contextStopped);
    ASSERT(m_hasPendingActivity);
    ASSERT(m_enqueuedEvents.size());
    ASSERT(scriptExecutionContext());
    ASSERT(event->target() == this);
    ASSERT_WITH_MESSAGE(m_readyState < DONE, "When dispatching event %s, m_readyState < DONE(%d), was %d", event->type().string().utf8().data(), DONE, m_readyState);

    DOMRequestState::Scope scope(m_requestState);

    if (event->type() != eventNames().blockedEvent)
        m_readyState = DONE;

    for (size_t i = 0; i < m_enqueuedEvents.size(); ++i) {
        if (m_enqueuedEvents[i].get() == event.get())
            m_enqueuedEvents.remove(i);
    }

    Vector<RefPtr<EventTarget>> targets;
    targets.append(this);
    if (m_transaction && !m_preventPropagation) {
        targets.append(m_transaction);
        // If there ever are events that are associated with a database but
        // that do not have a transaction, then this will not work and we need
        // this object to actually hold a reference to the database (to ensure
        // it stays alive).
        targets.append(m_transaction->db());
    }

    // Cursor properties should not updated until the success event is being dispatched.
    RefPtr<IDBCursor> cursorToNotify;
    if (event->type() == eventNames().successEvent) {
        cursorToNotify = getResultCursor();
        if (cursorToNotify) {
            cursorToNotify->setValueReady(requestState(), m_cursorKey.release(), m_cursorPrimaryKey.release(), m_cursorValue);
            m_cursorValue.clear();
        }
    }

    if (event->type() == eventNames().upgradeneededEvent) {
        ASSERT(!m_didFireUpgradeNeededEvent);
        m_didFireUpgradeNeededEvent = true;
    }

    // FIXME: When we allow custom event dispatching, this will probably need to change.
    ASSERT_WITH_MESSAGE(event->type() == eventNames().successEvent || event->type() == eventNames().errorEvent || event->type() == eventNames().blockedEvent || event->type() == eventNames().upgradeneededEvent, "event type was %s", event->type().string().utf8().data());
    const bool setTransactionActive = m_transaction && (event->type() == eventNames().successEvent || event->type() == eventNames().upgradeneededEvent || (event->type() == eventNames().errorEvent && m_errorCode != IDBDatabaseException::AbortError));

    if (setTransactionActive)
        m_transaction->setActive(true);

    bool dontPreventDefault = IDBEventDispatcher::dispatch(event.get(), targets);

    if (m_transaction) {
        if (m_readyState == DONE)
            m_transaction->unregisterRequest(this);

        // Possibly abort the transaction. This must occur after unregistering (so this request
        // doesn't receive a second error) and before deactivating (which might trigger commit).
        if (event->type() == eventNames().errorEvent && dontPreventDefault && !m_requestAborted) {
            m_transaction->setError(m_error, m_errorMessage);
            m_transaction->abort(IGNORE_EXCEPTION);
        }

        // If this was the last request in the transaction's list, it may commit here.
        if (setTransactionActive)
            m_transaction->setActive(false);
    }

    if (cursorToNotify)
        cursorToNotify->postSuccessHandlerCallback();

    if (m_readyState == DONE && (!cursorToNotify || m_cursorFinished) && event->type() != eventNames().upgradeneededEvent)
        m_hasPendingActivity = false;

    return dontPreventDefault;
}

void IDBRequest::uncaughtExceptionInEventHandler()
{
    if (m_transaction && !m_requestAborted) {
        m_transaction->setError(DOMError::create(IDBDatabaseException::getErrorName(IDBDatabaseException::AbortError)), "Uncaught exception in event handler.");
        m_transaction->abort(IGNORE_EXCEPTION);
    }
}

void IDBRequest::transactionDidFinishAndDispatch()
{
    ASSERT(m_transaction);
    ASSERT(m_transaction->isVersionChange());
    ASSERT(m_readyState == DONE);
    ASSERT(scriptExecutionContext());
    m_transaction.clear();
    m_readyState = PENDING;
}

void IDBRequest::enqueueEvent(PassRefPtr<Event> event)
{
    ASSERT(m_readyState == PENDING || m_readyState == DONE);

    if (m_contextStopped || !scriptExecutionContext())
        return;

    ASSERT_WITH_MESSAGE(m_readyState == PENDING || m_didFireUpgradeNeededEvent, "When queueing event %s, m_readyState was %d", event->type().string().utf8().data(), m_readyState);

    event->setTarget(this);

    if (scriptExecutionContext()->eventQueue().enqueueEvent(event.get()))
        m_enqueuedEvents.append(event);
}

} // namespace WebCore

#endif
