Skip to content

Commit

Permalink
Delete corrupted localstorage db
Browse files Browse the repository at this point in the history
  • Loading branch information
emutavchi committed Mar 14, 2022
1 parent c73a0db commit c3dbb59
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 12 deletions.
61 changes: 50 additions & 11 deletions Source/WebKit/NetworkProcess/WebStorage/LocalStorageDatabase.cpp
Expand Up @@ -169,14 +169,17 @@ void LocalStorageDatabase::importItems(StorageMap& storageMap)
return;

SQLiteStatement query(m_database, "SELECT key, value FROM ItemTable"_str);
if (query.prepare() != SQLITE_OK) {
LOG_ERROR("Unable to select items from ItemTable for local storage");
int result = query.prepare();
if (result != SQLITE_OK) {
LOG_ERROR("Unable to select items from ItemTable for local storage - %i", result);
if (result == SQLITE_CORRUPT || result == SQLITE_NOTADB)
handleDatabaseCorruption();
return;
}

HashMap<String, String> items;

int result = query.step();
result = query.step();
while (result == SQLITE_ROW) {
String key = query.getColumnText(0);
String value = query.getColumnBlobAsString(1);
Expand All @@ -186,7 +189,9 @@ void LocalStorageDatabase::importItems(StorageMap& storageMap)
}

if (result != SQLITE_DONE) {
LOG_ERROR("Error reading items from ItemTable for local storage");
LOG_ERROR("Error reading items from ItemTable for local storage - %i", result);
if (result == SQLITE_CORRUPT || result == SQLITE_NOTADB)
handleDatabaseCorruption();
return;
}

Expand All @@ -207,6 +212,7 @@ void LocalStorageDatabase::clear()
{
m_changedItems.clear();
m_shouldClearItems = true;
m_restoreHandler = nullptr;

scheduleDatabaseUpdate();
}
Expand All @@ -215,6 +221,7 @@ void LocalStorageDatabase::close()
{
ASSERT(!m_isClosed);
m_isClosed = true;
m_restoreHandler = nullptr;

if (m_didScheduleDatabaseUpdate) {
updateDatabaseWithChangedItems(m_changedItems);
Expand Down Expand Up @@ -287,31 +294,40 @@ void LocalStorageDatabase::updateDatabaseWithChangedItems(const HashMap<String,
if (!m_database.isOpen())
return;

int result;
if (m_shouldClearItems) {
m_shouldClearItems = false;

SQLiteStatement clearStatement(m_database, "DELETE FROM ItemTable");
if (clearStatement.prepare() != SQLITE_OK) {
LOG_ERROR("Failed to prepare clear statement - cannot write to local storage database");
if ((result = clearStatement.prepare()) != SQLITE_OK) {
LOG_ERROR("Failed to prepare clear statement - cannot write to local storage database - %i", result);
if (result == SQLITE_CORRUPT)
handleDatabaseCorruption();
return;
}

int result = clearStatement.step();
result = clearStatement.step();
if (result != SQLITE_DONE) {
LOG_ERROR("Failed to clear all items in the local storage database - %i", result);
if (result == SQLITE_CORRUPT)
handleDatabaseCorruption();
return;
}
}

SQLiteStatement insertStatement(m_database, "INSERT INTO ItemTable VALUES (?, ?)");
if (insertStatement.prepare() != SQLITE_OK) {
LOG_ERROR("Failed to prepare insert statement - cannot write to local storage database");
if ((result = insertStatement.prepare()) != SQLITE_OK) {
LOG_ERROR("Failed to prepare insert statement - cannot write to local storage database - %i", result);
if (result == SQLITE_CORRUPT)
handleDatabaseCorruption();
return;
}

SQLiteStatement deleteStatement(m_database, "DELETE FROM ItemTable WHERE key=?");
if (deleteStatement.prepare() != SQLITE_OK) {
LOG_ERROR("Failed to prepare delete statement - cannot write to local storage database");
if ((result = deleteStatement.prepare()) != SQLITE_OK) {
LOG_ERROR("Failed to prepare delete statement - cannot write to local storage database - %i", result);
if (result == SQLITE_CORRUPT)
handleDatabaseCorruption();
return;
}

Expand All @@ -331,6 +347,12 @@ void LocalStorageDatabase::updateDatabaseWithChangedItems(const HashMap<String,
int result = statement.step();
if (result != SQLITE_DONE) {
LOG_ERROR("Failed to update item in the local storage database - %i", result);
if (result == SQLITE_CORRUPT) {
statement.finalize();
transaction.stop();
handleDatabaseCorruption();
return;
}
break;
}

Expand Down Expand Up @@ -360,4 +382,21 @@ bool LocalStorageDatabase::databaseIsEmpty()
return !query.getColumnInt(0);
}

void LocalStorageDatabase::setRestoreHandler(Function<void()>&& restoreHandler)
{
m_restoreHandler = WTFMove(restoreHandler);
}

void LocalStorageDatabase::handleDatabaseCorruption()
{
if (m_database.isOpen())
m_database.close();
m_changedItems.clear();
m_tracker->deleteDatabaseWithOrigin(m_securityOrigin);
LOG_ERROR("Deleted corrupted local storage database - '%s'", m_databasePath.utf8().data());
auto restoreHandler = WTFMove(m_restoreHandler);
if (restoreHandler)
restoreHandler();
}

} // namespace WebKit
Expand Up @@ -59,6 +59,8 @@ class LocalStorageDatabase : public RefCounted<LocalStorageDatabase> {
// Will block until all pending changes have been written to disk.
void close();

void setRestoreHandler(Function<void()>&&);

private:
LocalStorageDatabase(Ref<WorkQueue>&&, Ref<LocalStorageDatabaseTracker>&&, const WebCore::SecurityOriginData&);

Expand All @@ -77,6 +79,7 @@ class LocalStorageDatabase : public RefCounted<LocalStorageDatabase> {
void updateDatabaseWithChangedItems(const HashMap<String, String>&);

bool databaseIsEmpty();
void handleDatabaseCorruption();

Ref<WorkQueue> m_queue;
Ref<LocalStorageDatabaseTracker> m_tracker;
Expand All @@ -93,6 +96,7 @@ class LocalStorageDatabase : public RefCounted<LocalStorageDatabase> {
HashMap<String, String> m_changedItems;

std::unique_ptr<WebCore::SuddenTerminationDisabler> m_disableSuddenTerminationWhileWritingToLocalStorage;
Function<void()> m_restoreHandler;
};


Expand Down
11 changes: 10 additions & 1 deletion Source/WebKit/NetworkProcess/WebStorage/StorageArea.cpp
Expand Up @@ -178,9 +178,18 @@ void StorageArea::openDatabaseAndImportItemsIfNeeded() const

ASSERT(m_localStorageNamespace->storageManager()->localStorageDatabaseTracker());
// We open the database here even if we've already imported our items to ensure that the database is open if we need to write to it.
if (!m_localStorageDatabase)
if (!m_localStorageDatabase) {
m_localStorageDatabase = LocalStorageDatabase::create(m_queue.copyRef(), *m_localStorageNamespace->storageManager()->localStorageDatabaseTracker(), m_securityOrigin);

m_localStorageDatabase->setRestoreHandler([this] () {
if (m_storageMap && m_localStorageDatabase) {
for (const auto& entry : m_storageMap->items()) {
m_localStorageDatabase->setItem(entry.key, entry.value);
}
}
});
}

if (m_didImportItemsFromDatabase)
return;

Expand Down

0 comments on commit c3dbb59

Please sign in to comment.