1/* 2 * Copyright (C) 2013 Apple Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 23 * THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25#include "config.h" 26#include "SQLiteIDBTransaction.h" 27 28#if ENABLE(INDEXED_DATABASE) && ENABLE(DATABASE_PROCESS) 29 30#include "SQLiteIDBCursor.h" 31#include "UniqueIDBDatabaseBackingStoreSQLite.h" 32#include <WebCore/IndexedDB.h> 33#include <WebCore/SQLiteTransaction.h> 34 35using namespace WebCore; 36 37static int64_t nextCursorID = 1; 38 39namespace WebKit { 40 41SQLiteIDBTransaction::SQLiteIDBTransaction(UniqueIDBDatabaseBackingStoreSQLite& backingStore, const IDBIdentifier& transactionIdentifier, IndexedDB::TransactionMode mode) 42 : m_identifier(transactionIdentifier) 43 , m_mode(mode) 44 , m_backingStore(backingStore) 45{ 46} 47 48SQLiteIDBTransaction::~SQLiteIDBTransaction() 49{ 50 if (inProgress()) 51 m_sqliteTransaction->rollback(); 52 53 // Explicitly clear cursors, as that also unregisters them from the backing store. 54 clearCursors(); 55} 56 57 58bool SQLiteIDBTransaction::begin(SQLiteDatabase& database) 59{ 60 ASSERT(!m_sqliteTransaction); 61 m_sqliteTransaction = std::make_unique<SQLiteTransaction>(database, m_mode == IndexedDB::TransactionMode::ReadOnly); 62 63 m_sqliteTransaction->begin(); 64 65 return m_sqliteTransaction->inProgress(); 66} 67 68bool SQLiteIDBTransaction::commit() 69{ 70 // It's okay to not have a SQLite transaction or not have started it yet because it's okay for a WebProcess 71 // to request the commit of a transaction immediately after creating it before it has even been used. 72 if (!m_sqliteTransaction || !m_sqliteTransaction->inProgress()) 73 return false; 74 75 m_sqliteTransaction->commit(); 76 77 return !m_sqliteTransaction->inProgress(); 78} 79 80bool SQLiteIDBTransaction::reset() 81{ 82 m_sqliteTransaction = nullptr; 83 clearCursors(); 84 85 return true; 86} 87 88bool SQLiteIDBTransaction::rollback() 89{ 90 ASSERT(m_sqliteTransaction); 91 if (m_sqliteTransaction->inProgress()) 92 m_sqliteTransaction->rollback(); 93 94 return true; 95} 96 97SQLiteIDBCursor* SQLiteIDBTransaction::openCursor(int64_t objectStoreID, int64_t indexID, IndexedDB::CursorDirection cursorDirection, IndexedDB::CursorType cursorType, IDBDatabaseBackend::TaskType taskType, const IDBKeyRangeData& keyRange) 98{ 99 ASSERT(m_sqliteTransaction); 100 if (!m_sqliteTransaction->inProgress()) 101 return nullptr; 102 103 IDBIdentifier cursorIdentifier(m_identifier.connection(), nextCursorID++); 104 105 auto addResult = m_cursors.add(cursorIdentifier, SQLiteIDBCursor::maybeCreate(this, cursorIdentifier, objectStoreID, indexID, cursorDirection, cursorType, taskType, keyRange)); 106 107 ASSERT(addResult.isNewEntry); 108 109 // It is possible the cursor failed to create and we just stored a null value. 110 if (!addResult.iterator->value) { 111 m_cursors.remove(addResult.iterator); 112 return nullptr; 113 } 114 115 return addResult.iterator->value.get(); 116} 117 118void SQLiteIDBTransaction::closeCursor(SQLiteIDBCursor& cursor) 119{ 120 ASSERT(m_cursors.contains(cursor.identifier())); 121 122 m_backingStore.unregisterCursor(&cursor); 123 m_cursors.remove(cursor.identifier()); 124} 125 126void SQLiteIDBTransaction::notifyCursorsOfChanges(int64_t objectStoreID) 127{ 128 for (auto& i : m_cursors) { 129 if (i.value->objectStoreID() == objectStoreID) 130 i.value->objectStoreRecordsChanged(); 131 } 132} 133 134void SQLiteIDBTransaction::clearCursors() 135{ 136 for (auto& cursor : m_cursors.values()) 137 m_backingStore.unregisterCursor(cursor.get()); 138 139 m_cursors.clear(); 140} 141 142bool SQLiteIDBTransaction::inProgress() const 143{ 144 return m_sqliteTransaction && m_sqliteTransaction->inProgress(); 145} 146 147} // namespace WebKit 148 149#endif // ENABLE(INDEXED_DATABASE) && ENABLE(DATABASE_PROCESS) 150