Realm: allow to clear corrupted session db

This commit is contained in:
ganfra 2019-09-30 19:09:10 +02:00
parent 7817f49072
commit b5c6c1af0d
2 changed files with 77 additions and 11 deletions

View File

@ -0,0 +1,73 @@
/*
* Copyright 2019 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.matrix.android.internal.database
import android.content.Context
import im.vector.matrix.android.internal.database.model.SessionRealmModule
import im.vector.matrix.android.internal.session.SessionModule
import io.realm.Realm
import io.realm.RealmConfiguration
import timber.log.Timber
import java.io.File
import javax.inject.Inject
private const val REALM_SHOULD_CLEAR_FLAG_ = "REALM_SHOULD_CLEAR_FLAG_"
/**
* This class is handling creation of RealmConfiguration for a session.
* It will handle corrupted realm by clearing the db file. It allows to just clear cache without losing your crypto keys.
* It's clearly not perfect but there is no way to catch the native crash.
*/
internal class SessionRealmConfigurationFactory @Inject constructor(private val realmKeysUtils: RealmKeysUtils,
context: Context) {
private val sharedPreferences = context.getSharedPreferences("im.vector.matrix.android.realm", Context.MODE_PRIVATE)
fun create(directory: File, userMd5: String): RealmConfiguration {
val shouldClearRealm = sharedPreferences.getBoolean("$REALM_SHOULD_CLEAR_FLAG_$userMd5", false)
if (shouldClearRealm) {
directory.deleteRecursively()
}
sharedPreferences
.edit()
.putBoolean("$REALM_SHOULD_CLEAR_FLAG_$userMd5", true)
.apply()
val realmConfiguration = RealmConfiguration.Builder()
.directory(directory)
.name("disk_store.realm")
.apply {
realmKeysUtils.configureEncryption(this, "${SessionModule.DB_ALIAS_PREFIX}$userMd5")
}
.modules(SessionRealmModule())
.deleteRealmIfMigrationNeeded()
.build()
// Try creating a realm instance and if it succeeds we can clear the flag
Realm.getInstance(realmConfiguration).use {
Timber.v("Successfully create realm instance")
sharedPreferences
.edit()
.putBoolean("$REALM_SHOULD_CLEAR_FLAG_$userMd5", false)
.apply()
}
return realmConfiguration
}
}

View File

@ -30,7 +30,7 @@ import im.vector.matrix.android.api.session.Session
import im.vector.matrix.android.api.session.homeserver.HomeServerCapabilitiesService
import im.vector.matrix.android.api.session.securestorage.SecureStorageService
import im.vector.matrix.android.internal.database.LiveEntityObserver
import im.vector.matrix.android.internal.database.RealmKeysUtils
import im.vector.matrix.android.internal.database.SessionRealmConfigurationFactory
import im.vector.matrix.android.internal.database.model.SessionRealmModule
import im.vector.matrix.android.internal.di.*
import im.vector.matrix.android.internal.network.AccessTokenInterceptor
@ -54,6 +54,7 @@ internal abstract class SessionModule {
@Module
companion object {
internal const val DB_ALIAS_PREFIX = "session_db_"
@JvmStatic
@ -94,18 +95,10 @@ internal abstract class SessionModule {
@Provides
@SessionDatabase
@SessionScope
fun providesRealmConfiguration(realmKeysUtils: RealmKeysUtils,
fun providesRealmConfiguration(realmConfigurationFactory: SessionRealmConfigurationFactory,
@UserCacheDirectory directory: File,
@UserMd5 userMd5: String): RealmConfiguration {
return RealmConfiguration.Builder()
.directory(directory)
.name("disk_store.realm")
.apply {
realmKeysUtils.configureEncryption(this, "$DB_ALIAS_PREFIX$userMd5")
}
.modules(SessionRealmModule())
.deleteRealmIfMigrationNeeded()
.build()
return realmConfigurationFactory.create(directory, userMd5)
}
@JvmStatic