Changeset 141316 in webkit


Ignore:
Timestamp:
Jan 30, 2013 2:39:41 PM (11 years ago)
Author:
alecflett@chromium.org
Message:

IndexedDB: Avoid crashing when deleting indexes
https://bugs.webkit.org/show_bug.cgi?id=108356

Reviewed by Tony Chang.

Source/WebCore:

It is reasonable that the backend aborts a transaction before
the frontend is aware, depending on the timing of events. This
allows the transactionId to be invalid rather than asserting.

Test: storage/indexeddb/createIndex-after-failure.html

  • Modules/indexeddb/IDBDatabaseBackendImpl.cpp:

(WebCore::IDBDatabaseBackendImpl::createObjectStore):
(WebCore::IDBDatabaseBackendImpl::deleteObjectStore):
(WebCore::IDBDatabaseBackendImpl::createIndex):
(WebCore::IDBDatabaseBackendImpl::deleteIndex):
(WebCore::IDBDatabaseBackendImpl::get):
(WebCore::IDBDatabaseBackendImpl::put):
(WebCore::IDBDatabaseBackendImpl::setIndexKeys):
(WebCore::IDBDatabaseBackendImpl::setIndexesReady):
(WebCore::IDBDatabaseBackendImpl::openCursor):
(WebCore::IDBDatabaseBackendImpl::count):
(WebCore::IDBDatabaseBackendImpl::deleteRange):
(WebCore::IDBDatabaseBackendImpl::clear):

LayoutTests:

This test works on an edge case around the asynchronous
creation/deletion of indexes that used to crash. It doesn't fail/crash even
without this patch but was the test condition that uncovered the overall problem
before https://bugs.webkit.org/show_bug.cgi?id=107311 changed the timing of
some of the events.

  • storage/indexeddb/createIndex-after-failure.html: Added.
  • storage/indexeddb/resources/createIndex-after-failure.js: Added.

(sleep):
(prepareDatabase):
(deleteIndexAfterGet):

  • storage/indexeddb/resources/shared.js:

(.requests.forEach):
(waitForRequests):

  • storage/indexeddb/createIndex-after-failure.html: Added.
  • storage/indexeddb/resources/createIndex-after-failure.js: Added.

(prepareDatabase):
(deleteIndexAfterGet):

  • storage/indexeddb/resources/shared.js:

(.requests.forEach):
(waitForRequests):

Location:
trunk
Files:
3 added
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r141311 r141316  
     12013-01-30  Alec Flett  <alecflett@chromium.org>
     2
     3        IndexedDB: Avoid crashing when deleting indexes
     4        https://bugs.webkit.org/show_bug.cgi?id=108356
     5
     6        Reviewed by Tony Chang.
     7
     8        This test works on an edge case around the asynchronous
     9        creation/deletion of indexes that used to crash. It doesn't fail/crash even
     10        without this patch but was the test condition that uncovered the overall problem
     11        before https://bugs.webkit.org/show_bug.cgi?id=107311 changed the timing of
     12        some of the events.
     13
     14        * storage/indexeddb/createIndex-after-failure.html: Added.
     15        * storage/indexeddb/resources/createIndex-after-failure.js: Added.
     16        (sleep):
     17        (prepareDatabase):
     18        (deleteIndexAfterGet):
     19        * storage/indexeddb/resources/shared.js:
     20        (.requests.forEach):
     21        (waitForRequests):
     22
     23        * storage/indexeddb/createIndex-after-failure.html: Added.
     24        * storage/indexeddb/resources/createIndex-after-failure.js: Added.
     25        (prepareDatabase):
     26        (deleteIndexAfterGet):
     27        * storage/indexeddb/resources/shared.js:
     28        (.requests.forEach):
     29        (waitForRequests):
     30
    1312013-01-30  Philip Rogers  <pdr@google.com>
    232
  • trunk/LayoutTests/storage/indexeddb/resources/shared.js

    r137635 r141316  
    205205    };
    206206}
     207
     208function waitForRequests(requests, callback) {
     209    var count = requests.length;
     210
     211    if (!count) {
     212        callback(requests);
     213        return;
     214    }
     215
     216    requests.forEach(function(req) {
     217        req.onsuccess = function() {
     218            --count;
     219            if (!count)
     220                callback(requests);
     221        };
     222        req.onerror = unexpectedErrorCallback;
     223    });
     224}
  • trunk/Source/WebCore/ChangeLog

    r141315 r141316  
     12013-01-30  Alec Flett  <alecflett@chromium.org>
     2
     3        IndexedDB: Avoid crashing when deleting indexes
     4        https://bugs.webkit.org/show_bug.cgi?id=108356
     5
     6        Reviewed by Tony Chang.
     7
     8        It is reasonable that the backend aborts a transaction before
     9        the frontend is aware, depending on the timing of events. This
     10        allows the transactionId to be invalid rather than asserting.
     11
     12        Test: storage/indexeddb/createIndex-after-failure.html
     13
     14        * Modules/indexeddb/IDBDatabaseBackendImpl.cpp:
     15        (WebCore::IDBDatabaseBackendImpl::createObjectStore):
     16        (WebCore::IDBDatabaseBackendImpl::deleteObjectStore):
     17        (WebCore::IDBDatabaseBackendImpl::createIndex):
     18        (WebCore::IDBDatabaseBackendImpl::deleteIndex):
     19        (WebCore::IDBDatabaseBackendImpl::get):
     20        (WebCore::IDBDatabaseBackendImpl::put):
     21        (WebCore::IDBDatabaseBackendImpl::setIndexKeys):
     22        (WebCore::IDBDatabaseBackendImpl::setIndexesReady):
     23        (WebCore::IDBDatabaseBackendImpl::openCursor):
     24        (WebCore::IDBDatabaseBackendImpl::count):
     25        (WebCore::IDBDatabaseBackendImpl::deleteRange):
     26        (WebCore::IDBDatabaseBackendImpl::clear):
     27
    1282013-01-30  Kentaro Hara  <haraken@chromium.org>
    229
  • trunk/Source/WebCore/Modules/indexeddb/IDBDatabaseBackendImpl.cpp

    r141142 r141316  
    557557{
    558558    IDB_TRACE("IDBDatabaseBackendImpl::createObjectStore");
     559    IDBTransactionBackendImpl* transaction = m_transactions.get(transactionId);
     560    if (!transaction)
     561        return;
     562    ASSERT(transaction->mode() == IDBTransaction::VERSION_CHANGE);
     563
    559564    ASSERT(!m_metadata.objectStores.contains(objectStoreId));
    560 
    561     ASSERT(m_transactions.contains(transactionId));
    562     IDBTransactionBackendImpl* transaction = m_transactions.get(transactionId);
    563 
    564565    IDBObjectStoreMetadata objectStoreMetadata(name, objectStoreId, keyPath, autoIncrement, IDBDatabaseBackendInterface::MinimumIndexId);
    565566
     
    582583{
    583584    IDB_TRACE("IDBDatabaseBackendImpl::deleteObjectStore");
     585    IDBTransactionBackendImpl* transaction = m_transactions.get(transactionId);
     586    if (!transaction)
     587        return;
     588    ASSERT(transaction->mode() == IDBTransaction::VERSION_CHANGE);
     589
    584590    ASSERT(m_metadata.objectStores.contains(objectStoreId));
    585591    const IDBObjectStoreMetadata& objectStoreMetadata = m_metadata.objectStores.get(objectStoreId);
    586592
    587     ASSERT(m_transactions.contains(transactionId));
    588     IDBTransactionBackendImpl* transaction = m_transactions.get(transactionId);
    589     ASSERT(transaction->mode() == IDBTransaction::VERSION_CHANGE);
    590 
    591593    transaction->scheduleTask(DeleteObjectStoreOperation::create(m_backingStore, objectStoreMetadata),  DeleteObjectStoreAbortOperation::create(this, objectStoreMetadata));
    592594    removeObjectStore(objectStoreId);
     
    596598{
    597599    IDB_TRACE("IDBDatabaseBackendImpl::createIndex");
     600    IDBTransactionBackendImpl* transaction = m_transactions.get(transactionId);
     601    if (!transaction)
     602        return;
     603    ASSERT(transaction->mode() == IDBTransaction::VERSION_CHANGE);
     604
    598605    ASSERT(m_metadata.objectStores.contains(objectStoreId));
    599606    const IDBObjectStoreMetadata objectStore = m_metadata.objectStores.get(objectStoreId);
     
    602609    const IDBIndexMetadata indexMetadata(name, indexId, keyPath, unique, multiEntry);
    603610
    604     ASSERT(m_transactions.contains(transactionId));
    605     IDBTransactionBackendImpl* transaction = m_transactions.get(transactionId);
    606     ASSERT(transaction->mode() == IDBTransaction::VERSION_CHANGE);
    607 
    608611    transaction->scheduleTask(CreateIndexOperation::create(m_backingStore, objectStoreId, indexMetadata), CreateIndexAbortOperation::create(this, objectStoreId, indexId));
    609612
    610613    addIndex(objectStoreId, indexMetadata, indexId);
    611614}
    612 
    613615
    614616void CreateIndexOperation::perform(IDBTransactionBackendImpl* transaction)
     
    631633{
    632634    IDB_TRACE("IDBDatabaseBackendImpl::deleteIndex");
     635    IDBTransactionBackendImpl* transaction = m_transactions.get(transactionId);
     636    if (!transaction)
     637        return;
     638    ASSERT(transaction->mode() == IDBTransaction::VERSION_CHANGE);
     639
    633640    ASSERT(m_metadata.objectStores.contains(objectStoreId));
    634641    const IDBObjectStoreMetadata objectStore = m_metadata.objectStores.get(objectStoreId);
     
    636643    ASSERT(objectStore.indexes.contains(indexId));
    637644    const IDBIndexMetadata& indexMetadata = objectStore.indexes.get(indexId);
    638 
    639     ASSERT(m_transactions.contains(transactionId));
    640     IDBTransactionBackendImpl* transaction = m_transactions.get(transactionId);
    641     ASSERT(transaction->mode() == IDBTransaction::VERSION_CHANGE);
    642645
    643646    transaction->scheduleTask(DeleteIndexOperation::create(m_backingStore, objectStoreId, indexId), DeleteIndexAbortOperation::create(this, objectStoreId, indexMetadata));
     
    683686{
    684687    IDB_TRACE("IDBDatabaseBackendImpl::get");
    685     ASSERT(m_transactions.contains(transactionId));
    686688    IDBTransactionBackendImpl* transaction = m_transactions.get(transactionId);
     689    if (!transaction)
     690        return;
    687691
    688692    transaction->scheduleTask(GetOperation::create(m_backingStore, m_metadata, objectStoreId, indexId, keyRange, keyOnly ? IDBCursorBackendInterface::KeyOnly : IDBCursorBackendInterface::KeyAndValue, callbacks));
     
    780784{
    781785    IDB_TRACE("IDBDatabaseBackendImpl::put");
    782 
    783     ASSERT(m_transactions.contains(transactionId));
    784786    IDBTransactionBackendImpl* transaction = m_transactions.get(transactionId);
     787    if (!transaction)
     788        return;
    785789    ASSERT(transaction->mode() != IDBTransaction::READ_ONLY);
    786790
     
    863867}
    864868
    865 
    866869void IDBDatabaseBackendImpl::setIndexKeys(int64_t transactionId, int64_t objectStoreId, PassRefPtr<IDBKey> prpPrimaryKey, const Vector<int64_t>& indexIds, const Vector<IndexKeys>& indexKeys)
    867870{
    868871    IDB_TRACE("IDBDatabaseBackendImpl::setIndexKeys");
    869     if (!m_transactions.contains(transactionId))
    870         return;
    871 
    872872    IDBTransactionBackendImpl* transaction = m_transactions.get(transactionId);
    873     if (transaction->isFinished())
    874         return;
     873    if (!transaction || transaction->isFinished())
     874        return;
     875    ASSERT(transaction->mode() == IDBTransaction::VERSION_CHANGE);
    875876
    876877    RefPtr<IDBKey> primaryKey = prpPrimaryKey;
     
    915916    IDB_TRACE("IDBObjectStoreBackendImpl::setIndexesReady");
    916917
    917     if (!m_transactions.contains(transactionId))
    918         return;
    919 
    920918    IDBTransactionBackendImpl* transaction = m_transactions.get(transactionId);
    921     if (transaction->isFinished())
     919    if (!transaction || transaction->isFinished())
    922920        return;
    923921
     
    936934{
    937935    IDB_TRACE("IDBDatabaseBackendImpl::openCursor");
    938     ASSERT(m_transactions.contains(transactionId));
    939936    IDBTransactionBackendImpl* transaction = m_transactions.get(transactionId);
     937    if (!transaction)
     938        return;
    940939
    941940    transaction->scheduleTask(OpenCursorOperation::create(m_backingStore, id(), objectStoreId, indexId, keyRange, direction, keyOnly ? IDBCursorBackendInterface::KeyOnly : IDBCursorBackendInterface::KeyAndValue, taskType, callbacks));
     
    979978{
    980979    IDB_TRACE("IDBDatabaseBackendImpl::count");
    981     ASSERT(m_transactions.contains(transactionId));
    982980    IDBTransactionBackendImpl* transaction = m_transactions.get(transactionId);
     981    if (!transaction)
     982        return;
     983
    983984    ASSERT(m_metadata.objectStores.contains(objectStoreId));
    984985    transaction->scheduleTask(CountOperation::create(m_backingStore, id(), objectStoreId, indexId, keyRange, callbacks));
     
    10101011{
    10111012    IDB_TRACE("IDBDatabaseBackendImpl::deleteRange");
    1012 
    1013     ASSERT(m_transactions.contains(transactionId));
    10141013    IDBTransactionBackendImpl* transaction = m_transactions.get(transactionId);
     1014    if (!transaction)
     1015        return;
    10151016    ASSERT(transaction->mode() != IDBTransaction::READ_ONLY);
    10161017
     
    10341035{
    10351036    IDB_TRACE("IDBDatabaseBackendImpl::clear");
    1036 
    1037     ASSERT(m_transactions.contains(transactionId));
    10381037    IDBTransactionBackendImpl* transaction = m_transactions.get(transactionId);
     1038    if (!transaction)
     1039        return;
    10391040    ASSERT(transaction->mode() != IDBTransaction::READ_ONLY);
    10401041
Note: See TracChangeset for help on using the changeset viewer.