Changeset 128533 in webkit


Ignore:
Timestamp:
Sep 13, 2012 5:28:38 PM (12 years ago)
Author:
jsbell@chromium.org
Message:

IndexedDB: Consolidate two-phase connection to avoid race conditions
https://bugs.webkit.org/show_bug.cgi?id=90411

Reviewed by Tony Chang.

Source/WebCore:

Previously, IDB connections were opened by having the front-end (1) call through to
a back-end open() method, eventually receive a success message with a back-end object
handle, and (2) call into the back-end object to register front-end callbacks. This left
the back-end's notion of an open connection in a limbo state between these two calls.
In multi-process ports, a crash of the front-end process could leave the back-end wedged
waiting for this second call (e.g. can't delete until all connections are closed).

Simplify this by having the front-end pass through the callbacks into the back-end
during the initial open() call, which eliminates the limbo state.

No new tests - no functional changes. Chromium port's webkit_unit_tests updated.

  • Modules/indexeddb/IDBDatabase.cpp:

(WebCore::IDBDatabase::create):
(WebCore::IDBDatabase::IDBDatabase): Db-callbacks is available at creation time.
(WebCore::IDBDatabase::~IDBDatabase):

  • Modules/indexeddb/IDBDatabase.h:

(IDBDatabase):

  • Modules/indexeddb/IDBDatabaseBackendImpl.cpp:

(WebCore::IDBDatabaseBackendImpl::PendingOpenCall::create): Need to track db-callbacks as well.
(WebCore::IDBDatabaseBackendImpl::PendingOpenCall::databaseCallbacks):
(WebCore::IDBDatabaseBackendImpl::PendingOpenCall::PendingOpenCall):
(IDBDatabaseBackendImpl::PendingOpenCall):
(WebCore::IDBDatabaseBackendImpl::PendingOpenWithVersionCall::create): Ditto.
(WebCore::IDBDatabaseBackendImpl::PendingOpenWithVersionCall::databaseCallbacks):
(WebCore::IDBDatabaseBackendImpl::PendingOpenWithVersionCall::PendingOpenWithVersionCall):
(IDBDatabaseBackendImpl::PendingOpenWithVersionCall):
(WebCore::IDBDatabaseBackendImpl::IDBDatabaseBackendImpl):
(WebCore::IDBDatabaseBackendImpl::setVersion):
(WebCore::IDBDatabaseBackendImpl::connectionCount): Don't need to count limbo connections any more.
(WebCore::IDBDatabaseBackendImpl::processPendingCalls): Pass through db-callbacks.
(WebCore::IDBDatabaseBackendImpl::openConnection): No more limbo connections (yay!).
(WebCore::IDBDatabaseBackendImpl::runIntVersionChangeTransaction): Pass through db-callbacks.
(WebCore::IDBDatabaseBackendImpl::openConnectionWithVersion): Ditto.
(WebCore::IDBDatabaseBackendImpl::deleteDatabase): Style.
(WebCore::IDBDatabaseBackendImpl::close): Resolve FIXME about connectionCount.

  • Modules/indexeddb/IDBDatabaseBackendImpl.h:

(IDBDatabaseBackendImpl):

  • Modules/indexeddb/IDBDatabaseBackendInterface.h:

(IDBDatabaseBackendInterface):

  • Modules/indexeddb/IDBDatabaseCallbacksImpl.cpp:

(WebCore::IDBDatabaseCallbacksImpl::create):
(WebCore::IDBDatabaseCallbacksImpl::IDBDatabaseCallbacksImpl):
(WebCore::IDBDatabaseCallbacksImpl::connect):

  • Modules/indexeddb/IDBDatabaseCallbacksImpl.h:

(IDBDatabaseCallbacksImpl):

  • Modules/indexeddb/IDBFactory.cpp:

(WebCore::IDBFactory::open): Mint the db-callbacks here...

  • Modules/indexeddb/IDBFactoryBackendImpl.cpp:

(WebCore::IDBFactoryBackendImpl::open): ...passed through to here...

  • Modules/indexeddb/IDBFactoryBackendImpl.h:

(IDBFactoryBackendImpl):

  • Modules/indexeddb/IDBFactoryBackendInterface.h:

(IDBFactoryBackendInterface):

  • Modules/indexeddb/IDBOpenDBRequest.cpp:

(WebCore::IDBOpenDBRequest::create): ...all the way to here...
(WebCore::IDBOpenDBRequest::IDBOpenDBRequest):
(WebCore::IDBOpenDBRequest::onUpgradeNeeded): ...and finally hooked up here.
(WebCore::IDBOpenDBRequest::onSuccess): (or here, if no upgrade needed).

  • Modules/indexeddb/IDBOpenDBRequest.h:

(WebCore):
(IDBOpenDBRequest):

  • Modules/indexeddb/IDBTransaction.cpp:

(WebCore::IDBTransaction::onAbort): Tweak event/notification ordering; the
notifying the database that the transaction is finished may unblock closing,
which fires more events, and the delivery matters. Previously the close would
be blocked by the transaction which gave the desired order.
(WebCore::IDBTransaction::onComplete): Ditto.

  • inspector/InspectorIndexedDBAgent.cpp: New hookup logic.

(WebCore):

Source/WebKit/chromium:

API plumbing for simplified single-phase connection opening, and tests updated
to exercise the new APIs.

  • public/WebIDBDatabase.h:

(WebIDBDatabase): Just a FIXME to remove the old second-phase hookup API.

  • public/WebIDBFactory.h:

(WebKit):
(WebIDBFactory):
(WebKit::WebIDBFactory::open): New overload that takes db-callbacks.

  • src/IDBCallbacksProxy.cpp: The db-callbacks plumbing is needed earlier.

(WebKit::IDBCallbacksProxy::onSuccess):
(WebKit::IDBCallbacksProxy::onUpgradeNeeded):
(WebKit):
(WebKit::IDBCallbacksProxy::setDatabaseCallbacks): Needs to hold on to
the db-callbacks and hook it up when the onSuccess callback comes through.

  • src/IDBCallbacksProxy.h:

(WebKit):
(IDBCallbacksProxy):

  • src/IDBDatabaseBackendProxy.cpp:
  • src/IDBDatabaseBackendProxy.h:

(IDBDatabaseBackendProxy):

  • src/IDBFactoryBackendProxy.cpp:

(WebKit::IDBFactoryBackendProxy::open):

  • src/IDBFactoryBackendProxy.h:

(IDBFactoryBackendProxy):

  • src/WebIDBDatabaseImpl.cpp:

(WebKit::WebIDBDatabaseImpl::WebIDBDatabaseImpl):
(WebKit::WebIDBDatabaseImpl::close):

  • src/WebIDBDatabaseImpl.h:

(WebIDBDatabaseImpl):

  • src/WebIDBFactoryImpl.cpp:

(WebKit::WebIDBFactoryImpl::open):

  • src/WebIDBFactoryImpl.h:

(WebIDBFactoryImpl):

  • tests/IDBAbortOnCorruptTest.cpp:

(FakeIDBDatabaseCallbacks):
(WebCore::FakeIDBDatabaseCallbacks::create):
(WebCore::FakeIDBDatabaseCallbacks::~FakeIDBDatabaseCallbacks):
(WebCore::FakeIDBDatabaseCallbacks::FakeIDBDatabaseCallbacks):
(WebCore):
(WebCore::TEST): Updated connection sequence.

  • tests/IDBDatabaseBackendTest.cpp: Ditto.
Location:
trunk/Source
Files:
31 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r128531 r128533  
     12012-09-13  Joshua Bell  <jsbell@chromium.org>
     2
     3        IndexedDB: Consolidate two-phase connection to avoid race conditions
     4        https://bugs.webkit.org/show_bug.cgi?id=90411
     5
     6        Reviewed by Tony Chang.
     7
     8        Previously, IDB connections were opened by having the front-end (1) call through to
     9        a back-end open() method, eventually receive a success message with a back-end object
     10        handle, and (2) call into the back-end object to register front-end callbacks. This left
     11        the back-end's notion of an open connection in a limbo state between these two calls.
     12        In multi-process ports, a crash of the front-end process could leave the back-end wedged
     13        waiting for this second call (e.g. can't delete until all connections are closed).
     14
     15        Simplify this by having the front-end pass through the callbacks into the back-end
     16        during the initial open() call, which eliminates the limbo state.
     17
     18        No new tests - no functional changes. Chromium port's webkit_unit_tests updated.
     19
     20        * Modules/indexeddb/IDBDatabase.cpp:
     21        (WebCore::IDBDatabase::create):
     22        (WebCore::IDBDatabase::IDBDatabase): Db-callbacks is available at creation time.
     23        (WebCore::IDBDatabase::~IDBDatabase):
     24        * Modules/indexeddb/IDBDatabase.h:
     25        (IDBDatabase):
     26        * Modules/indexeddb/IDBDatabaseBackendImpl.cpp:
     27        (WebCore::IDBDatabaseBackendImpl::PendingOpenCall::create): Need to track db-callbacks as well.
     28        (WebCore::IDBDatabaseBackendImpl::PendingOpenCall::databaseCallbacks):
     29        (WebCore::IDBDatabaseBackendImpl::PendingOpenCall::PendingOpenCall):
     30        (IDBDatabaseBackendImpl::PendingOpenCall):
     31        (WebCore::IDBDatabaseBackendImpl::PendingOpenWithVersionCall::create): Ditto.
     32        (WebCore::IDBDatabaseBackendImpl::PendingOpenWithVersionCall::databaseCallbacks):
     33        (WebCore::IDBDatabaseBackendImpl::PendingOpenWithVersionCall::PendingOpenWithVersionCall):
     34        (IDBDatabaseBackendImpl::PendingOpenWithVersionCall):
     35        (WebCore::IDBDatabaseBackendImpl::IDBDatabaseBackendImpl):
     36        (WebCore::IDBDatabaseBackendImpl::setVersion):
     37        (WebCore::IDBDatabaseBackendImpl::connectionCount): Don't need to count limbo connections any more.
     38        (WebCore::IDBDatabaseBackendImpl::processPendingCalls): Pass through db-callbacks.
     39        (WebCore::IDBDatabaseBackendImpl::openConnection): No more limbo connections (yay!).
     40        (WebCore::IDBDatabaseBackendImpl::runIntVersionChangeTransaction): Pass through db-callbacks.
     41        (WebCore::IDBDatabaseBackendImpl::openConnectionWithVersion): Ditto.
     42        (WebCore::IDBDatabaseBackendImpl::deleteDatabase): Style.
     43        (WebCore::IDBDatabaseBackendImpl::close): Resolve FIXME about connectionCount.
     44        * Modules/indexeddb/IDBDatabaseBackendImpl.h:
     45        (IDBDatabaseBackendImpl):
     46        * Modules/indexeddb/IDBDatabaseBackendInterface.h:
     47        (IDBDatabaseBackendInterface):
     48        * Modules/indexeddb/IDBDatabaseCallbacksImpl.cpp:
     49        (WebCore::IDBDatabaseCallbacksImpl::create):
     50        (WebCore::IDBDatabaseCallbacksImpl::IDBDatabaseCallbacksImpl):
     51        (WebCore::IDBDatabaseCallbacksImpl::connect):
     52        * Modules/indexeddb/IDBDatabaseCallbacksImpl.h:
     53        (IDBDatabaseCallbacksImpl):
     54        * Modules/indexeddb/IDBFactory.cpp:
     55        (WebCore::IDBFactory::open): Mint the db-callbacks here...
     56        * Modules/indexeddb/IDBFactoryBackendImpl.cpp:
     57        (WebCore::IDBFactoryBackendImpl::open): ...passed through to here...
     58        * Modules/indexeddb/IDBFactoryBackendImpl.h:
     59        (IDBFactoryBackendImpl):
     60        * Modules/indexeddb/IDBFactoryBackendInterface.h:
     61        (IDBFactoryBackendInterface):
     62        * Modules/indexeddb/IDBOpenDBRequest.cpp:
     63        (WebCore::IDBOpenDBRequest::create): ...all the way to here...
     64        (WebCore::IDBOpenDBRequest::IDBOpenDBRequest):
     65        (WebCore::IDBOpenDBRequest::onUpgradeNeeded): ...and finally hooked up here.
     66        (WebCore::IDBOpenDBRequest::onSuccess): (or here, if no upgrade needed).
     67        * Modules/indexeddb/IDBOpenDBRequest.h:
     68        (WebCore):
     69        (IDBOpenDBRequest):
     70        * Modules/indexeddb/IDBTransaction.cpp:
     71        (WebCore::IDBTransaction::onAbort): Tweak event/notification ordering; the
     72        notifying the database that the transaction is finished may unblock closing,
     73        which fires more events, and the delivery matters. Previously the close would
     74        be blocked by the transaction which gave the desired order.
     75        (WebCore::IDBTransaction::onComplete): Ditto.
     76        * inspector/InspectorIndexedDBAgent.cpp: New hookup logic.
     77        (WebCore):
     78
    1792012-09-13  Ryosuke Niwa  <rniwa@webkit.org>
    280
  • trunk/Source/WebCore/Modules/indexeddb/IDBDatabase.cpp

    r128496 r128533  
    3232#include "ExceptionCode.h"
    3333#include "IDBAny.h"
    34 #include "IDBDatabaseCallbacksImpl.h"
     34#include "IDBDatabaseCallbacks.h"
    3535#include "IDBDatabaseError.h"
    3636#include "IDBDatabaseException.h"
     
    5151namespace WebCore {
    5252
    53 PassRefPtr<IDBDatabase> IDBDatabase::create(ScriptExecutionContext* context, PassRefPtr<IDBDatabaseBackendInterface> database)
    54 {
    55     RefPtr<IDBDatabase> idbDatabase(adoptRef(new IDBDatabase(context, database)));
     53PassRefPtr<IDBDatabase> IDBDatabase::create(ScriptExecutionContext* context, PassRefPtr<IDBDatabaseBackendInterface> database, PassRefPtr<IDBDatabaseCallbacks> callbacks)
     54{
     55    RefPtr<IDBDatabase> idbDatabase(adoptRef(new IDBDatabase(context, database, callbacks)));
    5656    idbDatabase->suspendIfNeeded();
    5757    return idbDatabase.release();
    5858}
    5959
    60 IDBDatabase::IDBDatabase(ScriptExecutionContext* context, PassRefPtr<IDBDatabaseBackendInterface> backend)
     60IDBDatabase::IDBDatabase(ScriptExecutionContext* context, PassRefPtr<IDBDatabaseBackendInterface> backend, PassRefPtr<IDBDatabaseCallbacks> callbacks)
    6161    : ActiveDOMObject(context, this)
    6262    , m_backend(backend)
    6363    , m_closePending(false)
    6464    , m_contextStopped(false)
     65    , m_databaseCallbacks(callbacks)
    6566{
    6667    // We pass a reference of this object before it can be adopted.
    6768    relaxAdoptionRequirement();
    68     m_databaseCallbacks = IDBDatabaseCallbacksImpl::create(this);
    6969    m_metadata = m_backend->metadata();
    7070}
     
    7373{
    7474    close();
    75     m_databaseCallbacks->unregisterDatabase(this);
    7675}
    7776
     
    336335}
    337336
    338 void IDBDatabase::registerFrontendCallbacks()
    339 {
    340     ASSERT(m_backend);
    341     m_backend->registerFrontendCallbacks(m_databaseCallbacks);
    342 }
    343 
    344337void IDBDatabase::enqueueEvent(PassRefPtr<Event> event)
    345338{
  • trunk/Source/WebCore/Modules/indexeddb/IDBDatabase.h

    r128496 r128533  
    3333#include "EventTarget.h"
    3434#include "IDBDatabaseBackendInterface.h"
    35 #include "IDBDatabaseCallbacksImpl.h"
     35#include "IDBDatabaseCallbacks.h"
    3636#include "IDBMetadata.h"
    3737#include "IDBObjectStore.h"
     
    5252class IDBDatabase : public RefCounted<IDBDatabase>, public EventTarget, public ActiveDOMObject {
    5353public:
    54     static PassRefPtr<IDBDatabase> create(ScriptExecutionContext*, PassRefPtr<IDBDatabaseBackendInterface>);
     54    static PassRefPtr<IDBDatabase> create(ScriptExecutionContext*, PassRefPtr<IDBDatabaseBackendInterface>, PassRefPtr<IDBDatabaseCallbacks>);
    5555    ~IDBDatabase();
    5656
     
    9090
    9191    void forceClose();
    92     void registerFrontendCallbacks();
    9392    const IDBDatabaseMetadata metadata() const { return m_metadata; }
    9493    void enqueueEvent(PassRefPtr<Event>);
     
    10099
    101100private:
    102     IDBDatabase(ScriptExecutionContext*, PassRefPtr<IDBDatabaseBackendInterface>);
     101    IDBDatabase(ScriptExecutionContext*, PassRefPtr<IDBDatabaseBackendInterface>, PassRefPtr<IDBDatabaseCallbacks>);
    103102
    104103    // EventTarget
     
    124123    Vector<RefPtr<Event> > m_enqueuedEvents;
    125124
    126     RefPtr<IDBDatabaseCallbacksImpl> m_databaseCallbacks;
     125    RefPtr<IDBDatabaseCallbacks> m_databaseCallbacks;
    127126};
    128127
  • trunk/Source/WebCore/Modules/indexeddb/IDBDatabaseBackendImpl.cpp

    r128496 r128533  
    4242class IDBDatabaseBackendImpl::PendingOpenCall : public RefCounted<PendingOpenCall> {
    4343public:
    44     static PassRefPtr<PendingOpenCall> create(PassRefPtr<IDBCallbacks> callbacks)
    45     {
    46         return adoptRef(new PendingOpenCall(callbacks));
     44    static PassRefPtr<PendingOpenCall> create(PassRefPtr<IDBCallbacks> callbacks, PassRefPtr<IDBDatabaseCallbacks> databaseCallbacks)
     45    {
     46        return adoptRef(new PendingOpenCall(callbacks, databaseCallbacks));
    4747    }
    4848    PassRefPtr<IDBCallbacks> callbacks() { return m_callbacks; }
     49    PassRefPtr<IDBDatabaseCallbacks> databaseCallbacks() { return m_databaseCallbacks; }
    4950
    5051private:
    51     PendingOpenCall(PassRefPtr<IDBCallbacks> callbacks)
     52    PendingOpenCall(PassRefPtr<IDBCallbacks> callbacks, PassRefPtr<IDBDatabaseCallbacks> databaseCallbacks)
    5253        : m_callbacks(callbacks)
     54        , m_databaseCallbacks(databaseCallbacks)
    5355    {
    5456    }
    5557
    5658    RefPtr<IDBCallbacks> m_callbacks;
     59    RefPtr<IDBDatabaseCallbacks> m_databaseCallbacks;
    5760};
    5861
    5962class IDBDatabaseBackendImpl::PendingOpenWithVersionCall : public RefCounted<PendingOpenWithVersionCall> {
    6063public:
    61     static PassRefPtr<PendingOpenWithVersionCall> create(PassRefPtr<IDBCallbacks> callbacks, int64_t version)
    62     {
    63         return adoptRef(new PendingOpenWithVersionCall(callbacks, version));
     64    static PassRefPtr<PendingOpenWithVersionCall> create(PassRefPtr<IDBCallbacks> callbacks, PassRefPtr<IDBDatabaseCallbacks> databaseCallbacks, int64_t version)
     65    {
     66        return adoptRef(new PendingOpenWithVersionCall(callbacks, databaseCallbacks, version));
    6467    }
    6568    PassRefPtr<IDBCallbacks> callbacks() { return m_callbacks; }
     69    PassRefPtr<IDBDatabaseCallbacks> databaseCallbacks() { return m_databaseCallbacks; }
    6670    int64_t version() { return m_version; }
    6771
    6872private:
    69     PendingOpenWithVersionCall(PassRefPtr<IDBCallbacks> callbacks, int64_t version)
     73    PendingOpenWithVersionCall(PassRefPtr<IDBCallbacks> callbacks, PassRefPtr<IDBDatabaseCallbacks> databaseCallbacks, int64_t version)
    7074        : m_callbacks(callbacks)
     75        , m_databaseCallbacks(databaseCallbacks)
    7176        , m_version(version)
    7277    {
    7378    }
    7479    RefPtr<IDBCallbacks> m_callbacks;
     80    RefPtr<IDBDatabaseCallbacks> m_databaseCallbacks;
    7581    int64_t m_version;
    7682};
     
    131137    , m_factory(factory)
    132138    , m_transactionCoordinator(coordinator)
    133     , m_pendingConnectionCount(0)
    134139{
    135140    ASSERT(!m_name.isNull());
     
    241246    }
    242247    for (DatabaseCallbacksSet::const_iterator it = m_databaseCallbacksSet.begin(); it != m_databaseCallbacksSet.end(); ++it) {
     248        // Front end ensures the event is not fired at connections that have closePending set.
    243249        if (*it != databaseCallbacks)
    244250            (*it)->onVersionChange(version);
     
    343349}
    344350
    345 int32_t IDBDatabaseBackendImpl::connectionCount()
    346 {
    347     return m_databaseCallbacksSet.size() + m_pendingConnectionCount;
     351size_t IDBDatabaseBackendImpl::connectionCount()
     352{
     353    // This does not include pending open calls, as those should not block version changes and deletes.
     354    return m_databaseCallbacksSet.size();
    348355}
    349356
     
    356363        ASSERT(pendingOpenWithVersionCall->version() == m_intVersion);
    357364        ASSERT(m_id != InvalidId);
    358         ++m_pendingConnectionCount;
    359365        pendingOpenWithVersionCall->callbacks()->onSuccess(this);
    360         return;
     366        // Fall through when complete, as pending deletes may be (partially) unblocked.
    361367    }
    362368
     
    401407    while (!pendingOpenWithVersionCalls.isEmpty()) {
    402408        RefPtr<PendingOpenWithVersionCall> pendingOpenWithVersionCall = pendingOpenWithVersionCalls.takeFirst();
    403         openConnectionWithVersion(pendingOpenWithVersionCall->callbacks(), pendingOpenWithVersionCall->version());
     409        openConnectionWithVersion(pendingOpenWithVersionCall->callbacks(), pendingOpenWithVersionCall->databaseCallbacks(), pendingOpenWithVersionCall->version());
    404410    }
    405411
     
    410416    while (!pendingOpenCalls.isEmpty()) {
    411417        RefPtr<PendingOpenCall> pendingOpenCall = pendingOpenCalls.takeFirst();
    412         openConnection(pendingOpenCall->callbacks());
     418        openConnection(pendingOpenCall->callbacks(), pendingOpenCall->databaseCallbacks());
    413419    }
    414420    ASSERT(m_pendingOpenCalls.isEmpty());
     
    429435}
    430436
    431 void IDBDatabaseBackendImpl::registerFrontendCallbacks(PassRefPtr<IDBDatabaseCallbacks> callbacks)
    432 {
    433     ASSERT(m_backingStore.get());
    434     ASSERT(m_pendingConnectionCount);
    435     --m_pendingConnectionCount;
    436     m_databaseCallbacksSet.add(RefPtr<IDBDatabaseCallbacks>(callbacks));
    437     // We give max priority to open calls that follow upgradeneeded
    438     // events; trigger the rest of the queues to be serviced when those open
    439     // calls are finished.
    440     processPendingCalls();
    441 }
    442 
    443 void IDBDatabaseBackendImpl::openConnection(PassRefPtr<IDBCallbacks> callbacks)
     437void IDBDatabaseBackendImpl::openConnection(PassRefPtr<IDBCallbacks> callbacks, PassRefPtr<IDBDatabaseCallbacks> databaseCallbacks)
    444438{
    445439    ASSERT(m_backingStore.get());
    446440    if (!m_pendingDeleteCalls.isEmpty() || m_runningVersionChangeTransaction || !m_pendingSetVersionCalls.isEmpty())
    447         m_pendingOpenCalls.append(PendingOpenCall::create(callbacks));
     441        m_pendingOpenCalls.append(PendingOpenCall::create(callbacks, databaseCallbacks));
    448442    else {
    449443        if (m_id == InvalidId && !openInternal())
    450444            callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UNKNOWN_ERR, "Internal error."));
    451445        else {
    452             ++m_pendingConnectionCount;
     446            m_databaseCallbacksSet.add(RefPtr<IDBDatabaseCallbacks>(databaseCallbacks));
    453447            callbacks->onSuccess(this);
    454448        }
     
    456450}
    457451
    458 void IDBDatabaseBackendImpl::runIntVersionChangeTransaction(int64_t requestedVersion, PassRefPtr<IDBCallbacks> prpCallbacks)
     452void IDBDatabaseBackendImpl::runIntVersionChangeTransaction(int64_t requestedVersion, PassRefPtr<IDBCallbacks> prpCallbacks, PassRefPtr<IDBDatabaseCallbacks> prpDatabaseCallbacks)
    459453{
    460454    RefPtr<IDBCallbacks> callbacks = prpCallbacks;
     455    RefPtr<IDBDatabaseCallbacks> databaseCallbacks = prpDatabaseCallbacks;
    461456    ASSERT(callbacks);
    462457    for (DatabaseCallbacksSet::const_iterator it = m_databaseCallbacksSet.begin(); it != m_databaseCallbacksSet.end(); ++it) {
    463         // Note that some connections might close in the versionchange event
    464         // handler for some other connection, after which its own versionchange
    465         // event should not be fired. The backend doesn't worry about this, we
    466         // just queue up a version change event for every connection. The
    467         // frontend takes care to only dispatch to open connections.
    468         (*it)->onVersionChange(m_intVersion, requestedVersion);
     458        // Front end ensures the event is not fired at connections that have closePending set.
     459        if (*it != databaseCallbacks)
     460            (*it)->onVersionChange(m_intVersion, requestedVersion);
    469461    }
    470462    // The spec dictates we wait until all the version change events are
     
    475467    // tells us that all the blocked events have been delivered. See
    476468    // https://bugs.webkit.org/show_bug.cgi?id=71130
    477     if (connectionCount() > 0)
     469    if (connectionCount())
    478470        callbacks->onBlocked(m_intVersion);
    479471    // FIXME: Add test for m_runningVersionChangeTransaction.
    480     if (m_runningVersionChangeTransaction || connectionCount() > 0) {
    481         m_pendingOpenWithVersionCalls.append(PendingOpenWithVersionCall::create(callbacks, requestedVersion));
     472    if (m_runningVersionChangeTransaction || connectionCount()) {
     473        m_pendingOpenWithVersionCalls.append(PendingOpenWithVersionCall::create(callbacks, databaseCallbacks, requestedVersion));
    482474        return;
    483475    }
     
    498490    }
    499491    ASSERT_WITH_MESSAGE(!m_pendingSecondHalfOpenWithVersionCalls.size(), "m_pendingSecondHalfOpenWithVersionCalls.size = %zu", m_pendingSecondHalfOpenWithVersionCalls.size());
    500     m_pendingSecondHalfOpenWithVersionCalls.append(PendingOpenWithVersionCall::create(callbacks, requestedVersion));
    501 }
    502 
    503 void IDBDatabaseBackendImpl::openConnectionWithVersion(PassRefPtr<IDBCallbacks> prpCallbacks, int64_t version)
     492    m_pendingSecondHalfOpenWithVersionCalls.append(PendingOpenWithVersionCall::create(callbacks, databaseCallbacks, requestedVersion));
     493    m_databaseCallbacksSet.add(databaseCallbacks);
     494}
     495
     496void IDBDatabaseBackendImpl::openConnectionWithVersion(PassRefPtr<IDBCallbacks> prpCallbacks, PassRefPtr<IDBDatabaseCallbacks> prpDatabaseCallbacks, int64_t version)
    504497{
    505498    RefPtr<IDBCallbacks> callbacks = prpCallbacks;
     499    RefPtr<IDBDatabaseCallbacks> databaseCallbacks = prpDatabaseCallbacks;
    506500    if (!m_pendingDeleteCalls.isEmpty() || m_runningVersionChangeTransaction || !m_pendingSetVersionCalls.isEmpty()) {
    507         m_pendingOpenWithVersionCalls.append(PendingOpenWithVersionCall::create(callbacks, version));
     501        m_pendingOpenWithVersionCalls.append(PendingOpenWithVersionCall::create(callbacks, databaseCallbacks, version));
    508502        return;
    509503    }
     
    517511    }
    518512    if (version > m_intVersion) {
    519         runIntVersionChangeTransaction(version, callbacks);
     513        runIntVersionChangeTransaction(version, callbacks, databaseCallbacks);
    520514        return;
    521515    }
     
    525519    }
    526520    ASSERT(version == m_intVersion);
    527     ++m_pendingConnectionCount;
     521    m_databaseCallbacksSet.add(databaseCallbacks);
    528522    callbacks->onSuccess(this);
    529523}
     
    536530    }
    537531    RefPtr<IDBCallbacks> callbacks = prpCallbacks;
    538     // FIXME: Only fire onVersionChange if there the connection isn't in
    539     // the process of closing.
    540     // https://bugs.webkit.org/show_bug.cgi?id=71129
    541     for (DatabaseCallbacksSet::const_iterator it = m_databaseCallbacksSet.begin(); it != m_databaseCallbacksSet.end(); ++it)
     532    for (DatabaseCallbacksSet::const_iterator it = m_databaseCallbacksSet.begin(); it != m_databaseCallbacksSet.end(); ++it) {
     533        // Front end ensures the event is not fired at connections that have closePending set.
    542534        (*it)->onVersionChange("");
     535    }
    543536    // FIXME: Only fire onBlocked if there are open connections after the
    544537    // VersionChangeEvents are received, not just set up to fire.
    545538    // https://bugs.webkit.org/show_bug.cgi?id=71130
    546     if (connectionCount() >= 1) {
     539    if (connectionCount()) {
    547540        m_pendingDeleteCalls.append(PendingDeleteCall::create(callbacks));
    548541        callbacks->onBlocked();
     
    565558    RefPtr<IDBDatabaseCallbacks> callbacks = prpCallbacks;
    566559    ASSERT(m_databaseCallbacksSet.contains(callbacks));
     560
    567561    m_databaseCallbacksSet.remove(callbacks);
     562    // FIXME: If callbacks is also held in m_pendingSecondHalfOpenWithVersionCalls
     563    // it should be removed and onError fired against it.
     564
    568565    if (connectionCount() > 1)
    569566        return;
    570567
    571     TransactionSet transactions(m_transactions);
    572568    processPendingCalls();
    573569
    574     ASSERT(m_transactions.size() - transactions.size() <= 1);
    575     // FIXME: Instead of relying on transactions.size(), make connectionCount
    576     // aware of in-flight upgradeneeded events as well as in-flight success
    577     // events.
    578     if (!connectionCount() && !m_pendingDeleteCalls.size() && m_transactions.size() == transactions.size()) {
     570    // FIXME: Add a test for the m_pendingOpenCalls·and m_pendingOpenWithVersionCalls cases below.
     571    if (!connectionCount() && !m_pendingOpenCalls.size() && !m_pendingOpenWithVersionCalls.size() && !m_pendingDeleteCalls.size()) {
     572        TransactionSet transactions(m_transactions);
    579573        for (TransactionSet::const_iterator it = transactions.begin(); it != transactions.end(); ++it)
    580574            (*it)->abort();
  • trunk/Source/WebCore/Modules/indexeddb/IDBDatabaseBackendImpl.h

    r128496 r128533  
    5656    int64_t id() const { return m_id; }
    5757
    58     void registerFrontendCallbacks(PassRefPtr<IDBDatabaseCallbacks>);
    59     void openConnection(PassRefPtr<IDBCallbacks>);
    60     void openConnectionWithVersion(PassRefPtr<IDBCallbacks>, int64_t version);
     58    void openConnection(PassRefPtr<IDBCallbacks>, PassRefPtr<IDBDatabaseCallbacks>);
     59    void openConnectionWithVersion(PassRefPtr<IDBCallbacks>, PassRefPtr<IDBDatabaseCallbacks>, int64_t version);
    6160    void deleteDatabase(PassRefPtr<IDBCallbacks>);
    6261
     
    8079
    8180    bool openInternal();
    82     void runIntVersionChangeTransaction(int64_t requestedVersion, PassRefPtr<IDBCallbacks>);
     81    void runIntVersionChangeTransaction(int64_t requestedVersion, PassRefPtr<IDBCallbacks>, PassRefPtr<IDBDatabaseCallbacks>);
    8382    void loadObjectStores();
    84     int32_t connectionCount();
     83    size_t connectionCount();
    8584    void processPendingCalls();
    8685
     
    128127    Deque<RefPtr<PendingDeleteCall> > m_pendingDeleteCalls;
    129128
    130     // FIXME: Eliminate the limbo state between openConnection() and registerFrontendCallbacks()
    131     // that this counter tracks.
    132     int32_t m_pendingConnectionCount;
    133 
    134129    typedef ListHashSet<RefPtr<IDBDatabaseCallbacks> > DatabaseCallbacksSet;
    135130    DatabaseCallbacksSet m_databaseCallbacksSet;
  • trunk/Source/WebCore/Modules/indexeddb/IDBDatabaseBackendInterface.h

    r128496 r128533  
    3636
    3737class DOMStringList;
    38 class Frame;
    3938class IDBCallbacks;
    4039class IDBDatabaseCallbacks;
     
    6160    virtual PassRefPtr<IDBTransactionBackendInterface> transaction(DOMStringList* storeNames, unsigned short mode, ExceptionCode&) = 0;
    6261    virtual void close(PassRefPtr<IDBDatabaseCallbacks>) = 0;
    63 
    64     virtual void registerFrontendCallbacks(PassRefPtr<IDBDatabaseCallbacks>) = 0;
    6562};
    6663
  • trunk/Source/WebCore/Modules/indexeddb/IDBDatabaseCallbacksImpl.cpp

    r128496 r128533  
    3333namespace WebCore {
    3434
    35 PassRefPtr<IDBDatabaseCallbacksImpl> IDBDatabaseCallbacksImpl::create(IDBDatabase* database)
     35PassRefPtr<IDBDatabaseCallbacksImpl> IDBDatabaseCallbacksImpl::create()
    3636{
    37     return adoptRef(new IDBDatabaseCallbacksImpl(database));
     37    return adoptRef(new IDBDatabaseCallbacksImpl());
    3838}
    3939
    40 IDBDatabaseCallbacksImpl::IDBDatabaseCallbacksImpl(IDBDatabase* database)
    41     : m_database(database)
     40IDBDatabaseCallbacksImpl::IDBDatabaseCallbacksImpl()
     41    : m_database(0)
    4242{
    4343}
     
    6565}
    6666
    67 void IDBDatabaseCallbacksImpl::unregisterDatabase(IDBDatabase* database)
     67void IDBDatabaseCallbacksImpl::connect(IDBDatabase* database)
    6868{
    69     ASSERT_UNUSED(database, database == m_database);
    70     m_database = 0;
     69    ASSERT(!m_database);
     70    ASSERT(database);
     71    m_database = database;
    7172}
    7273
  • trunk/Source/WebCore/Modules/indexeddb/IDBDatabaseCallbacksImpl.h

    r128496 r128533  
    3939class IDBDatabaseCallbacksImpl : public IDBDatabaseCallbacks {
    4040public:
    41     static PassRefPtr<IDBDatabaseCallbacksImpl> create(IDBDatabase*);
     41    static PassRefPtr<IDBDatabaseCallbacksImpl> create();
    4242    virtual ~IDBDatabaseCallbacksImpl();
    4343
     44    // IDBDatabaseCallbacks
    4445    virtual void onForcedClose();
    4546    virtual void onVersionChange(const String& version);
    4647    virtual void onVersionChange(int64_t oldVersion, int64_t newVersion);
    47     void unregisterDatabase(IDBDatabase*);
     48
     49    void connect(IDBDatabase*);
    4850
    4951private:
    50     IDBDatabaseCallbacksImpl(IDBDatabase*);
     52    IDBDatabaseCallbacksImpl();
    5153
    52     // m_database has a RefPtr to this, so use a weak pointer to avoid a cycle.
     54    // The initial IDBOpenDBRequest or final IDBDatabase maintains a RefPtr to this
    5355    IDBDatabase* m_database;
    5456};
  • trunk/Source/WebCore/Modules/indexeddb/IDBFactory.cpp

    r128496 r128533  
    3838#include "GroupSettings.h"
    3939#include "IDBDatabase.h"
     40#include "IDBDatabaseCallbacksImpl.h"
    4041#include "IDBDatabaseException.h"
    4142#include "IDBFactoryBackendInterface.h"
     
    121122        return 0;
    122123
    123     RefPtr<IDBOpenDBRequest> request = IDBOpenDBRequest::create(context, IDBAny::createNull(), version);
    124     m_backend->open(name, version, request, context->securityOrigin(), context, getIndexedDBDatabasePath(context));
     124    RefPtr<IDBDatabaseCallbacksImpl> databaseCallbacks = IDBDatabaseCallbacksImpl::create();
     125    RefPtr<IDBOpenDBRequest> request = IDBOpenDBRequest::create(context, IDBAny::createNull(), databaseCallbacks, version);
     126    m_backend->open(name, version, request, databaseCallbacks, context->securityOrigin(), context, getIndexedDBDatabasePath(context));
    125127    return request;
    126128}
  • trunk/Source/WebCore/Modules/indexeddb/IDBFactoryBackendImpl.cpp

    r128496 r128533  
    151151}
    152152
    153 void IDBFactoryBackendImpl::open(const String& name, int64_t version, PassRefPtr<IDBCallbacks> callbacks, PassRefPtr<SecurityOrigin> prpSecurityOrigin, ScriptExecutionContext*, const String& dataDirectory)
     153void IDBFactoryBackendImpl::open(const String& name, int64_t version, PassRefPtr<IDBCallbacks> callbacks, PassRefPtr<IDBDatabaseCallbacks> databaseCallbacks, PassRefPtr<SecurityOrigin> prpSecurityOrigin, ScriptExecutionContext*, const String& dataDirectory)
    154154{
    155155    RefPtr<SecurityOrigin> securityOrigin = prpSecurityOrigin;
     
    176176
    177177    if (version == IDBDatabaseMetadata::NoIntVersion)
    178         databaseBackend->openConnection(callbacks);
     178        databaseBackend->openConnection(callbacks, databaseCallbacks);
    179179    else
    180         databaseBackend->openConnectionWithVersion(callbacks, version);
     180        databaseBackend->openConnectionWithVersion(callbacks, databaseCallbacks, version);
    181181}
    182182
  • trunk/Source/WebCore/Modules/indexeddb/IDBFactoryBackendImpl.h

    r128496 r128533  
    5858
    5959    virtual void getDatabaseNames(PassRefPtr<IDBCallbacks>, PassRefPtr<SecurityOrigin>, ScriptExecutionContext*, const String& dataDir);
    60     virtual void open(const String& name, int64_t version, PassRefPtr<IDBCallbacks>, PassRefPtr<SecurityOrigin>, ScriptExecutionContext*, const String& dataDir);
     60    virtual void open(const String& name, int64_t version, PassRefPtr<IDBCallbacks>, PassRefPtr<IDBDatabaseCallbacks>, PassRefPtr<SecurityOrigin>, ScriptExecutionContext*, const String& dataDir);
    6161    virtual void deleteDatabase(const String& name, PassRefPtr<IDBCallbacks>, PassRefPtr<SecurityOrigin>, ScriptExecutionContext*, const String& dataDir);
    6262
  • trunk/Source/WebCore/Modules/indexeddb/IDBFactoryBackendInterface.h

    r128496 r128533  
    2929#define IDBFactoryBackendInterface_h
    3030
    31 #include "IDBCallbacks.h"
     31#include <wtf/PassRefPtr.h>
    3232#include <wtf/Threading.h>
    33 #include <wtf/Vector.h>
    3433#include <wtf/text/WTFString.h>
    3534
     
    3837namespace WebCore {
    3938
    40 class Frame;
     39class IDBCallbacks;
    4140class IDBDatabase;
     41class IDBDatabaseCallbacks;
    4242class SecurityOrigin;
    43 class WorkerContext;
     43class ScriptExecutionContext;
    4444
    4545typedef int ExceptionCode;
     
    5555
    5656    virtual void getDatabaseNames(PassRefPtr<IDBCallbacks>, PassRefPtr<SecurityOrigin>, ScriptExecutionContext*, const String& dataDir) = 0;
    57     virtual void open(const String& name, int64_t version, PassRefPtr<IDBCallbacks>, PassRefPtr<SecurityOrigin>, ScriptExecutionContext*, const String& dataDir) = 0;
     57    virtual void open(const String& name, int64_t version, PassRefPtr<IDBCallbacks>, PassRefPtr<IDBDatabaseCallbacks>, PassRefPtr<SecurityOrigin>, ScriptExecutionContext*, const String& dataDir) = 0;
    5858    virtual void deleteDatabase(const String& name, PassRefPtr<IDBCallbacks>, PassRefPtr<SecurityOrigin>, ScriptExecutionContext*, const String& dataDir) = 0;
    5959};
  • trunk/Source/WebCore/Modules/indexeddb/IDBOpenDBRequest.cpp

    r128496 r128533  
    3030
    3131#include "IDBDatabase.h"
     32#include "IDBDatabaseCallbacksImpl.h"
    3233#include "IDBPendingTransactionMonitor.h"
    3334#include "IDBTracing.h"
     
    3738namespace WebCore {
    3839
    39 PassRefPtr<IDBOpenDBRequest> IDBOpenDBRequest::create(ScriptExecutionContext* context, PassRefPtr<IDBAny> source, int64_t version)
     40PassRefPtr<IDBOpenDBRequest> IDBOpenDBRequest::create(ScriptExecutionContext* context, PassRefPtr<IDBAny> source, PassRefPtr<IDBDatabaseCallbacksImpl> callbacks, int64_t version)
    4041{
    41     RefPtr<IDBOpenDBRequest> request(adoptRef(new IDBOpenDBRequest(context, source, version)));
     42    RefPtr<IDBOpenDBRequest> request(adoptRef(new IDBOpenDBRequest(context, source, callbacks, version)));
    4243    request->suspendIfNeeded();
    4344    return request.release();
    4445}
    4546
    46 IDBOpenDBRequest::IDBOpenDBRequest(ScriptExecutionContext* context, PassRefPtr<IDBAny> source, int64_t version)
     47IDBOpenDBRequest::IDBOpenDBRequest(ScriptExecutionContext* context, PassRefPtr<IDBAny> source, PassRefPtr<IDBDatabaseCallbacksImpl> callbacks, int64_t version)
    4748    : IDBRequest(context, source, IDBTransactionBackendInterface::NormalTask, 0)
     49    , m_databaseCallbacks(callbacks)
    4850    , m_version(version)
    4951{
     
    7375        return;
    7476
     77    ASSERT(m_databaseCallbacks);
     78
    7579    RefPtr<IDBDatabaseBackendInterface> databaseBackend = prpDatabaseBackend;
    7680    RefPtr<IDBTransactionBackendInterface> transactionBackend = prpTransactionBackend;
    77     RefPtr<IDBDatabase> idbDatabase = IDBDatabase::create(scriptExecutionContext(), databaseBackend);
     81    RefPtr<IDBDatabase> idbDatabase = IDBDatabase::create(scriptExecutionContext(), databaseBackend, m_databaseCallbacks);
     82    m_databaseCallbacks->connect(idbDatabase.get());
     83    m_databaseCallbacks = 0;
    7884
    7985    RefPtr<IDBTransaction> frontend = IDBTransaction::create(scriptExecutionContext(), transactionBackend, IDBTransaction::VERSION_CHANGE, idbDatabase.get(), this);
     
    99105        idbDatabase = m_result->idbDatabase();
    100106        ASSERT(idbDatabase);
     107        ASSERT(!m_databaseCallbacks);
    101108    } else {
    102         idbDatabase = IDBDatabase::create(scriptExecutionContext(), backend);
     109        ASSERT(m_databaseCallbacks);
     110        idbDatabase = IDBDatabase::create(scriptExecutionContext(), backend, m_databaseCallbacks);
     111        m_databaseCallbacks->connect(idbDatabase.get());
     112        m_databaseCallbacks = 0;
    103113        m_result = IDBAny::create(idbDatabase.get());
    104114    }
    105     idbDatabase->registerFrontendCallbacks();
    106115    enqueueEvent(Event::create(eventNames().successEvent, false, false));
    107116}
  • trunk/Source/WebCore/Modules/indexeddb/IDBOpenDBRequest.h

    r128496 r128533  
    3333namespace WebCore {
    3434
     35class IDBDatabaseCallbacksImpl;
     36
    3537class IDBOpenDBRequest : public IDBRequest {
    3638public:
    37     static PassRefPtr<IDBOpenDBRequest> create(ScriptExecutionContext*, PassRefPtr<IDBAny> source, int64_t version);
     39    static PassRefPtr<IDBOpenDBRequest> create(ScriptExecutionContext*, PassRefPtr<IDBAny> source, PassRefPtr<IDBDatabaseCallbacksImpl>, int64_t version);
    3840    virtual ~IDBOpenDBRequest();
    3941
     
    5456
    5557private:
    56     IDBOpenDBRequest(ScriptExecutionContext*, PassRefPtr<IDBAny> source, int64_t version);
     58    IDBOpenDBRequest(ScriptExecutionContext*, PassRefPtr<IDBAny> source, PassRefPtr<IDBDatabaseCallbacksImpl>, int64_t version);
    5759
     60    RefPtr<IDBDatabaseCallbacksImpl> m_databaseCallbacks;
    5861    int64_t m_version;
    5962};
  • trunk/Source/WebCore/Modules/indexeddb/IDBTransaction.cpp

    r128496 r128533  
    295295    m_objectStoreCleanupMap.clear();
    296296    closeOpenCursors();
     297
     298    // Enqueue events before notifying database, as database may close which enqueues more events and order matters.
     299    enqueueEvent(Event::create(eventNames().abortEvent, true, false));
    297300    m_database->transactionFinished(this);
    298 
    299     if (m_contextStopped || !scriptExecutionContext())
    300         return;
    301 
    302     enqueueEvent(Event::create(eventNames().abortEvent, true, false));
    303301}
    304302
     
    310308    m_objectStoreCleanupMap.clear();
    311309    closeOpenCursors();
     310
     311    // Enqueue events before notifying database, as database may close which enqueues more events and order matters.
     312    enqueueEvent(Event::create(eventNames().completeEvent, false, false));
    312313    m_database->transactionFinished(this);
    313 
    314     if (m_contextStopped || !scriptExecutionContext())
    315         return;
    316 
    317     enqueueEvent(Event::create(eventNames().completeEvent, false, false));
    318314}
    319315
  • trunk/Source/WebCore/inspector/InspectorIndexedDBAgent.cpp

    r128496 r128533  
    173173};
    174174
     175class DatabaseConnection {
     176public:
     177    DatabaseConnection()
     178        : m_idbDatabaseCallbacks(InspectorIDBDatabaseCallbacks::create()) { }
     179
     180    ~DatabaseConnection()
     181    {
     182        if (m_idbDatabase)
     183            m_idbDatabase->close(m_idbDatabaseCallbacks);
     184    }
     185
     186    void connect(PassRefPtr<IDBDatabaseBackendInterface> database) { m_idbDatabase = database; }
     187    PassRefPtr<IDBDatabaseCallbacks> callbacks() { return m_idbDatabaseCallbacks; }
     188
     189private:
     190    RefPtr<IDBDatabaseBackendInterface> m_idbDatabase;
     191    RefPtr<IDBDatabaseCallbacks> m_idbDatabaseCallbacks;
     192};
     193
    175194class ExecutableWithDatabase : public RefCounted<ExecutableWithDatabase> {
    176195public:
    177196    virtual ~ExecutableWithDatabase() { };
    178197    void start(IDBFactoryBackendInterface*, SecurityOrigin*, ScriptExecutionContext*, const String& databaseName);
     198    void connect(PassRefPtr<IDBDatabaseBackendInterface> database) { m_connection.connect(database); }
    179199    virtual void execute(PassRefPtr<IDBDatabaseBackendInterface>) = 0;
    180 };
    181 
    182 class DatabaseConnection {
    183 public:
    184     DatabaseConnection()
    185         : m_idbDatabaseCallbacks(InspectorIDBDatabaseCallbacks::create()) { }
    186 
    187     void connect(PassRefPtr<IDBDatabaseBackendInterface> idbDatabase)
    188     {
    189         m_idbDatabase = idbDatabase;
    190         m_idbDatabase->registerFrontendCallbacks(m_idbDatabaseCallbacks);
    191     }
    192 
    193     ~DatabaseConnection()
    194     {
    195         if (m_idbDatabase)
    196             m_idbDatabase->close(m_idbDatabaseCallbacks);
    197     }
    198 
    199 private:
    200     RefPtr<IDBDatabaseBackendInterface> m_idbDatabase;
    201     RefPtr<IDBDatabaseCallbacks> m_idbDatabaseCallbacks;
     200private:
     201    DatabaseConnection m_connection;
    202202};
    203203
     
    214214    {
    215215        RefPtr<IDBDatabaseBackendInterface> idbDatabase = prpDatabase;
     216        m_executableWithDatabase->connect(idbDatabase);
    216217        m_executableWithDatabase->execute(idbDatabase);
    217218    }
     
    226227{
    227228    RefPtr<OpenDatabaseCallback> callback = OpenDatabaseCallback::create(this);
    228     idbFactory->open(databaseName, IDBDatabaseMetadata::NoIntVersion, callback.get(), securityOrigin, context, String());
     229    idbFactory->open(databaseName, IDBDatabaseMetadata::NoIntVersion, callback, m_connection.callbacks(), securityOrigin, context, String());
    229230}
    230231
     
    297298    {
    298299        RefPtr<IDBDatabaseBackendInterface> idbDatabase = prpDatabase;
    299         m_connection.connect(idbDatabase);
    300300        if (!m_requestCallback->isActive())
    301301            return;
     
    340340        : m_requestCallback(requestCallback) { }
    341341    RefPtr<RequestDatabaseCallback> m_requestCallback;
    342     DatabaseConnection m_connection;
    343342};
    344343
     
    556555    {
    557556        RefPtr<IDBDatabaseBackendInterface> idbDatabase = prpDatabase;
    558         m_connection.connect(idbDatabase);
    559557        if (!m_requestCallback->isActive())
    560558            return;
     
    598596    int m_skipCount;
    599597    unsigned m_pageSize;
    600     DatabaseConnection m_connection;
    601598};
    602599
  • trunk/Source/WebKit/chromium/ChangeLog

    r128526 r128533  
     12012-09-13  Joshua Bell  <jsbell@chromium.org>
     2
     3        IndexedDB: Consolidate two-phase connection to avoid race conditions
     4        https://bugs.webkit.org/show_bug.cgi?id=90411
     5
     6        Reviewed by Tony Chang.
     7
     8        API plumbing for simplified single-phase connection opening, and tests updated
     9        to exercise the new APIs.
     10
     11        * public/WebIDBDatabase.h:
     12        (WebIDBDatabase): Just a FIXME to remove the old second-phase hookup API.
     13        * public/WebIDBFactory.h:
     14        (WebKit):
     15        (WebIDBFactory):
     16        (WebKit::WebIDBFactory::open): New overload that takes db-callbacks.
     17        * src/IDBCallbacksProxy.cpp: The db-callbacks plumbing is needed earlier.
     18        (WebKit::IDBCallbacksProxy::onSuccess):
     19        (WebKit::IDBCallbacksProxy::onUpgradeNeeded):
     20        (WebKit):
     21        (WebKit::IDBCallbacksProxy::setDatabaseCallbacks): Needs to hold on to
     22        the db-callbacks and hook it up when the onSuccess callback comes through.
     23        * src/IDBCallbacksProxy.h:
     24        (WebKit):
     25        (IDBCallbacksProxy):
     26        * src/IDBDatabaseBackendProxy.cpp:
     27        * src/IDBDatabaseBackendProxy.h:
     28        (IDBDatabaseBackendProxy):
     29        * src/IDBFactoryBackendProxy.cpp:
     30        (WebKit::IDBFactoryBackendProxy::open):
     31        * src/IDBFactoryBackendProxy.h:
     32        (IDBFactoryBackendProxy):
     33        * src/WebIDBDatabaseImpl.cpp:
     34        (WebKit::WebIDBDatabaseImpl::WebIDBDatabaseImpl):
     35        (WebKit::WebIDBDatabaseImpl::close):
     36        * src/WebIDBDatabaseImpl.h:
     37        (WebIDBDatabaseImpl):
     38        * src/WebIDBFactoryImpl.cpp:
     39        (WebKit::WebIDBFactoryImpl::open):
     40        * src/WebIDBFactoryImpl.h:
     41        (WebIDBFactoryImpl):
     42        * tests/IDBAbortOnCorruptTest.cpp:
     43        (FakeIDBDatabaseCallbacks):
     44        (WebCore::FakeIDBDatabaseCallbacks::create):
     45        (WebCore::FakeIDBDatabaseCallbacks::~FakeIDBDatabaseCallbacks):
     46        (WebCore::FakeIDBDatabaseCallbacks::FakeIDBDatabaseCallbacks):
     47        (WebCore):
     48        (WebCore::TEST): Updated connection sequence.
     49        * tests/IDBDatabaseBackendTest.cpp: Ditto.
     50
    1512012-09-13  James Robinson  <jamesr@chromium.org>
    252
  • trunk/Source/WebKit/chromium/public/WebIDBDatabase.h

    r128496 r128533  
    6767    virtual void forceClose() { WEBKIT_ASSERT_NOT_REACHED(); }
    6868
     69    // FIXME: Remove this method after WK90411 cleanup is complete on the Chromium side.
    6970    virtual void open(WebIDBDatabaseCallbacks*) { WEBKIT_ASSERT_NOT_REACHED(); }
    7071
  • trunk/Source/WebKit/chromium/public/WebIDBFactory.h

    r128496 r128533  
    5656    virtual void getDatabaseNames(WebIDBCallbacks* callbacks, const WebSecurityOrigin& origin, WebFrame* frame, const WebString& dataDir) { WEBKIT_ASSERT_NOT_REACHED(); }
    5757
    58     // FIXME: This overload should be removed when WK90411 lands.
     58    // FIXME: Remove this overload after WK90411 cleanup is complete on the Chromium side.
    5959    // The WebKit implementation of open ignores the WebFrame* parameter.
    6060    virtual void open(const WebString& name, long long version, WebIDBCallbacks* callbacks, const WebSecurityOrigin& origin, WebFrame* frame, const WebString& dataDir) { WEBKIT_ASSERT_NOT_REACHED(); }
  • trunk/Source/WebKit/chromium/src/IDBCallbacksProxy.cpp

    r128496 r128533  
    3535#include "IDBDatabaseBackendInterface.h"
    3636#include "IDBDatabaseBackendProxy.h"
     37#include "IDBDatabaseCallbacksProxy.h"
    3738#include "IDBDatabaseError.h"
    3839#include "IDBObjectStoreBackendInterface.h"
     
    4041#include "WebIDBCallbacks.h"
    4142#include "WebIDBCursorImpl.h"
     43#include "WebIDBDatabaseCallbacks.h"
     44#include "WebIDBDatabaseError.h"
    4245#include "WebIDBDatabaseImpl.h"
    43 #include "WebIDBDatabaseError.h"
    4446#include "WebIDBKey.h"
    4547#include "WebIDBTransactionImpl.h"
     
    7678void IDBCallbacksProxy::onSuccess(PassRefPtr<IDBDatabaseBackendInterface> backend)
    7779{
    78     m_callbacks->onSuccess(new WebIDBDatabaseImpl(backend));
     80    ASSERT(m_databaseCallbacks.get());
     81    m_callbacks->onSuccess(new WebIDBDatabaseImpl(backend, m_databaseCallbacks.release()));
    7982}
    8083
     
    138141void IDBCallbacksProxy::onUpgradeNeeded(int64_t oldVersion, PassRefPtr<IDBTransactionBackendInterface> transaction, PassRefPtr<IDBDatabaseBackendInterface> database)
    139142{
    140     m_callbacks->onUpgradeNeeded(oldVersion, new WebIDBTransactionImpl(transaction), new WebIDBDatabaseImpl(database));
     143    ASSERT(m_databaseCallbacks);
     144    m_callbacks->onUpgradeNeeded(oldVersion, new WebIDBTransactionImpl(transaction), new WebIDBDatabaseImpl(database, m_databaseCallbacks));
     145}
     146
     147void IDBCallbacksProxy::setDatabaseCallbacks(PassRefPtr<IDBDatabaseCallbacksProxy> databaseCallbacks)
     148{
     149    ASSERT(!m_databaseCallbacks);
     150    m_databaseCallbacks = databaseCallbacks;
    141151}
    142152
    143153} // namespace WebKit
    144154
     155
    145156#endif // ENABLE(INDEXED_DATABASE)
  • trunk/Source/WebKit/chromium/src/IDBCallbacksProxy.h

    r128496 r128533  
    4040
    4141class WebIDBCallbacks;
     42class IDBDatabaseCallbacksProxy;
    4243
    4344class IDBCallbacksProxy : public WebCore::IDBCallbacks {
     
    6061    virtual void onUpgradeNeeded(int64_t oldVersion, PassRefPtr<WebCore::IDBTransactionBackendInterface>, PassRefPtr<WebCore::IDBDatabaseBackendInterface>);
    6162
     63    void setDatabaseCallbacks(PassRefPtr<IDBDatabaseCallbacksProxy>);
     64
    6265private:
    6366    IDBCallbacksProxy(PassOwnPtr<WebIDBCallbacks>);
    6467
    6568    OwnPtr<WebIDBCallbacks> m_callbacks;
     69    RefPtr<IDBDatabaseCallbacksProxy> m_databaseCallbacks;
    6670};
    6771
  • trunk/Source/WebKit/chromium/src/IDBDatabaseBackendProxy.cpp

    r128496 r128533  
    108108}
    109109
    110 void IDBDatabaseBackendProxy::registerFrontendCallbacks(PassRefPtr<IDBDatabaseCallbacks> databaseCallbacks)
    111 {
    112     m_webIDBDatabase->open(new WebIDBDatabaseCallbacksImpl(databaseCallbacks));
    113 }
    114 
    115110} // namespace WebKit
    116111
  • trunk/Source/WebKit/chromium/src/IDBDatabaseBackendProxy.h

    r128496 r128533  
    5151    virtual void close(PassRefPtr<WebCore::IDBDatabaseCallbacks>);
    5252
    53     virtual void registerFrontendCallbacks(PassRefPtr<WebCore::IDBDatabaseCallbacks>);
    54 
    5553private:
    5654    IDBDatabaseBackendProxy(PassOwnPtr<WebIDBDatabase>);
  • trunk/Source/WebKit/chromium/src/IDBFactoryBackendProxy.cpp

    r128496 r128533  
    3535#include "DOMStringList.h"
    3636#include "IDBDatabaseBackendProxy.h"
     37#include "IDBDatabaseCallbacks.h"
    3738#include "IDBDatabaseError.h"
    3839#include "ScriptExecutionContext.h"
     
    4142#include "WebIDBCallbacksImpl.h"
    4243#include "WebIDBDatabase.h"
     44#include "WebIDBDatabaseCallbacksImpl.h"
    4345#include "WebIDBDatabaseError.h"
    4446#include "WebIDBFactory.h"
     
    204206
    205207
    206 void IDBFactoryBackendProxy::open(const String& name, int64_t version, PassRefPtr<IDBCallbacks> prpCallbacks, PassRefPtr<SecurityOrigin> securityOrigin, ScriptExecutionContext* context, const String& dataDir)
     208void IDBFactoryBackendProxy::open(const String& name, int64_t version, PassRefPtr<IDBCallbacks> prpCallbacks, PassRefPtr<IDBDatabaseCallbacks> prpDatabaseCallbacks, PassRefPtr<SecurityOrigin> securityOrigin, ScriptExecutionContext* context, const String& dataDir)
     209{
     210    RefPtr<IDBCallbacks> callbacks(prpCallbacks);
     211    RefPtr<IDBDatabaseCallbacks> databaseCallbacks(prpDatabaseCallbacks);
     212    WebSecurityOrigin origin(securityOrigin);
     213    if (!allowIndexedDB(context, name, origin, callbacks))
     214        return;
     215
     216    WebFrameImpl* webFrame = getWebFrame(context);
     217    m_webIDBFactory->open(name, version, new WebIDBCallbacksImpl(callbacks), new WebIDBDatabaseCallbacksImpl(databaseCallbacks), origin, webFrame, dataDir);
     218}
     219
     220void IDBFactoryBackendProxy::deleteDatabase(const String& name, PassRefPtr<IDBCallbacks> prpCallbacks, PassRefPtr<SecurityOrigin> securityOrigin, ScriptExecutionContext* context, const String& dataDir)
    207221{
    208222    RefPtr<IDBCallbacks> callbacks(prpCallbacks);
     
    212226
    213227    WebFrameImpl* webFrame = getWebFrame(context);
    214     m_webIDBFactory->open(name, version, new WebIDBCallbacksImpl(callbacks), origin, webFrame, dataDir);
    215 }
    216 
    217 void IDBFactoryBackendProxy::deleteDatabase(const String& name, PassRefPtr<IDBCallbacks> prpCallbacks, PassRefPtr<SecurityOrigin> securityOrigin, ScriptExecutionContext* context, const String& dataDir)
    218 {
    219     RefPtr<IDBCallbacks> callbacks(prpCallbacks);
    220     WebSecurityOrigin origin(securityOrigin);
    221     if (!allowIndexedDB(context, name, origin, callbacks))
    222         return;
    223 
    224     WebFrameImpl* webFrame = getWebFrame(context);
    225228    m_webIDBFactory->deleteDatabase(name, new WebIDBCallbacksImpl(callbacks), origin, webFrame, dataDir);
    226229}
  • trunk/Source/WebKit/chromium/src/IDBFactoryBackendProxy.h

    r128496 r128533  
    5050
    5151    virtual void getDatabaseNames(PassRefPtr<WebCore::IDBCallbacks>, PassRefPtr<WebCore::SecurityOrigin>, WebCore::ScriptExecutionContext*, const String& dataDir);
    52     virtual void open(const String& name, int64_t version, PassRefPtr<WebCore::IDBCallbacks>, PassRefPtr<WebCore::SecurityOrigin>, WebCore::ScriptExecutionContext*, const String& dataDir);
     52    virtual void open(const String& name, int64_t version, PassRefPtr<WebCore::IDBCallbacks>, PassRefPtr<WebCore::IDBDatabaseCallbacks>, PassRefPtr<WebCore::SecurityOrigin>, WebCore::ScriptExecutionContext*, const String& dataDir);
    5353    virtual void deleteDatabase(const String& name, PassRefPtr<WebCore::IDBCallbacks>, PassRefPtr<WebCore::SecurityOrigin>, WebCore::ScriptExecutionContext*, const String& dataDir);
    5454
  • trunk/Source/WebKit/chromium/src/WebIDBDatabaseImpl.cpp

    r128496 r128533  
    4646namespace WebKit {
    4747
    48 WebIDBDatabaseImpl::WebIDBDatabaseImpl(PassRefPtr<IDBDatabaseBackendInterface> databaseBackend)
     48WebIDBDatabaseImpl::WebIDBDatabaseImpl(PassRefPtr<IDBDatabaseBackendInterface> databaseBackend, WTF::PassRefPtr<IDBDatabaseCallbacksProxy> databaseCallbacks)
    4949    : m_databaseBackend(databaseBackend)
     50    , m_databaseCallbacks(databaseCallbacks)
    5051    , m_closePending(false)
    5152{
     
    9495void WebIDBDatabaseImpl::close()
    9596{
    96     // Use the callbacks that ::open gave us so that the backend in
     97    // Use the callbacks passed in to the constructor so that the backend in
    9798    // multi-process chromium knows which database connection is closing.
    9899    if (!m_databaseCallbacks) {
     
    114115}
    115116
    116 void WebIDBDatabaseImpl::open(WebIDBDatabaseCallbacks* callbacks)
    117 {
    118     ASSERT(!m_databaseCallbacks);
    119     m_databaseCallbacks = IDBDatabaseCallbacksProxy::create(adoptPtr(callbacks));
    120     m_databaseBackend->registerFrontendCallbacks(m_databaseCallbacks);
    121     if (m_closePending)
    122         close();
    123 }
    124 
    125117} // namespace WebKit
    126118
  • trunk/Source/WebKit/chromium/src/WebIDBDatabaseImpl.h

    r128496 r128533  
    4848class WebIDBDatabaseImpl : public WebIDBDatabase {
    4949public:
    50     WebIDBDatabaseImpl(WTF::PassRefPtr<WebCore::IDBDatabaseBackendInterface>);
     50    WebIDBDatabaseImpl(WTF::PassRefPtr<WebCore::IDBDatabaseBackendInterface>, WTF::PassRefPtr<IDBDatabaseCallbacksProxy>);
    5151    virtual ~WebIDBDatabaseImpl();
    5252
     
    5959    virtual void forceClose();
    6060    virtual void close();
    61 
    62     // FIXME: Rename "open" to registerFrontendCallbacks.
    63     virtual void open(WebIDBDatabaseCallbacks*);
    6461
    6562private:
  • trunk/Source/WebKit/chromium/src/WebIDBFactoryImpl.cpp

    r128496 r128533  
    3636#include "DOMStringList.h"
    3737#include "IDBCallbacksProxy.h"
     38#include "IDBDatabaseCallbacksProxy.h"
    3839#include "IDBFactoryBackendImpl.h"
    3940#include "SecurityOrigin.h"
     41#include "WebIDBDatabaseCallbacks.h"
    4042#include "WebIDBDatabaseError.h"
    4143#include <wtf/OwnPtr.h>
     
    6466}
    6567
    66 void WebIDBFactoryImpl::open(const WebString& name, long long version, WebIDBCallbacks* callbacks, const WebSecurityOrigin& origin, WebFrame*, const WebString& dataDir)
     68void WebIDBFactoryImpl::open(const WebString& name, long long version, WebIDBCallbacks* callbacks, WebIDBDatabaseCallbacks* databaseCallbacks, const WebSecurityOrigin& origin, WebFrame*, const WebString& dataDir)
    6769{
    68     m_idbFactoryBackend->open(name, version, IDBCallbacksProxy::create(adoptPtr(callbacks)).get(), origin, 0, dataDir);
     70    RefPtr<IDBCallbacksProxy> callbacksProxy = IDBCallbacksProxy::create(adoptPtr(callbacks));
     71    RefPtr<IDBDatabaseCallbacksProxy> databaseCallbacksProxy = IDBDatabaseCallbacksProxy::create(adoptPtr(databaseCallbacks));
     72    callbacksProxy->setDatabaseCallbacks(databaseCallbacksProxy);
     73    m_idbFactoryBackend->open(name, version, callbacksProxy.get(), databaseCallbacksProxy.get(), origin, 0, dataDir);
    6974}
    7075
  • trunk/Source/WebKit/chromium/src/WebIDBFactoryImpl.h

    r128496 r128533  
    4646
    4747    virtual void getDatabaseNames(WebIDBCallbacks*, const WebSecurityOrigin&, WebFrame*, const WebString& dataDir);
    48     virtual void open(const WebString& name, long long version, WebIDBCallbacks*, const WebSecurityOrigin&, WebFrame*, const WebString& dataDir);
     48    virtual void open(const WebString& name, long long version, WebIDBCallbacks*, WebIDBDatabaseCallbacks*, const WebSecurityOrigin&, WebFrame*, const WebString& dataDir);
    4949    virtual void deleteDatabase(const WebString& name, WebIDBCallbacks*, const WebSecurityOrigin&, WebFrame*, const WebString& dataDir);
    5050
  • trunk/Source/WebKit/chromium/tests/IDBAbortOnCorruptTest.cpp

    r128496 r128533  
    2727#include "IDBCursorBackendInterface.h"
    2828#include "IDBDatabaseBackendInterface.h"
     29#include "IDBDatabaseCallbacks.h"
    2930#include "IDBFactoryBackendImpl.h"
    3031#include "IDBFakeBackingStore.h"
     
    9798};
    9899
     100class FakeIDBDatabaseCallbacks : public IDBDatabaseCallbacks {
     101public:
     102    static PassRefPtr<FakeIDBDatabaseCallbacks> create() { return adoptRef(new FakeIDBDatabaseCallbacks()); }
     103    virtual ~FakeIDBDatabaseCallbacks() { }
     104    virtual void onVersionChange(const String& version) OVERRIDE { }
     105    virtual void onVersionChange(int64_t oldVersion, int64_t newVersion) OVERRIDE { }
     106    virtual void onForcedClose() OVERRIDE { }
     107private:
     108    FakeIDBDatabaseCallbacks() { }
     109};
     110
    99111TEST(IDBAbortTest, TheTest)
    100112{
     
    102114    const String& name = "db name";
    103115    MockIDBCallbacks callbacks;
     116    RefPtr<FakeIDBDatabaseCallbacks> databaseCallbacks = FakeIDBDatabaseCallbacks::create();
    104117    RefPtr<SecurityOrigin> origin = SecurityOrigin::create("http", "localhost", 81);
    105118    const int64_t DummyVersion = 2;
    106     factory->open(name, DummyVersion, &callbacks, origin, 0 /*Frame*/, String() /*path*/);
     119    factory->open(name, DummyVersion, &callbacks, databaseCallbacks, origin, 0 /*Frame*/, String() /*path*/);
    107120}
    108121
  • trunk/Source/WebKit/chromium/tests/IDBDatabaseBackendTest.cpp

    r128496 r128533  
    2828#include "IDBCursorBackendInterface.h"
    2929#include "IDBDatabaseBackendImpl.h"
     30#include "IDBDatabaseCallbacksProxy.h"
    3031#include "IDBFactoryBackendImpl.h"
    3132#include "IDBFakeBackingStore.h"
     
    4142
    4243using namespace WebCore;
     44using WebKit::IDBDatabaseCallbacksProxy;
    4345using WebKit::WebIDBDatabase;
     46using WebKit::WebIDBDatabaseImpl;
    4447using WebKit::WebIDBDatabaseCallbacksImpl;
    45 using WebKit::WebIDBDatabaseImpl;
    4648
    4749namespace {
     
    123125
    124126    RefPtr<MockIDBCallbacks> request1 = MockIDBCallbacks::create();
    125     db->openConnection(request1);
    126 
    127127    RefPtr<FakeIDBDatabaseCallbacks> connection1 = FakeIDBDatabaseCallbacks::create();
    128     db->registerFrontendCallbacks(connection1);
     128    db->openConnection(request1, connection1);
    129129
    130130    RefPtr<MockIDBCallbacks> request2 = MockIDBCallbacks::create();
    131     db->openConnection(request2);
     131    RefPtr<FakeIDBDatabaseCallbacks> connection2 = FakeIDBDatabaseCallbacks::create();
     132    db->openConnection(request2, connection2);
    132133
    133134    db->close(connection1);
    134135    EXPECT_GT(backingStore->refCount(), 1);
    135 
    136     RefPtr<FakeIDBDatabaseCallbacks> connection2 = FakeIDBDatabaseCallbacks::create();
    137     db->registerFrontendCallbacks(connection2);
    138136
    139137    db->close(connection2);
     
    150148    ~MockIDBDatabaseBackendProxy()
    151149    {
    152         EXPECT_TRUE(m_wasRegisterFrontendCallbacksCalled);
     150        EXPECT_TRUE(m_wasCloseCalled);
    153151    }
    154152
     
    164162        m_webDatabase.close();
    165163    }
    166     virtual void registerFrontendCallbacks(PassRefPtr<IDBDatabaseCallbacks> connection)
    167     {
    168         m_wasRegisterFrontendCallbacksCalled = true;
    169         m_webDatabase.open(new WebIDBDatabaseCallbacksImpl(connection));
    170     }
    171164
    172165private:
    173166    MockIDBDatabaseBackendProxy(WebIDBDatabaseImpl& webDatabase)
    174         : m_wasRegisterFrontendCallbacksCalled(false)
    175         , m_wasCloseCalled(false)
     167        : m_wasCloseCalled(false)
    176168        , m_webDatabase(webDatabase) { }
    177169
    178     bool m_wasRegisterFrontendCallbacksCalled;
    179170    bool m_wasCloseCalled;
    180171
     
    192183    EXPECT_GT(backingStore->refCount(), 1);
    193184
    194     WebIDBDatabaseImpl webDatabase(backend);
    195 
    196     RefPtr<MockIDBCallbacks> request1 = MockIDBCallbacks::create();
    197     backend->openConnection(request1);
     185    RefPtr<FakeIDBDatabaseCallbacks> connection = FakeIDBDatabaseCallbacks::create();
     186    RefPtr<IDBDatabaseCallbacksProxy> connectionProxy = IDBDatabaseCallbacksProxy::create(adoptPtr(new WebIDBDatabaseCallbacksImpl(connection)));
     187    WebIDBDatabaseImpl webDatabase(backend, connectionProxy);
    198188
    199189    RefPtr<MockIDBDatabaseBackendProxy> proxy = MockIDBDatabaseBackendProxy::create(webDatabase);
     190    RefPtr<MockIDBCallbacks> request = MockIDBCallbacks::create();
     191    backend->openConnection(request, connectionProxy);
    200192
    201193    ScriptExecutionContext* context = 0;
    202     RefPtr<IDBDatabase> idbDatabase = IDBDatabase::create(context, proxy);
    203     idbDatabase->registerFrontendCallbacks();
     194    RefPtr<IDBDatabase> idbDatabase = IDBDatabase::create(context, proxy, connection);
    204195
    205196    webDatabase.forceClose();
     197
    206198    EXPECT_TRUE(backingStore->hasOneRef());
    207199}
Note: See TracChangeset for help on using the changeset viewer.