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 Computer, 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 "modules/webdatabase/DatabaseTask.h" 30 31 #include "platform/Logging.h" 32 #include "modules/webdatabase/Database.h" 33 #include "modules/webdatabase/DatabaseContext.h" 34 #include "modules/webdatabase/DatabaseThread.h" 35 36 namespace WebCore { 37 38 DatabaseTaskSynchronizer::DatabaseTaskSynchronizer() 39 : m_taskCompleted(false) 40 #ifndef NDEBUG 41 , m_hasCheckedForTermination(false) 42 #endif 43 { 44 } 45 46 void DatabaseTaskSynchronizer::waitForTaskCompletion() 47 { 48 m_synchronousMutex.lock(); 49 while (!m_taskCompleted) 50 m_synchronousCondition.wait(m_synchronousMutex); 51 m_synchronousMutex.unlock(); 52 } 53 54 void DatabaseTaskSynchronizer::taskCompleted() 55 { 56 m_synchronousMutex.lock(); 57 m_taskCompleted = true; 58 m_synchronousCondition.signal(); 59 m_synchronousMutex.unlock(); 60 } 61 62 DatabaseTask::DatabaseTask(DatabaseBackend* database, DatabaseTaskSynchronizer* synchronizer) 63 : m_database(database) 64 , m_synchronizer(synchronizer) 65 #if !LOG_DISABLED 66 , m_complete(false) 67 #endif 68 { 69 } 70 71 DatabaseTask::~DatabaseTask() 72 { 73 #if !LOG_DISABLED 74 ASSERT(m_complete || !m_synchronizer); 75 #endif 76 } 77 78 void DatabaseTask::run() 79 { 80 // Database tasks are meant to be used only once, so make sure this one hasn't been performed before. 81 #if !LOG_DISABLED 82 ASSERT(!m_complete); 83 #endif 84 85 if (!m_synchronizer && !m_database->databaseContext()->databaseThread()->isDatabaseOpen(m_database.get())) { 86 taskCancelled(); 87 #if !LOG_DISABLED 88 m_complete = true; 89 #endif 90 return; 91 } 92 93 WTF_LOG(StorageAPI, "Performing %s %p\n", debugTaskName(), this); 94 95 m_database->resetAuthorizer(); 96 doPerformTask(); 97 98 if (m_synchronizer) 99 m_synchronizer->taskCompleted(); 100 101 #if !LOG_DISABLED 102 m_complete = true; 103 #endif 104 } 105 106 // *** DatabaseOpenTask *** 107 // Opens the database file and verifies the version matches the expected version. 108 109 DatabaseBackend::DatabaseOpenTask::DatabaseOpenTask(DatabaseBackend* database, bool setVersionInNewDatabase, DatabaseTaskSynchronizer* synchronizer, DatabaseError& error, String& errorMessage, bool& success) 110 : DatabaseTask(database, synchronizer) 111 , m_setVersionInNewDatabase(setVersionInNewDatabase) 112 , m_error(error) 113 , m_errorMessage(errorMessage) 114 , m_success(success) 115 { 116 ASSERT(synchronizer); // A task with output parameters is supposed to be synchronous. 117 } 118 119 void DatabaseBackend::DatabaseOpenTask::doPerformTask() 120 { 121 String errorMessage; 122 m_success = database()->performOpenAndVerify(m_setVersionInNewDatabase, m_error, errorMessage); 123 if (!m_success) 124 m_errorMessage = errorMessage.isolatedCopy(); 125 } 126 127 #if !LOG_DISABLED 128 const char* DatabaseBackend::DatabaseOpenTask::debugTaskName() const 129 { 130 return "DatabaseOpenTask"; 131 } 132 #endif 133 134 // *** DatabaseCloseTask *** 135 // Closes the database. 136 137 DatabaseBackend::DatabaseCloseTask::DatabaseCloseTask(DatabaseBackend* database, DatabaseTaskSynchronizer* synchronizer) 138 : DatabaseTask(database, synchronizer) 139 { 140 } 141 142 void DatabaseBackend::DatabaseCloseTask::doPerformTask() 143 { 144 Database::from(database())->close(); 145 } 146 147 #if !LOG_DISABLED 148 const char* DatabaseBackend::DatabaseCloseTask::debugTaskName() const 149 { 150 return "DatabaseCloseTask"; 151 } 152 #endif 153 154 // *** DatabaseTransactionTask *** 155 // Starts a transaction that will report its results via a callback. 156 157 DatabaseBackend::DatabaseTransactionTask::DatabaseTransactionTask(PassRefPtr<SQLTransactionBackend> transaction) 158 : DatabaseTask(Database::from(transaction->database()), 0) 159 , m_transaction(transaction) 160 { 161 } 162 163 DatabaseBackend::DatabaseTransactionTask::~DatabaseTransactionTask() 164 { 165 } 166 167 void DatabaseBackend::DatabaseTransactionTask::doPerformTask() 168 { 169 m_transaction->performNextStep(); 170 } 171 172 void DatabaseBackend::DatabaseTransactionTask::taskCancelled() 173 { 174 // If the task is being destructed without the transaction ever being run, 175 // then we must either have an error or an interruption. Give the 176 // transaction a chance to clean up since it may not have been able to 177 // run to its clean up state. 178 179 // Transaction phase 2 cleanup. See comment on "What happens if a 180 // transaction is interrupted?" at the top of SQLTransactionBackend.cpp. 181 182 m_transaction->notifyDatabaseThreadIsShuttingDown(); 183 } 184 185 #if !LOG_DISABLED 186 const char* DatabaseBackend::DatabaseTransactionTask::debugTaskName() const 187 { 188 return "DatabaseTransactionTask"; 189 } 190 #endif 191 192 // *** DatabaseTableNamesTask *** 193 // Retrieves a list of all tables in the database - for WebInspector support. 194 195 DatabaseBackend::DatabaseTableNamesTask::DatabaseTableNamesTask(DatabaseBackend* database, DatabaseTaskSynchronizer* synchronizer, Vector<String>& names) 196 : DatabaseTask(database, synchronizer) 197 , m_tableNames(names) 198 { 199 ASSERT(synchronizer); // A task with output parameters is supposed to be synchronous. 200 } 201 202 void DatabaseBackend::DatabaseTableNamesTask::doPerformTask() 203 { 204 m_tableNames = Database::from(database())->performGetTableNames(); 205 } 206 207 #if !LOG_DISABLED 208 const char* DatabaseBackend::DatabaseTableNamesTask::debugTaskName() const 209 { 210 return "DatabaseTableNamesTask"; 211 } 212 #endif 213 214 } // namespace WebCore 215