Ejemplo n.º 1
0
void IDBRequest::checkForReferenceCycle()
{
    // If this request and its cursor have the only references
    // to each other, then explicitly break the cycle.
    IDBCursor* cursor = getResultCursor();
    if (!cursor || cursor->request() != this)
        return;

    if (!hasOneRef() || !cursor->hasOneRef())
        return;

    m_result.clear();
}
Ejemplo n.º 2
0
void IDBRequest::setPendingCursor(PassRefPtr<IDBCursor> cursor)
{
    ASSERT(m_readyState == DONE);
    ASSERT(executionContext());
    ASSERT(m_transaction);
    ASSERT(!m_pendingCursor);
    ASSERT(cursor == getResultCursor());

    m_hasPendingActivity = true;
    m_pendingCursor = cursor;
    m_result.clear();
    m_readyState = PENDING;
    m_error.clear();
    m_transaction->registerRequest(this);
}
Ejemplo n.º 3
0
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);
}
Ejemplo n.º 4
0
void LegacyRequest::setPendingCursor(PassRefPtr<LegacyCursor> cursor)
{
    ASSERT(m_readyState == IDBRequestReadyState::Done);
    ASSERT(scriptExecutionContext());
    ASSERT(m_transaction);
    ASSERT(!m_pendingCursor);
    ASSERT(cursor == getResultCursor());

    m_pendingCursor = cursor;
    m_result = nullptr;
    m_readyState = IDBRequestReadyState::Pending;
    m_errorCode = 0;
    m_error = nullptr;
    m_errorMessage = String();
    m_transaction->registerRequest(this);
}
Ejemplo n.º 5
0
bool IDBRequest::dispatchEvent(PassRefPtr<Event> event)
{
    IDB_TRACE("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);
    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) {
        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(m_cursorKey.release(), m_cursorPrimaryKey.release(), m_cursorValue);
    }

    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::IDB_ABORT_ERR));

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

    bool dontPreventDefault = IDBEventDispatcher::dispatch(event.get(), targets);
    if (setTransactionActive)
        m_transaction->setActive(false);

    if (cursorToNotify)
        cursorToNotify->postSuccessHandlerCallback();

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

    if (m_transaction) {
        if (event->type() == eventNames().errorEvent && dontPreventDefault && !m_requestAborted) {
            m_transaction->setError(m_error);
            ExceptionCode unused;
            m_transaction->abort(unused);
        }

        if (event->type() != eventNames().blockedEvent)
            m_transaction->backend()->didCompleteTaskEvents();

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

    return dontPreventDefault;
}
Ejemplo n.º 6
0
bool IDBRequest::dispatchEvent(PassRefPtr<Event> event)
{
    IDB_TRACE("IDBRequest::dispatchEvent");
    if (m_contextStopped || !executionContext())
        return false;
    ASSERT(m_requestState.isValid());
    ASSERT(m_readyState == PENDING);
    ASSERT(m_hasPendingActivity);
    ASSERT(m_enqueuedEvents.size());
    ASSERT(event->target() == this);

    DOMRequestState::Scope scope(m_requestState);

    if (event->type() != EventTypeNames::blocked)
        m_readyState = DONE;
    dequeueEvent(event.get());

    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 be updated until the success event is being dispatched.
    RefPtr<IDBCursor> cursorToNotify;
    if (event->type() == EventTypeNames::success) {
        cursorToNotify = getResultCursor();
        if (cursorToNotify)
            cursorToNotify->setValueReady(m_cursorKey.release(), m_cursorPrimaryKey.release(), m_cursorValue.release());
    }

    if (event->type() == EventTypeNames::upgradeneeded) {
        ASSERT(!m_didFireUpgradeNeededEvent);
        m_didFireUpgradeNeededEvent = true;
    }

    // FIXME: When we allow custom event dispatching, this will probably need to change.
    ASSERT_WITH_MESSAGE(event->type() == EventTypeNames::success || event->type() == EventTypeNames::error || event->type() == EventTypeNames::blocked || event->type() == EventTypeNames::upgradeneeded, "event type was %s", event->type().string().utf8().data());
    const bool setTransactionActive = m_transaction && (event->type() == EventTypeNames::success || event->type() == EventTypeNames::upgradeneeded || (event->type() == EventTypeNames::error && !m_requestAborted));

    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() == EventTypeNames::error && dontPreventDefault && !m_requestAborted) {
            m_transaction->setError(m_error);
            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();

    // An upgradeneeded event will always be followed by a success or error event, so must
    // be kept alive.
    if (m_readyState == DONE && event->type() != EventTypeNames::upgradeneeded)
        m_hasPendingActivity = false;

    return dontPreventDefault;
}
Ejemplo n.º 7
0
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;
}