From cad810f21b803229eb11403f9209855525a25d57 Mon Sep 17 00:00:00 2001 From: Steve Block Date: Fri, 6 May 2011 11:45:16 +0100 Subject: Merge WebKit at r75315: Initial merge by git. Change-Id: I570314b346ce101c935ed22a626b48c2af266b84 --- Source/WebCore/storage/SQLTransactionSync.cpp | 212 ++++++++++++++++++++++++++ 1 file changed, 212 insertions(+) create mode 100644 Source/WebCore/storage/SQLTransactionSync.cpp (limited to 'Source/WebCore/storage/SQLTransactionSync.cpp') diff --git a/Source/WebCore/storage/SQLTransactionSync.cpp b/Source/WebCore/storage/SQLTransactionSync.cpp new file mode 100644 index 0000000..97a5cc5 --- /dev/null +++ b/Source/WebCore/storage/SQLTransactionSync.cpp @@ -0,0 +1,212 @@ +/* + * 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: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT + * OWNER OR 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 "SQLTransactionSync.h" + +#if ENABLE(DATABASE) + +#include "DatabaseAuthorizer.h" +#include "DatabaseSync.h" +#include "PlatformString.h" +#include "SQLException.h" +#include "SQLResultSet.h" +#include "SQLStatementSync.h" +#include "SQLTransactionClient.h" +#include "SQLTransactionSyncCallback.h" +#include "SQLValue.h" +#include "SQLiteTransaction.h" +#include "ScriptExecutionContext.h" +#include +#include + +namespace WebCore { + +PassRefPtr SQLTransactionSync::create(DatabaseSync* db, PassRefPtr callback, bool readOnly) +{ + return adoptRef(new SQLTransactionSync(db, callback, readOnly)); +} + +SQLTransactionSync::SQLTransactionSync(DatabaseSync* db, PassRefPtr callback, bool readOnly) + : m_database(db) + , m_callback(callback) + , m_readOnly(readOnly) + , m_modifiedDatabase(false) + , m_transactionClient(adoptPtr(new SQLTransactionClient())) +{ + ASSERT(m_database->scriptExecutionContext()->isContextThread()); +} + +SQLTransactionSync::~SQLTransactionSync() +{ + ASSERT(m_database->scriptExecutionContext()->isContextThread()); + if (m_sqliteTransaction && m_sqliteTransaction->inProgress()) + rollback(); +} + +PassRefPtr SQLTransactionSync::executeSQL(const String& sqlStatement, const Vector& arguments, ExceptionCode& ec) +{ + ASSERT(m_database->scriptExecutionContext()->isContextThread()); + if (!m_database->opened()) { + ec = SQLException::UNKNOWN_ERR; + return 0; + } + + if (!m_database->versionMatchesExpected()) { + ec = SQLException::VERSION_ERR; + return 0; + } + + if (sqlStatement.isEmpty()) + return 0; + + int permissions = DatabaseAuthorizer::ReadWriteMask; + if (!m_database->scriptExecutionContext()->allowDatabaseAccess()) + permissions |= DatabaseAuthorizer::NoAccessMask; + else if (m_readOnly) + permissions |= DatabaseAuthorizer::ReadOnlyMask; + + SQLStatementSync statement(sqlStatement, arguments, permissions); + + m_database->resetAuthorizer(); + bool retryStatement = true; + RefPtr resultSet; + while (retryStatement) { + retryStatement = false; + resultSet = statement.execute(m_database.get(), ec); + if (!resultSet) { + if (m_sqliteTransaction->wasRolledBackBySqlite()) + return 0; + + if (ec == SQLException::QUOTA_ERR) { + if (m_transactionClient->didExceedQuota(database())) { + ec = 0; + retryStatement = true; + } else + return 0; + } + } + } + + if (m_database->lastActionChangedDatabase()) { + m_modifiedDatabase = true; + m_transactionClient->didExecuteStatement(database()); + } + + return resultSet.release(); +} + +ExceptionCode SQLTransactionSync::begin() +{ + ASSERT(m_database->scriptExecutionContext()->isContextThread()); + if (!m_database->opened()) + return SQLException::UNKNOWN_ERR; + + ASSERT(!m_database->sqliteDatabase().transactionInProgress()); + + // Set the maximum usage for this transaction if this transactions is not read-only. + if (!m_readOnly) + m_database->sqliteDatabase().setMaximumSize(m_database->maximumSize()); + + ASSERT(!m_sqliteTransaction); + m_sqliteTransaction = adoptPtr(new SQLiteTransaction(m_database->sqliteDatabase(), m_readOnly)); + + m_database->resetDeletes(); + m_database->disableAuthorizer(); + m_sqliteTransaction->begin(); + m_database->enableAuthorizer(); + + // Check if begin() succeeded. + if (!m_sqliteTransaction->inProgress()) { + ASSERT(!m_database->sqliteDatabase().transactionInProgress()); + m_sqliteTransaction.clear(); + return SQLException::DATABASE_ERR; + } + + return 0; +} + +ExceptionCode SQLTransactionSync::execute() +{ + ASSERT(m_database->scriptExecutionContext()->isContextThread()); + if (!m_database->opened() || (m_callback && !m_callback->handleEvent(this))) { + m_callback = 0; + return SQLException::UNKNOWN_ERR; + } + + m_callback = 0; + return 0; +} + +ExceptionCode SQLTransactionSync::commit() +{ + ASSERT(m_database->scriptExecutionContext()->isContextThread()); + if (!m_database->opened()) + return SQLException::UNKNOWN_ERR; + + ASSERT(m_sqliteTransaction); + + m_database->disableAuthorizer(); + m_sqliteTransaction->commit(); + m_database->enableAuthorizer(); + + // If the commit failed, the transaction will still be marked as "in progress" + if (m_sqliteTransaction->inProgress()) + return SQLException::DATABASE_ERR; + + m_sqliteTransaction.clear(); + + // Vacuum the database if anything was deleted. + if (m_database->hadDeletes()) + m_database->incrementalVacuumIfNeeded(); + + // The commit was successful. If the transaction modified this database, notify the delegates. + if (m_modifiedDatabase) + m_transactionClient->didCommitWriteTransaction(database()); + + return 0; +} + +void SQLTransactionSync::rollback() +{ + ASSERT(m_database->scriptExecutionContext()->isContextThread()); + m_database->disableAuthorizer(); + if (m_sqliteTransaction) { + m_sqliteTransaction->rollback(); + m_sqliteTransaction.clear(); + } + m_database->enableAuthorizer(); + + ASSERT(!m_database->sqliteDatabase().transactionInProgress()); +} + +} // namespace WebCore + +#endif // ENABLE(DATABASE) -- cgit v1.1