Skip to content

Commit 65be942

Browse files
SconyPawel Lampe
authored andcommitted
Restore local storage after corruption
1 parent 17dc635 commit 65be942

2 files changed

Lines changed: 25 additions & 10 deletions

File tree

Source/WebKit/NetworkProcess/storage/SQLiteStorageArea.cpp

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,17 @@ HashMap<String, String> SQLiteStorageArea::allItems()
324324
}
325325

326326
Expected<void, StorageError> SQLiteStorageArea::setItem(IPC::Connection::UniqueID connection, StorageAreaImplIdentifier storageAreaImplID, String&& key, String&& value, const String& urlString)
327+
{
328+
String oldValue;
329+
if (auto valueOrError = getItem(key))
330+
oldValue = valueOrError.value();
331+
auto settingOutcome = setItem(key, value, true);
332+
if (settingOutcome)
333+
dispatchEvents(connection, storageAreaImplID, key, oldValue, value, urlString);
334+
return settingOutcome;
335+
}
336+
337+
Expected<void, StorageError> SQLiteStorageArea::setItem(const String& key, const String& value, bool handleDatabaseCorruption)
327338
{
328339
ASSERT(!isMainRunLoop());
329340

@@ -334,9 +345,6 @@ Expected<void, StorageError> SQLiteStorageArea::setItem(IPC::Connection::UniqueI
334345
return makeUnexpected(StorageError::QuotaExceeded);
335346

336347
startTransactionIfNecessary();
337-
String oldValue;
338-
if (auto valueOrError = getItem(key))
339-
oldValue = valueOrError.value();
340348

341349
auto statement = cachedStatement(StatementType::SetItem);
342350
if (!statement || statement->bindText(1, key) || statement->bindBlob(2, value)) {
@@ -346,12 +354,13 @@ Expected<void, StorageError> SQLiteStorageArea::setItem(IPC::Connection::UniqueI
346354

347355
const auto result = statement->step();
348356
if (result != SQLITE_DONE) {
349-
RELEASE_LOG_ERROR(Storage, "SQLiteStorageArea::setItem failed on stepping statement (%d) - %s", m_database->lastError(), m_database->lastErrorMsg());
350-
handleDatabaseCorruptionIfNeeded(result);
351-
return makeUnexpected(StorageError::Database);
357+
if (!handleDatabaseCorruption || !handleDatabaseCorruptionIfNeeded(result))
358+
return makeUnexpected(StorageError::Database);
359+
statement = cachedStatement(StatementType::SetItem);
360+
if (!statement || statement->bindText(1, key) || statement->bindBlob(2, value) || statement->step() != SQLITE_DONE)
361+
return makeUnexpected(StorageError::Database);
352362
}
353363

354-
dispatchEvents(connection, storageAreaImplID, key, oldValue, value, urlString);
355364
updateCacheIfNeeded(key, value);
356365

357366
return { };
@@ -454,11 +463,16 @@ bool SQLiteStorageArea::handleDatabaseCorruptionIfNeeded(int databaseError)
454463
if (databaseError != SQLITE_CORRUPT && databaseError != SQLITE_NOTADB)
455464
return false;
456465

457-
m_database = nullptr;
458-
m_cache = std::nullopt;
459-
m_cacheSize = std::nullopt;
466+
HashMap<String, Value> cache(WTFMove(*m_cache));
467+
close();
460468
RELEASE_LOG(Storage, "SQLiteStorageArea::handleDatabaseCorruption deletes corrupted database file '%s'", m_path.utf8().data());
461469
WebCore::SQLiteFileSystem::deleteDatabaseFile(m_path);
470+
471+
// Reconstruct database based on cache.
472+
for (auto& [key, value] : cache)
473+
if (auto* valueString = std::get_if<String>(&value))
474+
setItem(key, *valueString, false);
475+
462476
return true;
463477
}
464478

Source/WebKit/NetworkProcess/storage/SQLiteStorageArea.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ class SQLiteStorageArea final : public StorageAreaBase {
4848
void clear() final;
4949
HashMap<String, String> allItems() final;
5050
Expected<void, StorageError> setItem(IPC::Connection::UniqueID, StorageAreaImplIdentifier, String&& key, String&& value, const String& urlString) final;
51+
Expected<void, StorageError> setItem(const String& key, const String& value, bool handleDatabaseCorruption);
5152
Expected<void, StorageError> removeItem(IPC::Connection::UniqueID, StorageAreaImplIdentifier, const String& key, const String& urlString) final;
5253
Expected<void, StorageError> clear(IPC::Connection::UniqueID, StorageAreaImplIdentifier, const String& urlString) final;
5354

0 commit comments

Comments
 (0)