From 32761a6cee1d0dee366b885b7b9c777e67885688 Mon Sep 17 00:00:00 2001 From: Lorry Tar Creator Date: Sun, 10 Apr 2016 09:28:39 +0000 Subject: webkitgtk-2.4.11 --- .../Modules/webdatabase/DatabaseTracker.cpp | 368 +++++++++++---------- 1 file changed, 185 insertions(+), 183 deletions(-) (limited to 'Source/WebCore/Modules/webdatabase/DatabaseTracker.cpp') diff --git a/Source/WebCore/Modules/webdatabase/DatabaseTracker.cpp b/Source/WebCore/Modules/webdatabase/DatabaseTracker.cpp index 1fe9f1aec..8d3fa13a0 100644 --- a/Source/WebCore/Modules/webdatabase/DatabaseTracker.cpp +++ b/Source/WebCore/Modules/webdatabase/DatabaseTracker.cpp @@ -10,7 +10,7 @@ * 2. 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. - * 3. Neither the name of Apple Inc. ("Apple") nor the names of + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * @@ -29,10 +29,13 @@ #include "config.h" #include "DatabaseTracker.h" +#if ENABLE(SQL_DATABASE) + #include "Chrome.h" #include "ChromeClient.h" #include "Database.h" -#include "DatabaseContext.h" +#include "DatabaseBackendBase.h" +#include "DatabaseBackendContext.h" #include "DatabaseManager.h" #include "DatabaseManagerClient.h" #include "DatabaseThread.h" @@ -44,12 +47,9 @@ #include "SecurityOriginHash.h" #include "SQLiteFileSystem.h" #include "SQLiteStatement.h" -#include "UUID.h" #include -#include #include #include -#include #if PLATFORM(IOS) #include "WebCoreThread.h" @@ -57,12 +57,7 @@ namespace WebCore { -std::unique_ptr DatabaseTracker::trackerWithDatabasePath(const String& databasePath) -{ - return std::unique_ptr(new DatabaseTracker(databasePath)); -} - -static DatabaseTracker* staticTracker = nullptr; +static DatabaseTracker* staticTracker = 0; void DatabaseTracker::initializeTracker(const String& databasePath) { @@ -82,14 +77,14 @@ DatabaseTracker& DatabaseTracker::tracker() } DatabaseTracker::DatabaseTracker(const String& databasePath) - : m_client(nullptr) + : m_client(0) { setDatabaseDirectoryPath(databasePath); } void DatabaseTracker::setDatabaseDirectoryPath(const String& path) { - LockHolder lockDatabase(m_databaseGuard); + MutexLocker lockDatabase(m_databaseGuard); ASSERT(!m_database.isOpen()); m_databaseDirectoryPath = path.isolatedCopy(); } @@ -162,11 +157,11 @@ bool DatabaseTracker::hasAdequateQuotaForOrigin(SecurityOrigin* origin, unsigned return false; } -bool DatabaseTracker::canEstablishDatabase(DatabaseContext* context, const String& name, unsigned long estimatedSize, DatabaseError& error) +bool DatabaseTracker::canEstablishDatabase(DatabaseBackendContext* context, const String& name, unsigned long estimatedSize, DatabaseError& error) { error = DatabaseError::None; - LockHolder lockDatabase(m_databaseGuard); + MutexLocker lockDatabase(m_databaseGuard); SecurityOrigin* origin = context->securityOrigin(); if (isDeletingDatabaseOrOriginFor(origin, name)) { @@ -214,11 +209,11 @@ bool DatabaseTracker::canEstablishDatabase(DatabaseContext* context, const Strin // hasAdequateQuotaForOrigin() simple and correct (i.e. bug free), and just // re-use it. Also note that the path for opening a database involves IO, and // hence should not be a performance critical path anyway. -bool DatabaseTracker::retryCanEstablishDatabase(DatabaseContext* context, const String& name, unsigned long estimatedSize, DatabaseError& error) +bool DatabaseTracker::retryCanEstablishDatabase(DatabaseBackendContext* context, const String& name, unsigned long estimatedSize, DatabaseError& error) { error = DatabaseError::None; - LockHolder lockDatabase(m_databaseGuard); + MutexLocker lockDatabase(m_databaseGuard); SecurityOrigin* origin = context->securityOrigin(); // We have already eliminated other types of errors in canEstablishDatabase(). @@ -245,19 +240,19 @@ bool DatabaseTracker::hasEntryForOriginNoLock(SecurityOrigin* origin) return false; SQLiteStatement statement(m_database, "SELECT origin FROM Origins where origin=?;"); - if (statement.prepare() != SQLITE_OK) { + if (statement.prepare() != SQLResultOk) { LOG_ERROR("Failed to prepare statement."); return false; } statement.bindText(1, origin->databaseIdentifier()); - return statement.step() == SQLITE_ROW; + return statement.step() == SQLResultRow; } bool DatabaseTracker::hasEntryForOrigin(SecurityOrigin* origin) { - LockHolder lockDatabase(m_databaseGuard); + MutexLocker lockDatabase(m_databaseGuard); return hasEntryForOriginNoLock(origin); } @@ -273,20 +268,20 @@ bool DatabaseTracker::hasEntryForDatabase(SecurityOrigin* origin, const String& // We've got a tracker database. Set up a query to ask for the db of interest: SQLiteStatement statement(m_database, "SELECT guid FROM Databases WHERE origin=? AND name=?;"); - if (statement.prepare() != SQLITE_OK) + if (statement.prepare() != SQLResultOk) return false; statement.bindText(1, origin->databaseIdentifier()); statement.bindText(2, databaseIdentifier); - return statement.step() == SQLITE_ROW; + return statement.step() == SQLResultRow; } -unsigned long long DatabaseTracker::getMaxSizeForDatabase(const Database* database) +unsigned long long DatabaseTracker::getMaxSizeForDatabase(const DatabaseBackendBase* database) { // The maximum size for a database is the full quota for its origin, minus the current usage within the origin, // plus the current usage of the given database - LockHolder lockDatabase(m_databaseGuard); + MutexLocker lockDatabase(m_databaseGuard); SecurityOrigin* origin = database->securityOrigin(); unsigned long long quota = quotaForOriginNoLock(origin); @@ -307,22 +302,33 @@ unsigned long long DatabaseTracker::getMaxSizeForDatabase(const Database* databa return maxSize; } -void DatabaseTracker::closeAllDatabases() +void DatabaseTracker::interruptAllDatabasesForContext(const DatabaseBackendContext* context) { - Vector> openDatabases; + Vector> openDatabases; { - LockHolder openDatabaseMapLock(m_openDatabaseMapGuard); + MutexLocker openDatabaseMapLock(m_openDatabaseMapGuard); + if (!m_openDatabaseMap) return; - for (auto& nameMap : m_openDatabaseMap->values()) { - for (auto& set : nameMap->values()) { - for (auto& database : *set) - openDatabases.append(*database); + + DatabaseNameMap* nameMap = m_openDatabaseMap->get(context->securityOrigin()); + if (!nameMap) + return; + + DatabaseNameMap::const_iterator dbNameMapEndIt = nameMap->end(); + for (DatabaseNameMap::const_iterator dbNameMapIt = nameMap->begin(); dbNameMapIt != dbNameMapEndIt; ++dbNameMapIt) { + DatabaseSet* databaseSet = dbNameMapIt->value; + DatabaseSet::const_iterator dbSetEndIt = databaseSet->end(); + for (DatabaseSet::const_iterator dbSetIt = databaseSet->begin(); dbSetIt != dbSetEndIt; ++dbSetIt) { + if ((*dbSetIt)->databaseContext() == context) + openDatabases.append(*dbSetIt); } } } - for (auto& database : openDatabases) - database->close(); + + Vector>::const_iterator openDatabasesEndIt = openDatabases.end(); + for (Vector>::const_iterator openDatabasesIt = openDatabases.begin(); openDatabasesIt != openDatabasesEndIt; ++openDatabasesIt) + (*openDatabasesIt)->interrupt(); } String DatabaseTracker::originPath(SecurityOrigin* origin) const @@ -330,16 +336,6 @@ String DatabaseTracker::originPath(SecurityOrigin* origin) const return SQLiteFileSystem::appendDatabaseFileNameToPath(m_databaseDirectoryPath.isolatedCopy(), origin->databaseIdentifier()); } -static String generateDatabaseFileName() -{ - StringBuilder stringBuilder; - - stringBuilder.append(createCanonicalUUIDString()); - stringBuilder.appendLiteral(".db"); - - return stringBuilder.toString(); -} - String DatabaseTracker::fullPathForDatabaseNoLock(SecurityOrigin* origin, const String& name, bool createIfNotExists) { ASSERT(!m_databaseGuard.tryLock()); @@ -356,7 +352,7 @@ String DatabaseTracker::fullPathForDatabaseNoLock(SecurityOrigin* origin, const return String(); SQLiteStatement statement(m_database, "SELECT path FROM Databases WHERE origin=? AND name=?;"); - if (statement.prepare() != SQLITE_OK) + if (statement.prepare() != SQLResultOk) return String(); statement.bindText(1, originIdentifier); @@ -364,19 +360,18 @@ String DatabaseTracker::fullPathForDatabaseNoLock(SecurityOrigin* origin, const int result = statement.step(); - if (result == SQLITE_ROW) + if (result == SQLResultRow) return SQLiteFileSystem::appendDatabaseFileNameToPath(originPath, statement.getColumnText(0)); if (!createIfNotExists) return String(); - if (result != SQLITE_DONE) { + if (result != SQLResultDone) { LOG_ERROR("Failed to retrieve filename from Database Tracker for origin %s, name %s", originIdentifier.ascii().data(), name.ascii().data()); return String(); } statement.finalize(); - String fileName = generateDatabaseFileName(); - + String fileName = SQLiteFileSystem::getFileNameForNewDatabase(originPath, name, originIdentifier, &m_database); if (!addDatabase(origin, name, fileName)) return String(); @@ -389,32 +384,32 @@ String DatabaseTracker::fullPathForDatabaseNoLock(SecurityOrigin* origin, const String DatabaseTracker::fullPathForDatabase(SecurityOrigin* origin, const String& name, bool createIfNotExists) { - LockHolder lockDatabase(m_databaseGuard); + MutexLocker lockDatabase(m_databaseGuard); return fullPathForDatabaseNoLock(origin, name, createIfNotExists).isolatedCopy(); } void DatabaseTracker::origins(Vector>& originsResult) { - LockHolder lockDatabase(m_databaseGuard); + MutexLocker lockDatabase(m_databaseGuard); openTrackerDatabase(DontCreateIfDoesNotExist); if (!m_database.isOpen()) return; SQLiteStatement statement(m_database, "SELECT origin FROM Origins"); - if (statement.prepare() != SQLITE_OK) { + if (statement.prepare() != SQLResultOk) { LOG_ERROR("Failed to prepare statement."); return; } int result; - while ((result = statement.step()) == SQLITE_ROW) { + while ((result = statement.step()) == SQLResultRow) { RefPtr origin = SecurityOrigin::createFromDatabaseIdentifier(statement.getColumnText(0)); originsResult.append(origin->isolatedCopy()); } originsResult.shrinkToFit(); - if (result != SQLITE_DONE) + if (result != SQLResultDone) LOG_ERROR("Failed to read in all origins from the database."); } @@ -427,16 +422,16 @@ bool DatabaseTracker::databaseNamesForOriginNoLock(SecurityOrigin* origin, Vecto SQLiteStatement statement(m_database, "SELECT name FROM Databases where origin=?;"); - if (statement.prepare() != SQLITE_OK) + if (statement.prepare() != SQLResultOk) return false; statement.bindText(1, origin->databaseIdentifier()); int result; - while ((result = statement.step()) == SQLITE_ROW) + while ((result = statement.step()) == SQLResultRow) resultVector.append(statement.getColumnText(0)); - if (result != SQLITE_DONE) { + if (result != SQLResultDone) { LOG_ERROR("Failed to retrieve all database names for origin %s", origin->databaseIdentifier().ascii().data()); return false; } @@ -448,13 +443,13 @@ bool DatabaseTracker::databaseNamesForOrigin(SecurityOrigin* origin, Vector temp; { - LockHolder lockDatabase(m_databaseGuard); + MutexLocker lockDatabase(m_databaseGuard); if (!databaseNamesForOriginNoLock(origin, temp)) return false; } - for (auto& databaseName : temp) - resultVector.append(databaseName.isolatedCopy()); + for (Vector::iterator iter = temp.begin(); iter != temp.end(); ++iter) + resultVector.append(iter->isolatedCopy()); return true; } @@ -465,23 +460,23 @@ DatabaseDetails DatabaseTracker::detailsForNameAndOrigin(const String& name, Sec int64_t expectedUsage; { - LockHolder lockDatabase(m_databaseGuard); + MutexLocker lockDatabase(m_databaseGuard); openTrackerDatabase(DontCreateIfDoesNotExist); if (!m_database.isOpen()) return DatabaseDetails(); SQLiteStatement statement(m_database, "SELECT displayName, estimatedSize FROM Databases WHERE origin=? AND name=?"); - if (statement.prepare() != SQLITE_OK) + if (statement.prepare() != SQLResultOk) return DatabaseDetails(); statement.bindText(1, originIdentifier); statement.bindText(2, name); int result = statement.step(); - if (result == SQLITE_DONE) + if (result == SQLResultDone) return DatabaseDetails(); - if (result != SQLITE_ROW) { + if (result != SQLResultRow) { LOG_ERROR("Error retrieving details for database %s in origin %s from tracker database", name.ascii().data(), originIdentifier.ascii().data()); return DatabaseDetails(); } @@ -500,25 +495,25 @@ void DatabaseTracker::setDatabaseDetails(SecurityOrigin* origin, const String& n String originIdentifier = origin->databaseIdentifier(); int64_t guid = 0; - LockHolder lockDatabase(m_databaseGuard); + MutexLocker lockDatabase(m_databaseGuard); openTrackerDatabase(CreateIfDoesNotExist); if (!m_database.isOpen()) return; SQLiteStatement statement(m_database, "SELECT guid FROM Databases WHERE origin=? AND name=?"); - if (statement.prepare() != SQLITE_OK) + if (statement.prepare() != SQLResultOk) return; statement.bindText(1, originIdentifier); statement.bindText(2, name); int result = statement.step(); - if (result == SQLITE_ROW) + if (result == SQLResultRow) guid = statement.getColumnInt64(0); statement.finalize(); if (guid == 0) { - if (result != SQLITE_DONE) + if (result != SQLResultDone) LOG_ERROR("Error to determing existence of database %s in origin %s in tracker database", name.ascii().data(), originIdentifier.ascii().data()); else { // This case should never occur - we should never be setting database details for a database that doesn't already exist in the tracker @@ -531,14 +526,14 @@ void DatabaseTracker::setDatabaseDetails(SecurityOrigin* origin, const String& n } SQLiteStatement updateStatement(m_database, "UPDATE Databases SET displayName=?, estimatedSize=? WHERE guid=?"); - if (updateStatement.prepare() != SQLITE_OK) + if (updateStatement.prepare() != SQLResultOk) return; updateStatement.bindText(1, displayName); updateStatement.bindInt64(2, estimatedSize); updateStatement.bindInt64(3, guid); - if (updateStatement.step() != SQLITE_DONE) { + if (updateStatement.step() != SQLResultDone) { LOG_ERROR("Failed to update details for database %s in origin %s", name.ascii().data(), originIdentifier.ascii().data()); return; } @@ -547,22 +542,22 @@ void DatabaseTracker::setDatabaseDetails(SecurityOrigin* origin, const String& n m_client->dispatchDidModifyDatabase(origin, name); } -void DatabaseTracker::doneCreatingDatabase(Database* database) +void DatabaseTracker::doneCreatingDatabase(DatabaseBackendBase* database) { - LockHolder lockDatabase(m_databaseGuard); + MutexLocker lockDatabase(m_databaseGuard); doneCreatingDatabase(database->securityOrigin(), database->stringIdentifier()); } -void DatabaseTracker::addOpenDatabase(Database* database) +void DatabaseTracker::addOpenDatabase(DatabaseBackendBase* database) { if (!database) return; { - LockHolder openDatabaseMapLock(m_openDatabaseMapGuard); + MutexLocker openDatabaseMapLock(m_openDatabaseMapGuard); if (!m_openDatabaseMap) - m_openDatabaseMap = std::make_unique(); + m_openDatabaseMap = adoptPtr(new DatabaseOriginMap); String name(database->stringIdentifier()); DatabaseNameMap* nameMap = m_openDatabaseMap->get(database->securityOrigin()); @@ -583,13 +578,13 @@ void DatabaseTracker::addOpenDatabase(Database* database) } } -void DatabaseTracker::removeOpenDatabase(Database* database) +void DatabaseTracker::removeOpenDatabase(DatabaseBackendBase* database) { if (!database) return; { - LockHolder openDatabaseMapLock(m_openDatabaseMapGuard); + MutexLocker openDatabaseMapLock(m_openDatabaseMapGuard); if (!m_openDatabaseMap) { ASSERT_NOT_REACHED(); @@ -627,9 +622,9 @@ void DatabaseTracker::removeOpenDatabase(Database* database) } } -void DatabaseTracker::getOpenDatabases(SecurityOrigin* origin, const String& name, HashSet>* databases) +void DatabaseTracker::getOpenDatabases(SecurityOrigin* origin, const String& name, HashSet>* databases) { - LockHolder openDatabaseMapLock(m_openDatabaseMapGuard); + MutexLocker openDatabaseMapLock(m_openDatabaseMapGuard); if (!m_openDatabaseMap) return; @@ -641,13 +636,13 @@ void DatabaseTracker::getOpenDatabases(SecurityOrigin* origin, const String& nam if (!databaseSet) return; - for (auto& database : *databaseSet) - databases->add(database); + for (DatabaseSet::iterator it = databaseSet->begin(); it != databaseSet->end(); ++it) + databases->add(*it); } -RefPtr DatabaseTracker::originLockFor(SecurityOrigin* origin) +PassRefPtr DatabaseTracker::originLockFor(SecurityOrigin* origin) { - LockHolder lockDatabase(m_databaseGuard); + MutexLocker lockDatabase(m_databaseGuard); String databaseIdentifier = origin->databaseIdentifier(); // The originLockMap is accessed from multiple DatabaseThreads since @@ -663,11 +658,11 @@ RefPtr DatabaseTracker::originLockFor(SecurityOrigin* origin) return addResult.iterator->value; String path = originPath(origin); - RefPtr lock = adoptRef(*new OriginLock(path)); + RefPtr lock = adoptRef(new OriginLock(path)); ASSERT(lock); addResult.iterator->value = lock; - return lock; + return lock.release(); } void DatabaseTracker::deleteOriginLockFor(SecurityOrigin* origin) @@ -685,7 +680,8 @@ void DatabaseTracker::deleteOriginLockFor(SecurityOrigin* origin) // files in this origin. We'll give the OriginLock one chance to do an // orderly clean up first when we remove its ref from the m_originLockMap. // This may or may not be possible depending on whether other threads are - // also using the OriginLock at the same time. After that, we will delete the lock file. + // also using the OriginLock at the same time. After that, we will go ahead + // and delete the lock file. m_originLockMap.remove(origin->databaseIdentifier()); OriginLock::deleteLockFile(originPath(origin)); @@ -695,9 +691,12 @@ unsigned long long DatabaseTracker::usageForOrigin(SecurityOrigin* origin) { String originPath = this->originPath(origin); unsigned long long diskUsage = 0; - for (auto& fileName : listDirectory(originPath, ASCIILiteral("*.db"))) { + Vector fileNames = listDirectory(originPath, String("*.db")); + Vector::iterator fileName = fileNames.begin(); + Vector::iterator lastFileName = fileNames.end(); + for (; fileName != lastFileName; ++fileName) { long long size; - getFileSize(fileName, size); + getFileSize(*fileName, size); diskUsage += size; } return diskUsage; @@ -713,13 +712,13 @@ unsigned long long DatabaseTracker::quotaForOriginNoLock(SecurityOrigin* origin) return quota; SQLiteStatement statement(m_database, "SELECT quota FROM Origins where origin=?;"); - if (statement.prepare() != SQLITE_OK) { + if (statement.prepare() != SQLResultOk) { LOG_ERROR("Failed to prepare statement."); return quota; } statement.bindText(1, origin->databaseIdentifier()); - if (statement.step() == SQLITE_ROW) + if (statement.step() == SQLResultRow) quota = statement.getColumnInt64(0); return quota; @@ -727,13 +726,13 @@ unsigned long long DatabaseTracker::quotaForOriginNoLock(SecurityOrigin* origin) unsigned long long DatabaseTracker::quotaForOrigin(SecurityOrigin* origin) { - LockHolder lockDatabase(m_databaseGuard); + MutexLocker lockDatabase(m_databaseGuard); return quotaForOriginNoLock(origin); } void DatabaseTracker::setQuota(SecurityOrigin* origin, unsigned long long quota) { - LockHolder lockDatabase(m_databaseGuard); + MutexLocker lockDatabase(m_databaseGuard); if (quotaForOriginNoLock(origin) == quota) return; @@ -749,13 +748,13 @@ void DatabaseTracker::setQuota(SecurityOrigin* origin, unsigned long long quota) bool originEntryExists = hasEntryForOriginNoLock(origin); if (!originEntryExists) { SQLiteStatement statement(m_database, "INSERT INTO Origins VALUES (?, ?)"); - if (statement.prepare() != SQLITE_OK) { + if (statement.prepare() != SQLResultOk) { LOG_ERROR("Unable to establish origin %s in the tracker", origin->databaseIdentifier().ascii().data()); } else { statement.bindText(1, origin->databaseIdentifier()); statement.bindInt64(2, quota); - if (statement.step() != SQLITE_DONE) + if (statement.step() != SQLResultDone) LOG_ERROR("Unable to establish origin %s in the tracker", origin->databaseIdentifier().ascii().data()); #if PLATFORM(IOS) else @@ -764,7 +763,7 @@ void DatabaseTracker::setQuota(SecurityOrigin* origin, unsigned long long quota) } } else { SQLiteStatement statement(m_database, "UPDATE Origins SET quota=? WHERE origin=?"); - bool error = statement.prepare() != SQLITE_OK; + bool error = statement.prepare() != SQLResultOk; if (!error) { statement.bindInt64(1, quota); statement.bindText(2, origin->databaseIdentifier()); @@ -800,7 +799,7 @@ bool DatabaseTracker::addDatabase(SecurityOrigin* origin, const String& name, co SQLiteStatement statement(m_database, "INSERT INTO Databases (origin, name, path) VALUES (?, ?, ?);"); - if (statement.prepare() != SQLITE_OK) + if (statement.prepare() != SQLResultOk) return false; statement.bindText(1, origin->databaseIdentifier()); @@ -823,39 +822,8 @@ void DatabaseTracker::deleteAllDatabases() Vector> originsCopy; origins(originsCopy); - for (auto& origin : originsCopy) - deleteOrigin(origin.get()); -} - -void DatabaseTracker::deleteDatabasesModifiedSince(std::chrono::system_clock::time_point time) -{ - Vector> originsCopy; - origins(originsCopy); - - for (auto& origin : originsCopy) { - Vector databaseNames; - if (!databaseNamesForOrigin(origin.get(), databaseNames)) - continue; - - size_t deletedDatabases = 0; - - for (auto& databaseName : databaseNames) { - auto fullPath = fullPathForDatabase(origin.get(), databaseName, false); - - time_t modificationTime; - if (!getFileModificationTime(fullPath, modificationTime)) - continue; - - if (modificationTime < std::chrono::system_clock::to_time_t(time)) - continue; - - deleteDatabase(origin.get(), databaseName); - ++deletedDatabases; - } - - if (deletedDatabases == databaseNames.size()) - deleteOrigin(origin.get()); - } + for (unsigned i = 0; i < originsCopy.size(); ++i) + deleteOrigin(originsCopy[i].get()); } // It is the caller's responsibility to make sure that nobody is trying to create, delete, open, or close databases in this origin while the deletion is @@ -864,7 +832,7 @@ bool DatabaseTracker::deleteOrigin(SecurityOrigin* origin) { Vector databaseNames; { - LockHolder lockDatabase(m_databaseGuard); + MutexLocker lockDatabase(m_databaseGuard); openTrackerDatabase(DontCreateIfDoesNotExist); if (!m_database.isOpen()) return false; @@ -882,20 +850,20 @@ bool DatabaseTracker::deleteOrigin(SecurityOrigin* origin) } // We drop the lock here because holding locks during a call to deleteDatabaseFile will deadlock. - for (auto& name : databaseNames) { - if (!deleteDatabaseFile(origin, name)) { + for (unsigned i = 0; i < databaseNames.size(); ++i) { + if (!deleteDatabaseFile(origin, databaseNames[i])) { // Even if the file can't be deleted, we want to try and delete the rest, don't return early here. - LOG_ERROR("Unable to delete file for database %s in origin %s", name.ascii().data(), origin->databaseIdentifier().ascii().data()); + LOG_ERROR("Unable to delete file for database %s in origin %s", databaseNames[i].ascii().data(), origin->databaseIdentifier().ascii().data()); } } { - LockHolder lockDatabase(m_databaseGuard); + MutexLocker lockDatabase(m_databaseGuard); deleteOriginLockFor(origin); doneDeletingOrigin(origin); SQLiteStatement statement(m_database, "DELETE FROM Databases WHERE origin=?"); - if (statement.prepare() != SQLITE_OK) { + if (statement.prepare() != SQLResultOk) { LOG_ERROR("Unable to prepare deletion of databases from origin %s from tracker", origin->databaseIdentifier().ascii().data()); return false; } @@ -908,7 +876,7 @@ bool DatabaseTracker::deleteOrigin(SecurityOrigin* origin) } SQLiteStatement originStatement(m_database, "DELETE FROM Origins WHERE origin=?"); - if (originStatement.prepare() != SQLITE_OK) { + if (originStatement.prepare() != SQLResultOk) { LOG_ERROR("Unable to prepare deletion of origin %s from tracker", origin->databaseIdentifier().ascii().data()); return false; } @@ -928,9 +896,9 @@ bool DatabaseTracker::deleteOrigin(SecurityOrigin* origin) openTrackerDatabase(DontCreateIfDoesNotExist); if (m_database.isOpen()) { SQLiteStatement statement(m_database, "SELECT origin FROM Origins"); - if (statement.prepare() != SQLITE_OK) + if (statement.prepare() != SQLResultOk) LOG_ERROR("Failed to prepare statement."); - else if (statement.step() == SQLITE_ROW) + else if (statement.step() == SQLResultRow) isEmpty = false; } @@ -947,8 +915,8 @@ bool DatabaseTracker::deleteOrigin(SecurityOrigin* origin) #if PLATFORM(IOS) m_client->dispatchDidDeleteDatabaseOrigin(); #endif - for (auto& name : databaseNames) - m_client->dispatchDidModifyDatabase(origin, name); + for (unsigned i = 0; i < databaseNames.size(); ++i) + m_client->dispatchDidModifyDatabase(origin, databaseNames[i]); } } return true; @@ -1071,7 +1039,7 @@ void DatabaseTracker::doneDeletingOrigin(SecurityOrigin *origin) bool DatabaseTracker::deleteDatabase(SecurityOrigin* origin, const String& name) { { - LockHolder lockDatabase(m_databaseGuard); + MutexLocker lockDatabase(m_databaseGuard); openTrackerDatabase(DontCreateIfDoesNotExist); if (!m_database.isOpen()) return false; @@ -1086,15 +1054,15 @@ bool DatabaseTracker::deleteDatabase(SecurityOrigin* origin, const String& name) // We drop the lock here because holding locks during a call to deleteDatabaseFile will deadlock. if (!deleteDatabaseFile(origin, name)) { LOG_ERROR("Unable to delete file for database %s in origin %s", name.ascii().data(), origin->databaseIdentifier().ascii().data()); - LockHolder lockDatabase(m_databaseGuard); + MutexLocker lockDatabase(m_databaseGuard); doneDeletingDatabase(origin, name); return false; } - LockHolder lockDatabase(m_databaseGuard); + MutexLocker lockDatabase(m_databaseGuard); SQLiteStatement statement(m_database, "DELETE FROM Databases WHERE origin=? AND name=?"); - if (statement.prepare() != SQLITE_OK) { + if (statement.prepare() != SQLResultOk) { LOG_ERROR("Unable to prepare deletion of database %s from origin %s from tracker", name.ascii().data(), origin->databaseIdentifier().ascii().data()); doneDeletingDatabase(origin, name); return false; @@ -1131,18 +1099,18 @@ bool DatabaseTracker::deleteDatabaseFile(SecurityOrigin* origin, const String& n #ifndef NDEBUG { - LockHolder lockDatabase(m_databaseGuard); + MutexLocker lockDatabase(m_databaseGuard); ASSERT(isDeletingDatabaseOrOriginFor(origin, name)); } #endif - Vector> deletedDatabases; + Vector> deletedDatabases; // Make sure not to hold the any locks when calling // Database::markAsDeletedAndClose(), since that can cause a deadlock // during the synchronous DatabaseThread call it triggers. { - LockHolder openDatabaseMapLock(m_openDatabaseMapGuard); + MutexLocker openDatabaseMapLock(m_openDatabaseMapGuard); if (m_openDatabaseMap) { // There are some open databases, lets check if they are for this origin. DatabaseNameMap* nameMap = m_openDatabaseMap->get(origin); @@ -1152,15 +1120,16 @@ bool DatabaseTracker::deleteDatabaseFile(SecurityOrigin* origin, const String& n DatabaseSet* databaseSet = nameMap->get(name); if (databaseSet && databaseSet->size()) { // We have some database open with this name. Mark them as deleted. - for (auto& database : *databaseSet) - deletedDatabases.append(database); + DatabaseSet::const_iterator end = databaseSet->end(); + for (DatabaseSet::const_iterator it = databaseSet->begin(); it != end; ++it) + deletedDatabases.append(*it); } } } } - for (auto& database : deletedDatabases) - database->markAsDeletedAndClose(); + for (unsigned i = 0; i < deletedDatabases.size(); ++i) + deletedDatabases[i]->markAsDeletedAndClose(); #if !PLATFORM(IOS) return SQLiteFileSystem::deleteDatabaseFile(fullPath); @@ -1185,7 +1154,7 @@ void DatabaseTracker::removeDeletedOpenedDatabases() { // Acquire the lock before calling openTrackerDatabase. - LockHolder lockDatabase(m_databaseGuard); + MutexLocker lockDatabase(m_databaseGuard); openTrackerDatabase(DontCreateIfDoesNotExist); } @@ -1201,29 +1170,35 @@ void DatabaseTracker::removeDeletedOpenedDatabases() // Database::markAsDeletedAndClose(), since that can cause a deadlock // during the synchronous DatabaseThread call it triggers. { - LockHolder openDatabaseMapLock(m_openDatabaseMapGuard); + MutexLocker openDatabaseMapLock(m_openDatabaseMapGuard); if (m_openDatabaseMap) { - for (auto& openDatabase : *m_openDatabaseMap) { - auto& origin = openDatabase.key; - DatabaseNameMap* databaseNameMap = openDatabase.value; + DatabaseOriginMap::const_iterator originMapEnd = m_openDatabaseMap->end(); + for (DatabaseOriginMap::const_iterator originMapIt = m_openDatabaseMap->begin(); originMapIt != originMapEnd; ++originMapIt) { + RefPtr origin = originMapIt->key; + DatabaseNameMap* databaseNameMap = originMapIt->value; Vector deletedDatabaseNamesForThisOrigin; // Loop through all opened databases in this origin. Get the current database file path of each database and see if // it still matches the path stored in the opened database object. - for (auto& databases : *databaseNameMap) { - String databaseName = databases.key; + DatabaseNameMap::const_iterator dbNameMapEnd = databaseNameMap->end(); + for (DatabaseNameMap::const_iterator dbNameMapIt = databaseNameMap->begin(); dbNameMapIt != dbNameMapEnd; ++dbNameMapIt) { + String databaseName = dbNameMapIt->key; String databaseFileName; SQLiteStatement statement(m_database, "SELECT path FROM Databases WHERE origin=? AND name=?;"); - if (statement.prepare() == SQLITE_OK) { + if (statement.prepare() == SQLResultOk) { statement.bindText(1, origin->databaseIdentifier()); statement.bindText(2, databaseName); - if (statement.step() == SQLITE_ROW) + if (statement.step() == SQLResultRow) databaseFileName = statement.getColumnText(0); statement.finalize(); } bool foundDeletedDatabase = false; - for (auto& db : *databases.value) { + DatabaseSet* databaseSet = dbNameMapIt->value; + DatabaseSet::const_iterator dbEnd = databaseSet->end(); + for (DatabaseSet::const_iterator dbIt = databaseSet->begin(); dbIt != dbEnd; ++dbIt) { + Database* db = static_cast(*dbIt); + // We are done if this database has already been marked as deleted. if (db->deleted()) continue; @@ -1246,18 +1221,19 @@ void DatabaseTracker::removeDeletedOpenedDatabases() } } - for (auto& deletedDatabase : deletedDatabases) - deletedDatabase->markAsDeletedAndClose(); - - for (auto& deletedDatabase : deletedDatabaseMap) { - SecurityOrigin* origin = deletedDatabase.key.get(); + for (unsigned i = 0; i < deletedDatabases.size(); ++i) + deletedDatabases[i]->markAsDeletedAndClose(); + + DeletedDatabaseMap::const_iterator end = deletedDatabaseMap.end(); + for (DeletedDatabaseMap::const_iterator it = deletedDatabaseMap.begin(); it != end; ++it) { + SecurityOrigin* origin = it->key.get(); if (m_client) m_client->dispatchDidModifyOrigin(origin); - const Vector& databaseNames = deletedDatabase.value; - for (auto& databaseName : databaseNames) { + const Vector& databaseNames = it->value; + for (unsigned i = 0; i < databaseNames.size(); ++i) { if (m_client) - m_client->dispatchDidModifyDatabase(origin, databaseName); + m_client->dispatchDidModifyDatabase(origin, databaseNames[i]); } } } @@ -1280,20 +1256,20 @@ bool DatabaseTracker::deleteDatabaseFileIfEmpty(const String& path) // Specify that we want the exclusive locking mode, so after the next read, // we'll be holding the lock to this database file. SQLiteStatement lockStatement(database, "PRAGMA locking_mode=EXCLUSIVE;"); - if (lockStatement.prepare() != SQLITE_OK) + if (lockStatement.prepare() != SQLResultOk) return false; int result = lockStatement.step(); - if (result != SQLITE_ROW && result != SQLITE_DONE) + if (result != SQLResultRow && result != SQLResultDone) return false; lockStatement.finalize(); // Every sqlite database has a sqlite_master table that contains the schema for the database. // http://www.sqlite.org/faq.html#q7 SQLiteStatement readStatement(database, "SELECT * FROM sqlite_master LIMIT 1;"); - if (readStatement.prepare() != SQLITE_OK) + if (readStatement.prepare() != SQLResultOk) return false; // We shouldn't expect any result. - if (readStatement.step() != SQLITE_DONE) + if (readStatement.step() != SQLResultDone) return false; readStatement.finalize(); @@ -1305,9 +1281,9 @@ bool DatabaseTracker::deleteDatabaseFileIfEmpty(const String& path) return SQLiteFileSystem::deleteDatabaseFile(path); } -Lock& DatabaseTracker::openDatabaseMutex() +Mutex& DatabaseTracker::openDatabaseMutex() { - static NeverDestroyed mutex; + DEFINE_STATIC_LOCAL(Mutex, mutex, ()); return mutex; } @@ -1323,6 +1299,33 @@ void DatabaseTracker::emptyDatabaseFilesRemovalTaskDidFinish() openDatabaseMutex().unlock(); } +void DatabaseTracker::setDatabasesPaused(bool paused) +{ + MutexLocker openDatabaseMapLock(m_openDatabaseMapGuard); + if (!m_openDatabaseMap) + return; + + // This walking is - sadly - the only reliable way to get at each open database thread. + // This will be cleaner once or some other DB thread consolidation takes place. + DatabaseOriginMap::iterator i = m_openDatabaseMap.get()->begin(); + DatabaseOriginMap::iterator end = m_openDatabaseMap.get()->end(); + + for (; i != end; ++i) { + DatabaseNameMap* databaseNameMap = i->value; + DatabaseNameMap::iterator j = databaseNameMap->begin(); + DatabaseNameMap::iterator dbNameMapEnd = databaseNameMap->end(); + for (; j != dbNameMapEnd; ++j) { + DatabaseSet* databaseSet = j->value; + DatabaseSet::iterator k = databaseSet->begin(); + DatabaseSet::iterator dbSetEnd = databaseSet->end(); + for (; k != dbSetEnd; ++k) { + DatabaseContext* context = (*k)->databaseContext(); + context->setPaused(paused); + } + } + } +} + #endif void DatabaseTracker::setClient(DatabaseManagerClient* client) @@ -1330,9 +1333,9 @@ void DatabaseTracker::setClient(DatabaseManagerClient* client) m_client = client; } -static Lock& notificationMutex() +static Mutex& notificationMutex() { - static NeverDestroyed mutex; + DEFINE_STATIC_LOCAL(Mutex, mutex, ()); return mutex; } @@ -1340,13 +1343,13 @@ typedef Vector, String>> NotificationQueue; static NotificationQueue& notificationQueue() { - static NeverDestroyed queue; + DEFINE_STATIC_LOCAL(NotificationQueue, queue, ()); return queue; } void DatabaseTracker::scheduleNotifyDatabaseChanged(SecurityOrigin* origin, const String& name) { - LockHolder locker(notificationMutex()); + MutexLocker locker(notificationMutex()); notificationQueue().append(std::pair, String>(origin->isolatedCopy(), name.isolatedCopy())); scheduleForNotification(); @@ -1359,14 +1362,12 @@ void DatabaseTracker::scheduleForNotification() ASSERT(!notificationMutex().tryLock()); if (!notificationScheduled) { - callOnMainThread([] { - notifyDatabasesChanged(); - }); + callOnMainThread(DatabaseTracker::notifyDatabasesChanged, 0); notificationScheduled = true; } } -void DatabaseTracker::notifyDatabasesChanged() +void DatabaseTracker::notifyDatabasesChanged(void*) { // Note that if DatabaseTracker ever becomes non-singleton, we'll have to amend this notification // mechanism to include which tracker the notification goes out on as well. @@ -1374,7 +1375,7 @@ void DatabaseTracker::notifyDatabasesChanged() NotificationQueue notifications; { - LockHolder locker(notificationMutex()); + MutexLocker locker(notificationMutex()); notifications.swap(notificationQueue()); @@ -1390,3 +1391,4 @@ void DatabaseTracker::notifyDatabasesChanged() } // namespace WebCore +#endif -- cgit v1.2.1