1316f1de7e65935528cdf2fda15632fa240a9e3a
[WebKit-https.git] / Source / WebCore / Modules / webdatabase / Database.cpp
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
29 #include "config.h"
30 #include "Database.h"
31
32 #include "ChangeVersionData.h"
33 #include "ChangeVersionWrapper.h"
34 #include "DOMWindow.h"
35 #include "DatabaseAuthorizer.h"
36 #include "DatabaseCallback.h"
37 #include "DatabaseContext.h"
38 #include "DatabaseManager.h"
39 #include "DatabaseTask.h"
40 #include "DatabaseThread.h"
41 #include "DatabaseTracker.h"
42 #include "Document.h"
43 #include "JSDOMWindow.h"
44 #include "Logging.h"
45 #include "Page.h"
46 #include "SQLError.h"
47 #include "SQLTransaction.h"
48 #include "SQLTransactionCallback.h"
49 #include "SQLTransactionErrorCallback.h"
50 #include "SQLiteDatabaseTracker.h"
51 #include "SQLiteStatement.h"
52 #include "SQLiteTransaction.h"
53 #include "ScriptExecutionContext.h"
54 #include "SecurityOrigin.h"
55 #include "VoidCallback.h"
56 #include <wtf/NeverDestroyed.h>
57 #include <wtf/RefPtr.h>
58 #include <wtf/StdLibExtras.h>
59 #include <wtf/text/CString.h>
60
61 namespace WebCore {
62
63 // Registering "opened" databases with the DatabaseTracker
64 // =======================================================
65 // The DatabaseTracker maintains a list of databases that have been
66 // "opened" so that the client can call interrupt or delete on every database
67 // associated with a DatabaseContext.
68 //
69 // We will only call DatabaseTracker::addOpenDatabase() to add the database
70 // to the tracker as opened when we've succeeded in opening the database,
71 // and will set m_opened to true. Similarly, we only call
72 // DatabaseTracker::removeOpenDatabase() to remove the database from the
73 // tracker when we set m_opened to false in closeDatabase(). This sets up
74 // a simple symmetry between open and close operations, and a direct
75 // correlation to adding and removing databases from the tracker's list,
76 // thus ensuring that we have a correct list for the interrupt and
77 // delete operations to work on.
78 //
79 // The only databases instances not tracked by the tracker's open database
80 // list are the ones that have not been added yet, or the ones that we
81 // attempted an open on but failed to. Such instances only exist in the
82 // DatabaseServer's factory methods for creating database backends.
83 //
84 // The factory methods will either call openAndVerifyVersion() or
85 // performOpenAndVerify(). These methods will add the newly instantiated
86 // database backend if they succeed in opening the requested database.
87 // In the case of failure to open the database, the factory methods will
88 // simply discard the newly instantiated database backend when they return.
89 // The ref counting mechanims will automatically destruct the un-added
90 // (and un-returned) databases instances.
91
92 static const char versionKey[] = "WebKitDatabaseVersionKey";
93 static const char unqualifiedInfoTableName[] = "__WebKitDatabaseInfoTable__";
94
95 static const char* fullyQualifiedInfoTableName()
96 {
97     static const char qualifier[] = "main.";
98     static char qualifiedName[sizeof(qualifier) + sizeof(unqualifiedInfoTableName) - 1];
99
100     static std::once_flag onceFlag;
101     std::call_once(onceFlag, [] {
102         strcpy(qualifiedName, qualifier);
103         strcpy(qualifiedName + sizeof(qualifier) - 1, unqualifiedInfoTableName);
104     });
105
106     return qualifiedName;
107 }
108
109 static String formatErrorMessage(const char* message, int sqliteErrorCode, const char* sqliteErrorMessage)
110 {
111     return String::format("%s (%d %s)", message, sqliteErrorCode, sqliteErrorMessage);
112 }
113
114 static bool setTextValueInDatabase(SQLiteDatabase& db, const String& query, const String& value)
115 {
116     SQLiteStatement statement(db, query);
117     int result = statement.prepare();
118
119     if (result != SQLITE_OK) {
120         LOG_ERROR("Failed to prepare statement to set value in database (%s)", query.ascii().data());
121         return false;
122     }
123
124     statement.bindText(1, value);
125
126     result = statement.step();
127     if (result != SQLITE_DONE) {
128         LOG_ERROR("Failed to step statement to set value in database (%s)", query.ascii().data());
129         return false;
130     }
131
132     return true;
133 }
134
135 static bool retrieveTextResultFromDatabase(SQLiteDatabase& db, const String& query, String& resultString)
136 {
137     SQLiteStatement statement(db, query);
138     int result = statement.prepare();
139
140     if (result != SQLITE_OK) {
141         LOG_ERROR("Error (%i) preparing statement to read text result from database (%s)", result, query.ascii().data());
142         return false;
143     }
144
145     result = statement.step();
146     if (result == SQLITE_ROW) {
147         resultString = statement.getColumnText(0);
148         return true;
149     }
150     if (result == SQLITE_DONE) {
151         resultString = String();
152         return true;
153     }
154
155     LOG_ERROR("Error (%i) reading text result from database (%s)", result, query.ascii().data());
156     return false;
157 }
158
159 // FIXME: move all guid-related functions to a DatabaseVersionTracker class.
160 static StaticLock guidMutex;
161
162 typedef HashMap<DatabaseGuid, String> GuidVersionMap;
163 static GuidVersionMap& guidToVersionMap()
164 {
165     static NeverDestroyed<GuidVersionMap> map;
166     return map;
167 }
168
169 // NOTE: Caller must lock guidMutex().
170 static inline void updateGuidVersionMap(DatabaseGuid guid, String newVersion)
171 {
172     // Note: It is not safe to put an empty string into the guidToVersionMap() map.
173     // That's because the map is cross-thread, but empty strings are per-thread.
174     // The copy() function makes a version of the string you can use on the current
175     // thread, but we need a string we can keep in a cross-thread data structure.
176     // FIXME: This is a quite-awkward restriction to have to program with.
177
178     // Map null string to empty string (see comment above).
179     guidToVersionMap().set(guid, newVersion.isEmpty() ? String() : newVersion.isolatedCopy());
180 }
181
182 typedef HashMap<DatabaseGuid, std::unique_ptr<HashSet<Database*>>> GuidDatabaseMap;
183
184 static GuidDatabaseMap& guidToDatabaseMap()
185 {
186     static NeverDestroyed<GuidDatabaseMap> map;
187     return map;
188 }
189
190 static DatabaseGuid guidForOriginAndName(const String& origin, const String& name)
191 {
192     String stringID = origin + "/" + name;
193
194     static NeverDestroyed<HashMap<String, int>> map;
195     DatabaseGuid guid = map.get().get(stringID);
196     if (!guid) {
197         static int currentNewGUID = 1;
198         guid = currentNewGUID++;
199         map.get().set(stringID, guid);
200     }
201
202     return guid;
203 }
204
205 Database::Database(RefPtr<DatabaseContext>&& databaseContext, const String& name, const String& expectedVersion, const String& displayName, unsigned long estimatedSize)
206     : m_scriptExecutionContext(databaseContext->scriptExecutionContext())
207     , m_databaseContext(WTFMove(databaseContext))
208     , m_deleted(false)
209     , m_name(name.isolatedCopy())
210     , m_expectedVersion(expectedVersion.isolatedCopy())
211     , m_displayName(displayName.isolatedCopy())
212     , m_estimatedSize(estimatedSize)
213     , m_opened(false)
214     , m_new(false)
215     , m_transactionInProgress(false)
216     , m_isTransactionQueueEnabled(true)
217 {
218     m_contextThreadSecurityOrigin = m_databaseContext->securityOrigin()->isolatedCopy();
219
220     m_databaseAuthorizer = DatabaseAuthorizer::create(unqualifiedInfoTableName);
221
222     if (m_name.isNull())
223         m_name = emptyString();
224
225     {
226         std::lock_guard<StaticLock> locker(guidMutex);
227
228         m_guid = guidForOriginAndName(securityOrigin()->toString(), name);
229         std::unique_ptr<HashSet<Database*>>& hashSet = guidToDatabaseMap().add(m_guid, nullptr).iterator->value;
230         if (!hashSet)
231             hashSet = std::make_unique<HashSet<Database*>>();
232         hashSet->add(this);
233     }
234
235     m_filename = DatabaseManager::singleton().fullPathForDatabase(securityOrigin(), m_name);
236
237     m_databaseThreadSecurityOrigin = m_contextThreadSecurityOrigin->isolatedCopy();
238
239     ASSERT(m_databaseContext->databaseThread());
240 }
241
242 Database::~Database()
243 {
244     // The reference to the ScriptExecutionContext needs to be cleared on the JavaScript thread.  If we're on that thread already, we can just let the RefPtr's destruction do the dereffing.
245     if (!m_scriptExecutionContext->isContextThread()) {
246         // Grab a pointer to the script execution here because we're releasing it when we pass it to
247         // DerefContextTask::create.
248         RefPtr<ScriptExecutionContext> passedContext = WTFMove(m_scriptExecutionContext);
249         passedContext->postTask({ScriptExecutionContext::Task::CleanupTask, [passedContext] (ScriptExecutionContext& context) {
250             ASSERT_UNUSED(context, &context == passedContext);
251             RefPtr<ScriptExecutionContext> scriptExecutionContext(passedContext);
252         }});
253     }
254
255     // SQLite is "multi-thread safe", but each database handle can only be used
256     // on a single thread at a time.
257     //
258     // For DatabaseBackend, we open the SQLite database on the DatabaseThread,
259     // and hence we should also close it on that same thread. This means that the
260     // SQLite database need to be closed by another mechanism (see
261     // DatabaseContext::stopDatabases()). By the time we get here, the SQLite
262     // database should have already been closed.
263
264     ASSERT(!m_opened);
265 }
266
267 bool Database::openAndVerifyVersion(bool setVersionInNewDatabase, DatabaseError& error, String& errorMessage)
268 {
269     DatabaseTaskSynchronizer synchronizer;
270     if (!databaseContext()->databaseThread() || databaseContext()->databaseThread()->terminationRequested(&synchronizer))
271         return false;
272
273     bool success = false;
274     auto task = std::make_unique<DatabaseOpenTask>(*this, setVersionInNewDatabase, synchronizer, error, errorMessage, success);
275     databaseContext()->databaseThread()->scheduleImmediateTask(WTFMove(task));
276     synchronizer.waitForTaskCompletion();
277
278     return success;
279 }
280
281 void Database::interrupt()
282 {
283     // It is safe to call this from any thread for an opened or closed database.
284     m_sqliteDatabase.interrupt();
285 }
286
287 void Database::close()
288 {
289     if (!databaseContext()->databaseThread())
290         return;
291
292     DatabaseTaskSynchronizer synchronizer;
293     if (databaseContext()->databaseThread()->terminationRequested(&synchronizer)) {
294         LOG(StorageAPI, "Database handle %p is on a terminated DatabaseThread, cannot be marked for normal closure\n", this);
295         return;
296     }
297
298     databaseContext()->databaseThread()->scheduleImmediateTask(std::make_unique<DatabaseCloseTask>(*this, synchronizer));
299
300     // FIXME: iOS depends on this function blocking until the database is closed as part
301     // of closing all open databases from a process assertion expiration handler.
302     // See <https://bugs.webkit.org/show_bug.cgi?id=157184>.
303     synchronizer.waitForTaskCompletion();
304 }
305
306 void Database::performClose()
307 {
308     ASSERT(databaseContext()->databaseThread());
309     ASSERT(currentThread() == databaseContext()->databaseThread()->getThreadID());
310
311     {
312         LockHolder locker(m_transactionInProgressMutex);
313
314         // Clean up transactions that have not been scheduled yet:
315         // Transaction phase 1 cleanup. See comment on "What happens if a
316         // transaction is interrupted?" at the top of SQLTransactionBackend.cpp.
317         RefPtr<SQLTransactionBackend> transaction;
318         while (!m_transactionQueue.isEmpty()) {
319             transaction = m_transactionQueue.takeFirst();
320             transaction->notifyDatabaseThreadIsShuttingDown();
321         }
322
323         m_isTransactionQueueEnabled = false;
324         m_transactionInProgress = false;
325     }
326
327     closeDatabase();
328
329     // DatabaseThread keeps databases alive by referencing them in its
330     // m_openDatabaseSet. DatabaseThread::recordDatabaseClose() will remove
331     // this database from that set (which effectively deref's it). We hold on
332     // to it with a local pointer here for a liitle longer, so that we can
333     // unschedule any DatabaseTasks that refer to it before the database gets
334     // deleted.
335     Ref<Database> protectedThis(*this);
336     databaseContext()->databaseThread()->recordDatabaseClosed(this);
337     databaseContext()->databaseThread()->unscheduleDatabaseTasks(this);
338 }
339
340 class DoneCreatingDatabaseOnExitCaller {
341 public:
342     DoneCreatingDatabaseOnExitCaller(Database* database)
343         : m_database(database)
344         , m_openSucceeded(false)
345     {
346     }
347     ~DoneCreatingDatabaseOnExitCaller()
348     {
349         DatabaseTracker::tracker().doneCreatingDatabase(m_database);
350     }
351
352     void setOpenSucceeded() { m_openSucceeded = true; }
353
354 private:
355     Database* m_database;
356     bool m_openSucceeded;
357 };
358
359 bool Database::performOpenAndVerify(bool shouldSetVersionInNewDatabase, DatabaseError& error, String& errorMessage)
360 {
361     DoneCreatingDatabaseOnExitCaller onExitCaller(this);
362     ASSERT(errorMessage.isEmpty());
363     ASSERT(error == DatabaseError::None); // Better not have any errors already.
364     error = DatabaseError::InvalidDatabaseState; // Presumed failure. We'll clear it if we succeed below.
365
366     const int maxSqliteBusyWaitTime = 30000;
367
368 #if PLATFORM(IOS)
369     {
370         // Make sure we wait till the background removal of the empty database files finished before trying to open any database.
371         LockHolder locker(DatabaseTracker::openDatabaseMutex());
372     }
373 #endif
374
375     SQLiteTransactionInProgressAutoCounter transactionCounter;
376
377     if (!m_sqliteDatabase.open(m_filename, true)) {
378         errorMessage = formatErrorMessage("unable to open database", m_sqliteDatabase.lastError(), m_sqliteDatabase.lastErrorMsg());
379         return false;
380     }
381     if (!m_sqliteDatabase.turnOnIncrementalAutoVacuum())
382         LOG_ERROR("Unable to turn on incremental auto-vacuum (%d %s)", m_sqliteDatabase.lastError(), m_sqliteDatabase.lastErrorMsg());
383
384     m_sqliteDatabase.setBusyTimeout(maxSqliteBusyWaitTime);
385
386     String currentVersion;
387     {
388         std::lock_guard<StaticLock> locker(guidMutex);
389
390         auto entry = guidToVersionMap().find(m_guid);
391         if (entry != guidToVersionMap().end()) {
392             // Map null string to empty string (see updateGuidVersionMap()).
393             currentVersion = entry->value.isNull() ? emptyString() : entry->value.isolatedCopy();
394             LOG(StorageAPI, "Current cached version for guid %i is %s", m_guid, currentVersion.ascii().data());
395         } else {
396             LOG(StorageAPI, "No cached version for guid %i", m_guid);
397
398             SQLiteTransaction transaction(m_sqliteDatabase);
399             transaction.begin();
400             if (!transaction.inProgress()) {
401                 errorMessage = formatErrorMessage("unable to open database, failed to start transaction", m_sqliteDatabase.lastError(), m_sqliteDatabase.lastErrorMsg());
402                 m_sqliteDatabase.close();
403                 return false;
404             }
405
406             String tableName(unqualifiedInfoTableName);
407             if (!m_sqliteDatabase.tableExists(tableName)) {
408                 m_new = true;
409
410                 if (!m_sqliteDatabase.executeCommand("CREATE TABLE " + tableName + " (key TEXT NOT NULL ON CONFLICT FAIL UNIQUE ON CONFLICT REPLACE,value TEXT NOT NULL ON CONFLICT FAIL);")) {
411                     errorMessage = formatErrorMessage("unable to open database, failed to create 'info' table", m_sqliteDatabase.lastError(), m_sqliteDatabase.lastErrorMsg());
412                     transaction.rollback();
413                     m_sqliteDatabase.close();
414                     return false;
415                 }
416             } else if (!getVersionFromDatabase(currentVersion, false)) {
417                 errorMessage = formatErrorMessage("unable to open database, failed to read current version", m_sqliteDatabase.lastError(), m_sqliteDatabase.lastErrorMsg());
418                 transaction.rollback();
419                 m_sqliteDatabase.close();
420                 return false;
421             }
422
423             if (currentVersion.length()) {
424                 LOG(StorageAPI, "Retrieved current version %s from database %s", currentVersion.ascii().data(), databaseDebugName().ascii().data());
425             } else if (!m_new || shouldSetVersionInNewDatabase) {
426                 LOG(StorageAPI, "Setting version %s in database %s that was just created", m_expectedVersion.ascii().data(), databaseDebugName().ascii().data());
427                 if (!setVersionInDatabase(m_expectedVersion, false)) {
428                     errorMessage = formatErrorMessage("unable to open database, failed to write current version", m_sqliteDatabase.lastError(), m_sqliteDatabase.lastErrorMsg());
429                     transaction.rollback();
430                     m_sqliteDatabase.close();
431                     return false;
432                 }
433                 currentVersion = m_expectedVersion;
434             }
435             updateGuidVersionMap(m_guid, currentVersion);
436             transaction.commit();
437         }
438     }
439
440     if (currentVersion.isNull()) {
441         LOG(StorageAPI, "Database %s does not have its version set", databaseDebugName().ascii().data());
442         currentVersion = emptyString();
443     }
444
445     // If the expected version isn't the empty string, ensure that the current database version we have matches that version. Otherwise, set an exception.
446     // If the expected version is the empty string, then we always return with whatever version of the database we have.
447     if ((!m_new || shouldSetVersionInNewDatabase) && m_expectedVersion.length() && m_expectedVersion != currentVersion) {
448         errorMessage = "unable to open database, version mismatch, '" + m_expectedVersion + "' does not match the currentVersion of '" + currentVersion + "'";
449         m_sqliteDatabase.close();
450         return false;
451     }
452
453     ASSERT(m_databaseAuthorizer);
454     m_sqliteDatabase.setAuthorizer(m_databaseAuthorizer);
455
456     // See comment at the top this file regarding calling addOpenDatabase().
457     DatabaseTracker::tracker().addOpenDatabase(static_cast<Database*>(this));
458     m_opened = true;
459
460     // Declare success:
461     error = DatabaseError::None; // Clear the presumed error from above.
462     onExitCaller.setOpenSucceeded();
463
464     if (m_new && !shouldSetVersionInNewDatabase)
465         m_expectedVersion = emptyString(); // The caller provided a creationCallback which will set the expected version.
466
467     if (databaseContext()->databaseThread())
468         databaseContext()->databaseThread()->recordDatabaseOpen(this);
469
470     return true;
471 }
472
473 void Database::closeDatabase()
474 {
475     if (!m_opened)
476         return;
477
478     m_sqliteDatabase.close();
479     m_opened = false;
480     // See comment at the top this file regarding calling removeOpenDatabase().
481     DatabaseTracker::tracker().removeOpenDatabase(this);
482     {
483         std::lock_guard<StaticLock> locker(guidMutex);
484
485         auto it = guidToDatabaseMap().find(m_guid);
486         ASSERT(it != guidToDatabaseMap().end());
487         ASSERT(it->value);
488         ASSERT(it->value->contains(this));
489         it->value->remove(this);
490         if (it->value->isEmpty()) {
491             guidToDatabaseMap().remove(it);
492             guidToVersionMap().remove(m_guid);
493         }
494     }
495 }
496
497 bool Database::getVersionFromDatabase(String& version, bool shouldCacheVersion)
498 {
499     String query(String("SELECT value FROM ") + fullyQualifiedInfoTableName() +  " WHERE key = '" + versionKey + "';");
500
501     m_databaseAuthorizer->disable();
502
503     bool result = retrieveTextResultFromDatabase(m_sqliteDatabase, query, version);
504     if (result) {
505         if (shouldCacheVersion)
506             setCachedVersion(version);
507     } else
508         LOG_ERROR("Failed to retrieve version from database %s", databaseDebugName().ascii().data());
509
510     m_databaseAuthorizer->enable();
511
512     return result;
513 }
514
515 bool Database::setVersionInDatabase(const String& version, bool shouldCacheVersion)
516 {
517     // The INSERT will replace an existing entry for the database with the new version number, due to the UNIQUE ON CONFLICT REPLACE
518     // clause in the CREATE statement (see Database::performOpenAndVerify()).
519     String query(String("INSERT INTO ") + fullyQualifiedInfoTableName() +  " (key, value) VALUES ('" + versionKey + "', ?);");
520
521     m_databaseAuthorizer->disable();
522
523     bool result = setTextValueInDatabase(m_sqliteDatabase, query, version);
524     if (result) {
525         if (shouldCacheVersion)
526             setCachedVersion(version);
527     } else
528         LOG_ERROR("Failed to set version %s in database (%s)", version.ascii().data(), query.ascii().data());
529
530     m_databaseAuthorizer->enable();
531
532     return result;
533 }
534
535 void Database::setExpectedVersion(const String& version)
536 {
537     m_expectedVersion = version.isolatedCopy();
538 }
539
540 String Database::getCachedVersion() const
541 {
542     std::lock_guard<StaticLock> locker(guidMutex);
543
544     return guidToVersionMap().get(m_guid).isolatedCopy();
545 }
546
547 void Database::setCachedVersion(const String& actualVersion)
548 {
549     // Update the in memory database version map.
550     std::lock_guard<StaticLock> locker(guidMutex);
551
552     updateGuidVersionMap(m_guid, actualVersion);
553 }
554
555 bool Database::getActualVersionForTransaction(String &actualVersion)
556 {
557     ASSERT(m_sqliteDatabase.transactionInProgress());
558
559     // Note: In multi-process browsers the cached value may be inaccurate.
560     // So we retrieve the value from the database and update the cached value here.
561     return getVersionFromDatabase(actualVersion, true);
562 }
563
564 void Database::scheduleTransaction()
565 {
566     ASSERT(!m_transactionInProgressMutex.tryLock()); // Locked by caller.
567     RefPtr<SQLTransactionBackend> transaction;
568
569     if (m_isTransactionQueueEnabled && !m_transactionQueue.isEmpty())
570         transaction = m_transactionQueue.takeFirst();
571
572     if (transaction && databaseContext()->databaseThread()) {
573         auto task = std::make_unique<DatabaseTransactionTask>(WTFMove(transaction));
574         LOG(StorageAPI, "Scheduling DatabaseTransactionTask %p for transaction %p\n", task.get(), task->transaction());
575         m_transactionInProgress = true;
576         databaseContext()->databaseThread()->scheduleTask(WTFMove(task));
577     } else
578         m_transactionInProgress = false;
579 }
580
581 RefPtr<SQLTransactionBackend> Database::runTransaction(Ref<SQLTransaction>&& transaction, bool readOnly, const ChangeVersionData* data)
582 {
583     LockHolder locker(m_transactionInProgressMutex);
584     if (!m_isTransactionQueueEnabled)
585         return nullptr;
586
587     RefPtr<SQLTransactionWrapper> wrapper;
588     if (data)
589         wrapper = ChangeVersionWrapper::create(data->oldVersion(), data->newVersion());
590
591     RefPtr<SQLTransactionBackend> transactionBackend = SQLTransactionBackend::create(this, WTFMove(transaction), WTFMove(wrapper), readOnly);
592     m_transactionQueue.append(transactionBackend);
593     if (!m_transactionInProgress)
594         scheduleTransaction();
595
596     return transactionBackend;
597 }
598
599 void Database::scheduleTransactionStep(SQLTransactionBackend* transaction)
600 {
601     if (!databaseContext()->databaseThread())
602         return;
603
604     auto task = std::make_unique<DatabaseTransactionTask>(transaction);
605     LOG(StorageAPI, "Scheduling DatabaseTransactionTask %p for the transaction step\n", task.get());
606     databaseContext()->databaseThread()->scheduleTask(WTFMove(task));
607 }
608
609 void Database::inProgressTransactionCompleted()
610 {
611     LockHolder locker(m_transactionInProgressMutex);
612     m_transactionInProgress = false;
613     scheduleTransaction();
614 }
615
616 bool Database::hasPendingTransaction()
617 {
618     LockHolder locker(m_transactionInProgressMutex);
619     return m_transactionInProgress || !m_transactionQueue.isEmpty();
620 }
621
622 SQLTransactionClient* Database::transactionClient() const
623 {
624     return databaseContext()->databaseThread()->transactionClient();
625 }
626
627 SQLTransactionCoordinator* Database::transactionCoordinator() const
628 {
629     return databaseContext()->databaseThread()->transactionCoordinator();
630 }
631
632 String Database::version() const
633 {
634     if (m_deleted)
635         return String();
636
637     // Note: In multi-process browsers the cached value may be accurate, but we cannot read the
638     // actual version from the database without potentially inducing a deadlock.
639     // FIXME: Add an async version getter to the DatabaseAPI.
640     return getCachedVersion();
641 }
642
643 void Database::markAsDeletedAndClose()
644 {
645     if (m_deleted || !databaseContext()->databaseThread())
646         return;
647
648     LOG(StorageAPI, "Marking %s (%p) as deleted", stringIdentifier().ascii().data(), this);
649     m_deleted = true;
650
651     close();
652 }
653
654 void Database::changeVersion(const String& oldVersion, const String& newVersion, RefPtr<SQLTransactionCallback>&& callback, RefPtr<SQLTransactionErrorCallback>&& errorCallback, RefPtr<VoidCallback>&& successCallback)
655 {
656     ChangeVersionData data(oldVersion, newVersion);
657     runTransaction(WTFMove(callback), WTFMove(errorCallback), WTFMove(successCallback), false, &data);
658 }
659
660 void Database::transaction(RefPtr<SQLTransactionCallback>&& callback, RefPtr<SQLTransactionErrorCallback>&& errorCallback, RefPtr<VoidCallback>&& successCallback)
661 {
662     runTransaction(WTFMove(callback), WTFMove(errorCallback), WTFMove(successCallback), false);
663 }
664
665 void Database::readTransaction(RefPtr<SQLTransactionCallback>&& callback, RefPtr<SQLTransactionErrorCallback>&& errorCallback, RefPtr<VoidCallback>&& successCallback)
666 {
667     runTransaction(WTFMove(callback), WTFMove(errorCallback), WTFMove(successCallback), true);
668 }
669
670 String Database::stringIdentifier() const
671 {
672     // Return a deep copy for ref counting thread safety
673     return m_name.isolatedCopy();
674 }
675
676 String Database::displayName() const
677 {
678     // Return a deep copy for ref counting thread safety
679     return m_displayName.isolatedCopy();
680 }
681
682 unsigned long Database::estimatedSize() const
683 {
684     return m_estimatedSize;
685 }
686
687 String Database::fileName() const
688 {
689     // Return a deep copy for ref counting thread safety
690     return m_filename.isolatedCopy();
691 }
692
693 DatabaseDetails Database::details() const
694 {
695     // This code path is only used for database quota delegate calls, so file dates are irrelevant and left uninitialized.
696     return DatabaseDetails(stringIdentifier(), displayName(), estimatedSize(), 0, 0, 0);
697 }
698
699 void Database::disableAuthorizer()
700 {
701     ASSERT(m_databaseAuthorizer);
702     m_databaseAuthorizer->disable();
703 }
704
705 void Database::enableAuthorizer()
706 {
707     ASSERT(m_databaseAuthorizer);
708     m_databaseAuthorizer->enable();
709 }
710
711 void Database::setAuthorizerPermissions(int permissions)
712 {
713     ASSERT(m_databaseAuthorizer);
714     m_databaseAuthorizer->setPermissions(permissions);
715 }
716
717 bool Database::lastActionChangedDatabase()
718 {
719     ASSERT(m_databaseAuthorizer);
720     return m_databaseAuthorizer->lastActionChangedDatabase();
721 }
722
723 bool Database::lastActionWasInsert()
724 {
725     ASSERT(m_databaseAuthorizer);
726     return m_databaseAuthorizer->lastActionWasInsert();
727 }
728
729 void Database::resetDeletes()
730 {
731     ASSERT(m_databaseAuthorizer);
732     m_databaseAuthorizer->resetDeletes();
733 }
734
735 bool Database::hadDeletes()
736 {
737     ASSERT(m_databaseAuthorizer);
738     return m_databaseAuthorizer->hadDeletes();
739 }
740
741 void Database::resetAuthorizer()
742 {
743     if (m_databaseAuthorizer)
744         m_databaseAuthorizer->reset();
745 }
746
747 void Database::runTransaction(RefPtr<SQLTransactionCallback>&& callback, RefPtr<SQLTransactionErrorCallback>&& errorCallback, RefPtr<VoidCallback>&& successCallback, bool readOnly, const ChangeVersionData* changeVersionData)
748 {
749     Ref<SQLTransaction> transaction = SQLTransaction::create(*this, WTFMove(callback), WTFMove(successCallback), errorCallback.copyRef(), readOnly);
750
751     RefPtr<SQLTransactionBackend> transactionBackend = runTransaction(WTFMove(transaction), readOnly, changeVersionData);
752     if (!transactionBackend && errorCallback) {
753         RefPtr<SQLTransactionErrorCallback> errorCallbackProtector = WTFMove(errorCallback);
754         m_scriptExecutionContext->postTask([errorCallbackProtector](ScriptExecutionContext&) {
755             errorCallbackProtector->handleEvent(SQLError::create(SQLError::UNKNOWN_ERR, "database has been closed").ptr());
756         });
757     }
758 }
759
760 void Database::scheduleTransactionCallback(SQLTransaction* transaction)
761 {
762     RefPtr<SQLTransaction> transactionProtector(transaction);
763     m_scriptExecutionContext->postTask([transactionProtector] (ScriptExecutionContext&) {
764         transactionProtector->performPendingCallback();
765     });
766 }
767
768 Vector<String> Database::performGetTableNames()
769 {
770     disableAuthorizer();
771
772     SQLiteStatement statement(sqliteDatabase(), "SELECT name FROM sqlite_master WHERE type='table';");
773     if (statement.prepare() != SQLITE_OK) {
774         LOG_ERROR("Unable to retrieve list of tables for database %s", databaseDebugName().ascii().data());
775         enableAuthorizer();
776         return Vector<String>();
777     }
778
779     Vector<String> tableNames;
780     int result;
781     while ((result = statement.step()) == SQLITE_ROW) {
782         String name = statement.getColumnText(0);
783         if (name != unqualifiedInfoTableName)
784             tableNames.append(name);
785     }
786
787     enableAuthorizer();
788
789     if (result != SQLITE_DONE) {
790         LOG_ERROR("Error getting tables for database %s", databaseDebugName().ascii().data());
791         return Vector<String>();
792     }
793
794     return tableNames;
795 }
796
797 void Database::incrementalVacuumIfNeeded()
798 {
799     SQLiteTransactionInProgressAutoCounter transactionCounter;
800
801     int64_t freeSpaceSize = m_sqliteDatabase.freeSpaceSize();
802     int64_t totalSize = m_sqliteDatabase.totalSize();
803     if (totalSize <= 10 * freeSpaceSize) {
804         int result = m_sqliteDatabase.runIncrementalVacuumCommand();
805         if (result != SQLITE_OK)
806             logErrorMessage(formatErrorMessage("error vacuuming database", result, m_sqliteDatabase.lastErrorMsg()));
807     }
808 }
809
810 void Database::logErrorMessage(const String& message)
811 {
812     m_scriptExecutionContext->addConsoleMessage(MessageSource::Storage, MessageLevel::Error, message);
813 }
814
815 Vector<String> Database::tableNames()
816 {
817     // FIXME: Not using isolatedCopy on these strings looks ok since threads take strict turns
818     // in dealing with them. However, if the code changes, this may not be true anymore.
819     Vector<String> result;
820     DatabaseTaskSynchronizer synchronizer;
821     if (!databaseContext()->databaseThread() || databaseContext()->databaseThread()->terminationRequested(&synchronizer))
822         return result;
823
824     auto task = std::make_unique<DatabaseTableNamesTask>(*this, synchronizer, result);
825     databaseContext()->databaseThread()->scheduleImmediateTask(WTFMove(task));
826     synchronizer.waitForTaskCompletion();
827
828     return result;
829 }
830
831 SecurityOrigin* Database::securityOrigin() const
832 {
833     if (m_scriptExecutionContext->isContextThread())
834         return m_contextThreadSecurityOrigin.get();
835     if (currentThread() == databaseContext()->databaseThread()->getThreadID())
836         return m_databaseThreadSecurityOrigin.get();
837     return 0;
838 }
839
840 unsigned long long Database::maximumSize() const
841 {
842     return DatabaseTracker::tracker().getMaxSizeForDatabase(this);
843 }
844
845 #if !LOG_DISABLED || !ERROR_DISABLED
846 String Database::databaseDebugName() const
847 {
848     return m_contextThreadSecurityOrigin->toString() + "::" + m_name;
849 }
850 #endif
851
852 } // namespace WebCore