1/* 2 * Copyright (C) 2007, 2008, 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 * 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of Apple Inc. ("Apple") nor the names of 14 * its contributors may be used to endorse or promote products derived 15 * from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28#include "config.h" 29#include "DatabaseTask.h" 30 31#if ENABLE(SQL_DATABASE) 32 33#include "Database.h" 34#include "DatabaseBackend.h" 35#include "Logging.h" 36 37namespace WebCore { 38 39DatabaseTaskSynchronizer::DatabaseTaskSynchronizer() 40 : m_taskCompleted(false) 41#ifndef NDEBUG 42 , m_hasCheckedForTermination(false) 43#endif 44{ 45} 46 47void DatabaseTaskSynchronizer::waitForTaskCompletion() 48{ 49 m_synchronousMutex.lock(); 50 while (!m_taskCompleted) 51 m_synchronousCondition.wait(m_synchronousMutex); 52 m_synchronousMutex.unlock(); 53} 54 55void DatabaseTaskSynchronizer::taskCompleted() 56{ 57 m_synchronousMutex.lock(); 58 m_taskCompleted = true; 59 m_synchronousCondition.signal(); 60 m_synchronousMutex.unlock(); 61} 62 63DatabaseTask::DatabaseTask(DatabaseBackend* database, DatabaseTaskSynchronizer* synchronizer) 64 : m_database(database) 65 , m_synchronizer(synchronizer) 66#if !LOG_DISABLED 67 , m_complete(false) 68#endif 69{ 70} 71 72DatabaseTask::~DatabaseTask() 73{ 74#if !LOG_DISABLED 75 ASSERT(m_complete || !m_synchronizer); 76#endif 77} 78 79void DatabaseTask::performTask() 80{ 81 // Database tasks are meant to be used only once, so make sure this one hasn't been performed before. 82#if !LOG_DISABLED 83 ASSERT(!m_complete); 84#endif 85 86 LOG(StorageAPI, "Performing %s %p\n", debugTaskName(), this); 87 88#if !PLATFORM(IOS) 89 m_database->resetAuthorizer(); 90#else 91 if (m_database) 92 m_database->resetAuthorizer(); 93#endif 94 95 doPerformTask(); 96 97 if (m_synchronizer) 98 m_synchronizer->taskCompleted(); 99 100#if !LOG_DISABLED 101 m_complete = true; 102#endif 103} 104 105// *** DatabaseOpenTask *** 106// Opens the database file and verifies the version matches the expected version. 107 108DatabaseBackend::DatabaseOpenTask::DatabaseOpenTask(DatabaseBackend* database, bool setVersionInNewDatabase, DatabaseTaskSynchronizer* synchronizer, DatabaseError& error, String& errorMessage, bool& success) 109 : DatabaseTask(database, synchronizer) 110 , m_setVersionInNewDatabase(setVersionInNewDatabase) 111 , m_error(error) 112 , m_errorMessage(errorMessage) 113 , m_success(success) 114{ 115 ASSERT(synchronizer); // A task with output parameters is supposed to be synchronous. 116} 117 118void DatabaseBackend::DatabaseOpenTask::doPerformTask() 119{ 120 String errorMessage; 121 m_success = database()->performOpenAndVerify(m_setVersionInNewDatabase, m_error, errorMessage); 122 if (!m_success) 123 m_errorMessage = errorMessage.isolatedCopy(); 124} 125 126#if !LOG_DISABLED 127const char* DatabaseBackend::DatabaseOpenTask::debugTaskName() const 128{ 129 return "DatabaseOpenTask"; 130} 131#endif 132 133// *** DatabaseCloseTask *** 134// Closes the database. 135 136DatabaseBackend::DatabaseCloseTask::DatabaseCloseTask(DatabaseBackend* database, DatabaseTaskSynchronizer* synchronizer) 137 : DatabaseTask(database, synchronizer) 138{ 139} 140 141void DatabaseBackend::DatabaseCloseTask::doPerformTask() 142{ 143 Database::from(database())->close(); 144} 145 146#if !LOG_DISABLED 147const char* DatabaseBackend::DatabaseCloseTask::debugTaskName() const 148{ 149 return "DatabaseCloseTask"; 150} 151#endif 152 153// *** DatabaseTransactionTask *** 154// Starts a transaction that will report its results via a callback. 155 156DatabaseBackend::DatabaseTransactionTask::DatabaseTransactionTask(PassRefPtr<SQLTransactionBackend> transaction) 157 : DatabaseTask(Database::from(transaction->database()), 0) 158 , m_transaction(transaction) 159 , m_didPerformTask(false) 160{ 161} 162 163DatabaseBackend::DatabaseTransactionTask::~DatabaseTransactionTask() 164{ 165 // If the task is being destructed without the transaction ever being run, 166 // then we must either have an error or an interruption. Give the 167 // transaction a chance to clean up since it may not have been able to 168 // run to its clean up state. 169 170 // Transaction phase 2 cleanup. See comment on "What happens if a 171 // transaction is interrupted?" at the top of SQLTransactionBackend.cpp. 172 173 if (!m_didPerformTask) 174 m_transaction->notifyDatabaseThreadIsShuttingDown(); 175} 176 177#if PLATFORM(IOS) 178bool Database::DatabaseTransactionTask::shouldPerformWhilePaused() const 179{ 180 return m_transaction->shouldPerformWhilePaused(); 181} 182#endif 183 184void DatabaseBackend::DatabaseTransactionTask::doPerformTask() 185{ 186 m_transaction->performNextStep(); 187 m_didPerformTask = true; 188} 189 190#if !LOG_DISABLED 191const char* DatabaseBackend::DatabaseTransactionTask::debugTaskName() const 192{ 193 return "DatabaseTransactionTask"; 194} 195#endif 196 197// *** DatabaseTableNamesTask *** 198// Retrieves a list of all tables in the database - for WebInspector support. 199 200DatabaseBackend::DatabaseTableNamesTask::DatabaseTableNamesTask(DatabaseBackend* database, DatabaseTaskSynchronizer* synchronizer, Vector<String>& names) 201 : DatabaseTask(database, synchronizer) 202 , m_tableNames(names) 203{ 204 ASSERT(synchronizer); // A task with output parameters is supposed to be synchronous. 205} 206 207void DatabaseBackend::DatabaseTableNamesTask::doPerformTask() 208{ 209 m_tableNames = Database::from(database())->performGetTableNames(); 210} 211 212#if !LOG_DISABLED 213const char* DatabaseBackend::DatabaseTableNamesTask::debugTaskName() const 214{ 215 return "DatabaseTableNamesTask"; 216} 217#endif 218 219} // namespace WebCore 220 221#endif 222