// deleteDatabaseFile has to release locks between looking up the list of databases to close and closing them. While this is in progress, the caller // is responsible for making sure no new databases are opened in the file to be deleted. bool DatabaseTracker::deleteDatabaseFile(SecurityOrigin* origin, const String& name, DeletionMode deletionMode) { String fullPath = fullPathForDatabase(origin, name, false); if (fullPath.isEmpty()) return true; #ifndef NDEBUG { LockHolder lockDatabase(m_databaseGuard); ASSERT(isDeletingDatabaseOrOriginFor(origin, name)); } #endif Vector<RefPtr<Database>> 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); if (m_openDatabaseMap) { // There are some open databases, lets check if they are for this origin. DatabaseNameMap* nameMap = m_openDatabaseMap->get(origin); if (nameMap && nameMap->size()) { // There are some open databases for this origin, let's check // if they are this database by name. 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); } } } } for (auto& database : deletedDatabases) database->markAsDeletedAndClose(); #if PLATFORM(IOS) if (deletionMode == DeletionMode::Deferred) { // On the phone, other background processes may still be accessing this database. Deleting the database directly // would nuke the POSIX file locks, potentially causing Safari/WebApp to corrupt the new db if it's running in the background. // We'll instead truncate the database file to 0 bytes. If another process is operating on this same database file after // the truncation, it should get an error since the database file is no longer valid. When Safari is launched // next time, it'll go through the database files and clean up any zero-bytes ones. SQLiteDatabase database; if (!database.open(fullPath)) return false; return SQLiteFileSystem::truncateDatabaseFile(database.sqlite3Handle()); } #else UNUSED_PARAM(deletionMode); #endif return SQLiteFileSystem::deleteDatabaseFile(fullPath); }
static void truncateDatabaseFile(SQLiteDatabase& database) { sqlite3_file_control(database.sqlite3Handle(), 0, SQLITE_TRUNCATE_DATABASE, 0); }