static void removeAllDatabasesForOriginPath(const String& originPath, std::chrono::system_clock::time_point modifiedSince) { Vector<String> databasePaths = listDirectory(originPath, "*"); for (auto& databasePath : databasePaths) { String databaseFile = pathByAppendingComponent(databasePath, "IndexedDB.sqlite3"); if (!fileExists(databaseFile)) continue; if (modifiedSince > std::chrono::system_clock::time_point::min()) { time_t modificationTime; if (!getFileModificationTime(databaseFile, modificationTime)) continue; if (std::chrono::system_clock::from_time_t(modificationTime) < modifiedSince) continue; } SQLiteFileSystem::deleteDatabaseFile(databaseFile); deleteEmptyDirectory(databasePath); } deleteEmptyDirectory(originPath); }
static void removeAllDatabasesForOriginPath(const String& originPath, double startDate, double endDate) { // FIXME: We should also close/invalidate any live handles to the database files we are about to delete. // Right now: // - For read-only operations, they will continue functioning as normal on the unlinked file. // - For write operations, they will start producing errors as SQLite notices the missing backing store. // This is tracked by https://bugs.webkit.org/show_bug.cgi?id=135347 Vector<String> databasePaths = listDirectory(originPath, "*"); for (auto& databasePath : databasePaths) { String databaseFile = pathByAppendingComponent(databasePath, "IndexedDB.sqlite3"); if (!fileExists(databaseFile)) continue; time_t modTime; getFileModificationTime(databaseFile, modTime); if (modTime < startDate || modTime > endDate) continue; deleteFile(databaseFile); deleteEmptyDirectory(databasePath); } deleteEmptyDirectory(originPath); }
void LocalStorageDatabaseTracker::removeDatabaseWithOriginIdentifier(const String& originIdentifier) { openTrackerDatabase(SkipIfNonExistent); if (!m_database.isOpen()) return; String path = pathForDatabaseWithOriginIdentifier(originIdentifier); if (path.isEmpty()) return; SQLiteStatement deleteStatement(m_database, "DELETE FROM Origins where origin=?"); if (deleteStatement.prepare() != SQLITE_OK) { LOG_ERROR("Unable to prepare deletion of origin '%s'", originIdentifier.ascii().data()); return; } deleteStatement.bindText(1, originIdentifier); if (!deleteStatement.executeCommand()) { LOG_ERROR("Unable to execute deletion of origin '%s'", originIdentifier.ascii().data()); return; } SQLiteFileSystem::deleteDatabaseFile(path); m_origins.remove(originIdentifier); if (m_origins.isEmpty()) { // There are no origins left; delete the tracker database. m_database.close(); SQLiteFileSystem::deleteDatabaseFile(trackerDatabasePath()); deleteEmptyDirectory(m_localStorageDirectory); } // FIXME: Tell clients that the origin was removed. }
void FormData::removeGeneratedFilesIfNeeded() { for (FormDataElement& element : m_elements) { if (element.m_type == FormDataElement::Type::EncodedFile && element.m_ownsGeneratedFile) { ASSERT(!element.m_generatedFilename.isEmpty()); ASSERT(element.m_shouldGenerateFile); String directory = directoryName(element.m_generatedFilename); deleteFile(element.m_generatedFilename); deleteEmptyDirectory(directory); element.m_generatedFilename = String(); element.m_ownsGeneratedFile = false; } } }
void LocalStorageDatabaseTracker::deleteAllDatabases() { m_origins.clear(); openTrackerDatabase(SkipIfNonExistent); if (!m_database.isOpen()) return; SQLiteStatement statement(m_database, "SELECT origin, path FROM Origins"); if (statement.prepare() != SQLITE_OK) { LOG_ERROR("Failed to prepare statement."); return; } int result; while ((result = statement.step()) == SQLITE_ROW) { deleteFile(statement.getColumnText(1)); // FIXME: Call out to the client. } if (result != SQLITE_DONE) LOG_ERROR("Failed to read in all origins from the database."); if (m_database.isOpen()) m_database.close(); if (!deleteFile(trackerDatabasePath())) { // In the case where it is not possible to delete the database file (e.g some other program // like a virus scanner is accessing it), make sure to remove all entries. openTrackerDatabase(SkipIfNonExistent); if (!m_database.isOpen()) return; SQLiteStatement deleteStatement(m_database, "DELETE FROM Origins"); if (deleteStatement.prepare() != SQLITE_OK) { LOG_ERROR("Unable to prepare deletion of all origins"); return; } if (!deleteStatement.executeCommand()) { LOG_ERROR("Unable to execute deletion of all origins"); return; } } deleteEmptyDirectory(m_localStorageDirectory); }
void FormData::removeGeneratedFilesIfNeeded() { if (!m_hasGeneratedFiles) return; size_t n = m_elements.size(); for (size_t i = 0; i < n; ++i) { FormDataElement& e = m_elements[i]; if (e.m_type == FormDataElement::encodedFile && !e.m_generatedFilename.isEmpty()) { ASSERT(e.m_shouldGenerateFile); String directory = directoryName(e.m_generatedFilename); deleteFile(e.m_generatedFilename); deleteEmptyDirectory(directory); e.m_generatedFilename = String(); } } m_hasGeneratedFiles = false; }
bool SQLiteFileSystem::deleteEmptyDatabaseDirectory(const String& path) { return deleteEmptyDirectory(path); }
void StorageTracker::syncDeleteOrigin(const String& originIdentifier) { ASSERT(!isMainThread()); SQLiteTransactionInProgressAutoCounter transactionCounter; MutexLocker locker(m_databaseMutex); if (!canDeleteOrigin(originIdentifier)) { LOG_ERROR("Attempted to delete origin '%s' while it was being created\n", originIdentifier.ascii().data()); return; } openTrackerDatabase(false); if (!m_database.isOpen()) return; String path = databasePathForOrigin(originIdentifier); if (path.isEmpty()) { // It is possible to get a request from the API to delete the storage for an origin that // has no such storage. return; } SQLiteStatement deleteStatement(m_database, "DELETE FROM Origins where origin=?"); if (deleteStatement.prepare() != SQLResultOk) { LOG_ERROR("Unable to prepare deletion of origin '%s'", originIdentifier.ascii().data()); return; } deleteStatement.bindText(1, originIdentifier); if (!deleteStatement.executeCommand()) { LOG_ERROR("Unable to execute deletion of origin '%s'", originIdentifier.ascii().data()); return; } deleteFile(path); bool shouldDeleteTrackerFiles = false; { MutexLocker locker(m_originSetMutex); m_originSet.remove(originIdentifier); shouldDeleteTrackerFiles = m_originSet.isEmpty(); } if (shouldDeleteTrackerFiles) { #if PLATFORM(IOS) truncateDatabaseFile(m_database); #endif m_database.close(); #if !PLATFORM(IOS) deleteFile(trackerDatabasePath()); deleteEmptyDirectory(m_storageDirectoryPath); #endif } { MutexLocker locker(m_clientMutex); if (m_client) m_client->dispatchDidModifyOrigin(originIdentifier); } }
void StorageTracker::syncDeleteAllOrigins() { ASSERT(!isMainThread()); SQLiteTransactionInProgressAutoCounter transactionCounter; MutexLocker locker(m_databaseMutex); openTrackerDatabase(false); if (!m_database.isOpen()) return; SQLiteStatement statement(m_database, "SELECT origin, path FROM Origins"); if (statement.prepare() != SQLResultOk) { LOG_ERROR("Failed to prepare statement."); return; } int result; while ((result = statement.step()) == SQLResultRow) { if (!canDeleteOrigin(statement.getColumnText(0))) continue; deleteFile(statement.getColumnText(1)); { MutexLocker locker(m_clientMutex); if (m_client) m_client->dispatchDidModifyOrigin(statement.getColumnText(0)); } } if (result != SQLResultDone) LOG_ERROR("Failed to read in all origins from the database."); if (m_database.isOpen()) { #if PLATFORM(IOS) truncateDatabaseFile(m_database); #endif m_database.close(); } #if !PLATFORM(IOS) if (!deleteFile(trackerDatabasePath())) { // In the case where it is not possible to delete the database file (e.g some other program // like a virus scanner is accessing it), make sure to remove all entries. openTrackerDatabase(false); if (!m_database.isOpen()) return; SQLiteStatement deleteStatement(m_database, "DELETE FROM Origins"); if (deleteStatement.prepare() != SQLResultOk) { LOG_ERROR("Unable to prepare deletion of all origins"); return; } if (!deleteStatement.executeCommand()) { LOG_ERROR("Unable to execute deletion of all origins"); return; } } deleteEmptyDirectory(m_storageDirectoryPath); #endif }