#include "config.h"
#include "modules/indexeddb/IDBRequest.h"
-#include "bindings/v8/ExceptionState.h"
-#include "bindings/v8/ExceptionStatePlaceholder.h"
-#include "bindings/v8/IDBBindingUtilities.h"
+#include "bindings/core/v8/ExceptionState.h"
+#include "bindings/core/v8/ExceptionStatePlaceholder.h"
+#include "bindings/modules/v8/IDBBindingUtilities.h"
#include "core/dom/ExecutionContext.h"
#include "core/events/EventQueue.h"
+#include "modules/IndexedDBNames.h"
#include "modules/indexeddb/IDBCursorWithValue.h"
#include "modules/indexeddb/IDBDatabase.h"
#include "modules/indexeddb/IDBEventDispatcher.h"
#include "modules/indexeddb/IDBTracing.h"
#include "platform/SharedBuffer.h"
+#include "public/platform/WebBlobInfo.h"
-namespace WebCore {
+using blink::WebIDBCursor;
-PassRefPtr<IDBRequest> IDBRequest::create(ExecutionContext* context, PassRefPtr<IDBAny> source, IDBTransaction* transaction)
+namespace blink {
+
+IDBRequest* IDBRequest::create(ScriptState* scriptState, IDBAny* source, IDBTransaction* transaction)
{
- RefPtr<IDBRequest> request(adoptRef(new IDBRequest(context, source, transaction)));
+ IDBRequest* request = adoptRefCountedGarbageCollectedWillBeNoop(new IDBRequest(scriptState, source, transaction));
request->suspendIfNeeded();
// Requests associated with IDBFactory (open/deleteDatabase/getDatabaseNames) are not associated with transactions.
if (transaction)
- transaction->registerRequest(request.get());
- return request.release();
+ transaction->registerRequest(request);
+ return request;
}
-IDBRequest::IDBRequest(ExecutionContext* context, PassRefPtr<IDBAny> source, IDBTransaction* transaction)
- : ActiveDOMObject(context)
+IDBRequest::IDBRequest(ScriptState* scriptState, IDBAny* source, IDBTransaction* transaction)
+ : ActiveDOMObject(scriptState->executionContext())
, m_contextStopped(false)
, m_transaction(transaction)
, m_readyState(PENDING)
, m_requestAborted(false)
+ , m_scriptState(scriptState)
, m_source(source)
, m_hasPendingActivity(true)
, m_cursorType(IndexedDB::CursorKeyAndValue)
- , m_cursorDirection(IndexedDB::CursorNext)
- , m_pendingCursor(0)
+ , m_cursorDirection(WebIDBCursorDirectionNext)
+ , m_pendingCursor(nullptr)
, m_didFireUpgradeNeededEvent(false)
, m_preventPropagation(false)
, m_resultDirty(true)
- , m_requestState(context)
{
ScriptWrappable::init(this);
}
IDBRequest::~IDBRequest()
{
ASSERT(m_readyState == DONE || m_readyState == EarlyDeath || !executionContext());
+ handleBlobAcks();
+}
+
+void IDBRequest::trace(Visitor* visitor)
+{
+ visitor->trace(m_transaction);
+ visitor->trace(m_source);
+ visitor->trace(m_result);
+ visitor->trace(m_error);
+#if ENABLE(OILPAN)
+ visitor->trace(m_enqueuedEvents);
+#endif
+ visitor->trace(m_pendingCursor);
+ visitor->trace(m_cursorKey);
+ visitor->trace(m_cursorPrimaryKey);
+ EventTargetWithInlineData::trace(visitor);
}
ScriptValue IDBRequest::result(ExceptionState& exceptionState)
exceptionState.throwDOMException(InvalidStateError, IDBDatabase::requestNotFinishedErrorMessage);
return ScriptValue();
}
+ if (m_contextStopped || !executionContext())
+ return ScriptValue();
m_resultDirty = false;
- return idbAnyToScriptValue(&m_requestState, m_result);
+ ScriptValue value = idbAnyToScriptValue(m_scriptState.get(), m_result);
+ handleBlobAcks();
+ return value;
}
-PassRefPtr<DOMError> IDBRequest::error(ExceptionState& exceptionState) const
+PassRefPtrWillBeRawPtr<DOMError> IDBRequest::error(ExceptionState& exceptionState) const
{
if (m_readyState != DONE) {
exceptionState.throwDOMException(InvalidStateError, IDBDatabase::requestNotFinishedErrorMessage);
- return 0;
+ return nullptr;
}
return m_error;
}
-ScriptValue IDBRequest::source(ExecutionContext* context) const
+ScriptValue IDBRequest::source() const
{
- DOMRequestState requestState(context);
- return idbAnyToScriptValue(&requestState, m_source);
+ if (m_contextStopped || !executionContext())
+ return ScriptValue();
+
+ return idbAnyToScriptValue(m_scriptState.get(), m_source);
}
const String& IDBRequest::readyState() const
{
ASSERT(m_readyState == PENDING || m_readyState == DONE);
- DEFINE_STATIC_LOCAL(AtomicString, pending, ("pending", AtomicString::ConstructFromLiteral));
- DEFINE_STATIC_LOCAL(AtomicString, done, ("done", AtomicString::ConstructFromLiteral));
if (m_readyState == PENDING)
- return pending;
+ return IndexedDBNames::pending;
- return done;
+ return IndexedDBNames::done;
}
void IDBRequest::abort()
if (m_readyState == DONE)
return;
- // Enqueued events may be the only reference to this object.
- RefPtr<IDBRequest> self(this);
-
EventQueue* eventQueue = executionContext()->eventQueue();
for (size_t i = 0; i < m_enqueuedEvents.size(); ++i) {
bool removed = eventQueue->cancelEvent(m_enqueuedEvents[i].get());
m_requestAborted = true;
}
-void IDBRequest::setCursorDetails(IndexedDB::CursorType cursorType, IndexedDB::CursorDirection direction)
+void IDBRequest::setCursorDetails(IndexedDB::CursorType cursorType, WebIDBCursorDirection direction)
{
ASSERT(m_readyState == PENDING);
ASSERT(!m_pendingCursor);
m_cursorDirection = direction;
}
-void IDBRequest::setPendingCursor(PassRefPtr<IDBCursor> cursor)
+void IDBRequest::setPendingCursor(IDBCursor* cursor)
{
ASSERT(m_readyState == DONE);
ASSERT(executionContext());
m_hasPendingActivity = true;
m_pendingCursor = cursor;
- setResult(PassRefPtr<IDBAny>(0));
+ setResult(0);
m_readyState = PENDING;
m_error.clear();
m_transaction->registerRequest(this);
return 0;
}
-void IDBRequest::setResultCursor(PassRefPtr<IDBCursor> cursor, PassRefPtr<IDBKey> key, PassRefPtr<IDBKey> primaryKey, PassRefPtr<SharedBuffer> value)
+void IDBRequest::setResultCursor(IDBCursor* cursor, IDBKey* key, IDBKey* primaryKey, PassRefPtr<SharedBuffer> value, PassOwnPtr<Vector<WebBlobInfo> > blobInfo)
{
ASSERT(m_readyState == PENDING);
m_cursorKey = key;
m_cursorPrimaryKey = primaryKey;
m_cursorValue = value;
+ ASSERT(!m_blobInfo.get());
+ m_blobInfo = blobInfo;
onSuccessInternal(IDBAny::create(cursor));
}
-void IDBRequest::checkForReferenceCycle()
+void IDBRequest::handleBlobAcks()
{
- // 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();
+ if (m_blobInfo.get() && m_blobInfo->size()) {
+ m_transaction->db()->ackReceivedBlobs(m_blobInfo.get());
+ m_blobInfo.clear();
+ }
}
bool IDBRequest::shouldEnqueueEvent() const
return true;
}
-void IDBRequest::onError(PassRefPtr<DOMError> error)
+void IDBRequest::onError(PassRefPtrWillBeRawPtr<DOMError> error)
{
IDB_TRACE("IDBRequest::onError()");
if (!shouldEnqueueEvent())
return;
m_error = error;
+ setResult(IDBAny::createUndefined());
m_pendingCursor.clear();
enqueueEvent(Event::createCancelableBubble(EventTypeNames::error));
}
if (!shouldEnqueueEvent())
return;
- RefPtr<DOMStringList> domStringList = DOMStringList::create();
+ RefPtrWillBeRawPtr<DOMStringList> domStringList = DOMStringList::create();
for (size_t i = 0; i < stringList.size(); ++i)
domStringList->append(stringList[i]);
onSuccessInternal(IDBAny::create(domStringList.release()));
}
-void IDBRequest::onSuccess(PassOwnPtr<blink::WebIDBCursor> backend, PassRefPtr<IDBKey> key, PassRefPtr<IDBKey> primaryKey, PassRefPtr<SharedBuffer> value)
+void IDBRequest::onSuccess(PassOwnPtr<WebIDBCursor> backend, IDBKey* key, IDBKey* primaryKey, PassRefPtr<SharedBuffer> value, PassOwnPtr<Vector<WebBlobInfo> > blobInfo)
{
IDB_TRACE("IDBRequest::onSuccess(IDBCursor)");
if (!shouldEnqueueEvent())
return;
ASSERT(!m_pendingCursor);
- RefPtr<IDBCursor> cursor;
+ IDBCursor* cursor = 0;
switch (m_cursorType) {
case IndexedDB::CursorKeyOnly:
cursor = IDBCursor::create(backend, m_cursorDirection, this, m_source.get(), m_transaction.get());
default:
ASSERT_NOT_REACHED();
}
- setResultCursor(cursor, key, primaryKey, value);
+ setResultCursor(cursor, key, primaryKey, value, blobInfo);
}
-void IDBRequest::onSuccess(PassRefPtr<IDBKey> idbKey)
+void IDBRequest::onSuccess(IDBKey* idbKey)
{
IDB_TRACE("IDBRequest::onSuccess(IDBKey)");
if (!shouldEnqueueEvent())
onSuccessInternal(IDBAny::createUndefined());
}
-void IDBRequest::onSuccess(PassRefPtr<SharedBuffer> valueBuffer)
+void IDBRequest::onSuccess(PassRefPtr<SharedBuffer> valueBuffer, PassOwnPtr<Vector<WebBlobInfo> > blobInfo)
{
IDB_TRACE("IDBRequest::onSuccess(SharedBuffer)");
if (!shouldEnqueueEvent())
if (m_pendingCursor) {
// Value should be null, signifying the end of the cursor's range.
ASSERT(!valueBuffer.get());
+ ASSERT(!blobInfo->size());
m_pendingCursor->close();
m_pendingCursor.clear();
}
- onSuccessInternal(IDBAny::create(valueBuffer));
+ ASSERT(!m_blobInfo.get());
+ m_blobInfo = blobInfo;
+ onSuccessInternal(IDBAny::create(valueBuffer, m_blobInfo.get()));
}
-#ifndef NDEBUG
-static PassRefPtr<IDBObjectStore> effectiveObjectStore(PassRefPtr<IDBAny> source)
+#if ENABLE(ASSERT)
+static IDBObjectStore* effectiveObjectStore(IDBAny* source)
{
if (source->type() == IDBAny::IDBObjectStoreType)
return source->idbObjectStore();
}
#endif
-void IDBRequest::onSuccess(PassRefPtr<SharedBuffer> prpValueBuffer, PassRefPtr<IDBKey> prpPrimaryKey, const IDBKeyPath& keyPath)
+void IDBRequest::onSuccess(PassRefPtr<SharedBuffer> prpValueBuffer, PassOwnPtr<Vector<WebBlobInfo> > blobInfo, IDBKey* prpPrimaryKey, const IDBKeyPath& keyPath)
{
IDB_TRACE("IDBRequest::onSuccess(SharedBuffer, IDBKey, IDBKeyPath)");
if (!shouldEnqueueEvent())
return;
-#ifndef NDEBUG
ASSERT(keyPath == effectiveObjectStore(m_source)->metadata().keyPath);
-#endif
RefPtr<SharedBuffer> valueBuffer = prpValueBuffer;
- RefPtr<IDBKey> primaryKey = prpPrimaryKey;
+ IDBKey* primaryKey = prpPrimaryKey;
+ ASSERT(!m_blobInfo.get());
+ m_blobInfo = blobInfo;
-#ifndef NDEBUG
- assertPrimaryKeyValidOrInjectable(&m_requestState, valueBuffer, primaryKey, keyPath);
+#if ENABLE(ASSERT)
+ assertPrimaryKeyValidOrInjectable(m_scriptState.get(), valueBuffer, m_blobInfo.get(), primaryKey, keyPath);
#endif
- onSuccessInternal(IDBAny::create(valueBuffer, primaryKey, keyPath));
+ onSuccessInternal(IDBAny::create(valueBuffer, m_blobInfo.get(), primaryKey, keyPath));
}
void IDBRequest::onSuccess(int64_t value)
onSuccessInternal(IDBAny::createUndefined());
}
-void IDBRequest::onSuccessInternal(PassRefPtr<IDBAny> result)
+void IDBRequest::onSuccessInternal(IDBAny* result)
{
ASSERT(!m_contextStopped);
ASSERT(!m_pendingCursor);
enqueueEvent(Event::create(EventTypeNames::success));
}
-void IDBRequest::setResult(PassRefPtr<IDBAny> result)
+void IDBRequest::setResult(IDBAny* result)
{
m_result = result;
m_resultDirty = true;
}
-void IDBRequest::onSuccess(PassRefPtr<IDBKey> key, PassRefPtr<IDBKey> primaryKey, PassRefPtr<SharedBuffer> value)
+void IDBRequest::onSuccess(IDBKey* key, IDBKey* primaryKey, PassRefPtr<SharedBuffer> value, PassOwnPtr<Vector<WebBlobInfo> > blobInfo)
{
IDB_TRACE("IDBRequest::onSuccess(key, primaryKey, value)");
if (!shouldEnqueueEvent())
return;
ASSERT(m_pendingCursor);
- setResultCursor(m_pendingCursor.release(), key, primaryKey, value);
+ setResultCursor(m_pendingCursor.release(), key, primaryKey, value, blobInfo);
}
bool IDBRequest::hasPendingActivity() const
return;
m_contextStopped = true;
- m_requestState.clear();
-
- RefPtr<IDBRequest> protect(this);
if (m_readyState == PENDING) {
m_readyState = EarlyDeath;
}
m_enqueuedEvents.clear();
+ if (m_source)
+ m_source->contextWillBeDestroyed();
+ if (m_result)
+ m_result->contextWillBeDestroyed();
+ if (m_pendingCursor)
+ m_pendingCursor->contextWillBeDestroyed();
}
const AtomicString& IDBRequest::interfaceName() const
return ActiveDOMObject::executionContext();
}
-bool IDBRequest::dispatchEvent(PassRefPtr<Event> event)
+bool IDBRequest::dispatchEvent(PassRefPtrWillBeRawPtr<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);
+ ScriptState::Scope scope(m_scriptState.get());
if (event->type() != EventTypeNames::blocked)
m_readyState = DONE;
dequeueEvent(event.get());
- Vector<RefPtr<EventTarget> > targets;
+ WillBeHeapVector<RefPtrWillBeMember<EventTarget> > targets;
targets.append(this);
if (m_transaction && !m_preventPropagation) {
targets.append(m_transaction);
}
// Cursor properties should not be updated until the success event is being dispatched.
- RefPtr<IDBCursor> cursorToNotify;
+ IDBCursor* cursorToNotify = 0;
if (event->type() == EventTypeNames::success) {
cursorToNotify = getResultCursor();
if (cursorToNotify)
- cursorToNotify->setValueReady(m_cursorKey.release(), m_cursorPrimaryKey.release(), m_cursorValue.release());
+ cursorToNotify->setValueReady(m_cursorKey.release(), m_cursorPrimaryKey.release(), m_cursorValue.release(), m_blobInfo.release());
}
if (event->type() == EventTypeNames::upgradeneeded) {
m_readyState = PENDING;
}
-void IDBRequest::enqueueEvent(PassRefPtr<Event> event)
+void IDBRequest::enqueueEvent(PassRefPtrWillBeRawPtr<Event> event)
{
ASSERT(m_readyState == PENDING || m_readyState == DONE);
}
}
-} // namespace WebCore
+} // namespace blink