WebCore/storage/IDBRequest.cpp
changeset 0 4f2f89ce4247
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/WebCore/storage/IDBRequest.cpp	Fri Sep 17 09:02:29 2010 +0300
@@ -0,0 +1,188 @@
+/*
+ * 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 Computer, 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 "Event.h"
+#include "EventException.h"
+#include "EventListener.h"
+#include "EventNames.h"
+#include "IDBDatabaseRequest.h"
+#include "IDBIndexRequest.h"
+#include "IDBErrorEvent.h"
+#include "IDBObjectStoreRequest.h"
+#include "IDBSuccessEvent.h"
+#include "ScriptExecutionContext.h"
+
+namespace WebCore {
+
+IDBRequest::IDBRequest(ScriptExecutionContext* context, PassRefPtr<IDBAny> source)
+    : ActiveDOMObject(context, this)
+    , m_source(source)
+    , m_result(IDBAny::create())
+    , m_timer(this, &IDBRequest::timerFired)
+    , m_stopped(false)
+    , m_aborted(false)
+    , m_readyState(INITIAL)
+{
+}
+
+IDBRequest::~IDBRequest()
+{
+    if (m_readyState != DONE)
+        abort();
+}
+
+void IDBRequest::onError(PassRefPtr<IDBDatabaseError> error)
+{
+    onEventCommon();
+    m_error = error;
+}
+
+void IDBRequest::onSuccess()
+{
+    onEventCommon();
+    m_result->set();
+}
+
+void IDBRequest::onSuccess(PassRefPtr<IDBDatabase> idbDatabase)
+{
+    onEventCommon();
+    m_result->set(IDBDatabaseRequest::create(idbDatabase));
+}
+
+void IDBRequest::onSuccess(PassRefPtr<IDBIndex> idbIndex)
+{
+    onEventCommon();
+    m_result->set(IDBIndexRequest::create(idbIndex));
+}
+
+void IDBRequest::onSuccess(PassRefPtr<IDBKey> idbKey)
+{
+    onEventCommon();
+    m_result->set(idbKey);
+}
+
+void IDBRequest::onSuccess(PassRefPtr<IDBObjectStore> idbObjectStore)
+{
+    onEventCommon();
+    m_result->set(IDBObjectStoreRequest::create(idbObjectStore));
+}
+
+void IDBRequest::onSuccess(PassRefPtr<SerializedScriptValue> serializedScriptValue)
+{
+    onEventCommon();
+    m_result->set(serializedScriptValue);
+}
+
+void IDBRequest::abort()
+{
+    m_timer.stop();
+    m_aborted = true;
+    // FIXME: This should cancel any pending work being done in the backend.
+}
+
+ScriptExecutionContext* IDBRequest::scriptExecutionContext() const
+{
+    return ActiveDOMObject::scriptExecutionContext();
+}
+
+void IDBRequest::stop()
+{
+    abort();
+    m_selfRef = 0; // Could trigger a delete.
+}
+
+void IDBRequest::suspend()
+{
+    m_timer.stop();
+    m_stopped = true;
+}
+
+void IDBRequest::resume()
+{
+    m_stopped = false;
+    // We only hold our self ref when we're waiting to dispatch an event.
+    if (m_selfRef && !m_aborted)
+        m_timer.startOneShot(0);
+}
+
+EventTargetData* IDBRequest::eventTargetData()
+{
+    return &m_eventTargetData;
+}
+
+EventTargetData* IDBRequest::ensureEventTargetData()
+{
+    return &m_eventTargetData;
+}
+
+void IDBRequest::timerFired(Timer<IDBRequest>*)
+{
+    ASSERT(m_readyState == DONE);
+    ASSERT(m_selfRef);
+    ASSERT(!m_stopped);
+    ASSERT(!m_aborted);
+
+    // We need to keep self-referencing ourself, otherwise it's possible we'll be deleted.
+    // But in some cases, suspend() could be called while we're dispatching an event, so we
+    // need to make sure that resume() doesn't re-start the timer based on m_selfRef being set.
+    RefPtr<IDBRequest> selfRef = m_selfRef.release();
+
+    if (m_error) {
+        ASSERT(m_result->type() == IDBAny::UndefinedType);
+        dispatchEvent(IDBErrorEvent::create(m_source, *m_error));
+    } else {
+        ASSERT(m_result->type() != IDBAny::UndefinedType);
+        dispatchEvent(IDBSuccessEvent::create(m_source, m_result));        
+    }
+}
+
+void IDBRequest::onEventCommon()
+{
+    ASSERT(m_readyState < DONE);
+    ASSERT(m_result->type() == IDBAny::UndefinedType);
+    ASSERT(!m_error);
+    ASSERT(!m_selfRef);
+    ASSERT(!m_timer.isActive());
+
+    if (m_aborted)
+        return;
+
+    m_readyState = DONE;
+    m_selfRef = this;
+    if (!m_stopped)
+        m_timer.startOneShot(0);
+}
+
+} // namespace WebCore
+
+#endif