Migrated core db to mail app db.

MAILAND-1525
This commit is contained in:
Tomasz Giszczak 2021-08-16 14:50:04 +02:00 committed by stefanija
parent 2086ac1aab
commit af353ed1e3
6 changed files with 282 additions and 30 deletions

View File

@ -266,7 +266,7 @@ public abstract class BaseActivity extends AppCompatActivity implements INetwork
enableScreenshotProtector();
}
app.setAppInBackground(false);
NetworkConfigurator.Companion.setNetworkConfiguratorCallback(this);
networkConfigurator.setNetworkConfiguratorCallback(this);
accountStateManager.setHumanVerificationOrchestrator(humanVerificationOrchestrator);
}
@ -274,6 +274,7 @@ public abstract class BaseActivity extends AppCompatActivity implements INetwork
@Override
protected void onPause() {
app.setAppInBackground(true);
networkConfigurator.removeNetworkConfiguratorCallback();
super.onPause();
}

View File

@ -54,6 +54,7 @@ class NetworkConfigurator @Inject constructor(
lateinit var networkSwitcher: INetworkSwitcher
private var isRunning = false
var callback: INetworkConfiguratorCallback? = null
fun refreshDomainsAsync() = scope.launch {
if (!isRunning) {
@ -187,11 +188,12 @@ class NetworkConfigurator @Inject constructor(
}
}
companion object {
var callback: INetworkConfiguratorCallback? = null
fun setNetworkConfiguratorCallback(callback: INetworkConfiguratorCallback) {
this.callback = callback
}
fun setNetworkConfiguratorCallback(callback: INetworkConfiguratorCallback) {
this.callback = callback
}
fun removeNetworkConfiguratorCallback() {
callback = null
}
}

View File

@ -0,0 +1,154 @@
/*
* Copyright (c) 2020 Proton Technologies AG
*
* This file is part of ProtonMail.
*
* ProtonMail is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ProtonMail is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ProtonMail. If not, see https://www.gnu.org/licenses/.
*/
package ch.protonmail.android.data
import android.content.Context
import androidx.room.Database
import androidx.room.TypeConverters
import androidx.room.migration.Migration
import androidx.sqlite.db.SupportSQLiteDatabase
import ch.protonmail.android.data.local.ContactDao
import ch.protonmail.android.data.local.model.ContactData
import ch.protonmail.android.data.local.model.ContactEmail
import ch.protonmail.android.data.local.model.ContactEmailContactLabelJoin
import ch.protonmail.android.data.local.model.FullContactDetails
import ch.protonmail.android.data.local.model.FullContactDetailsConverter
import ch.protonmail.android.data.local.model.LabelEntity
import me.proton.core.account.data.db.AccountConverters
import me.proton.core.account.data.db.AccountDatabase
import me.proton.core.account.data.entity.AccountEntity
import me.proton.core.account.data.entity.AccountMetadataEntity
import me.proton.core.account.data.entity.SessionDetailsEntity
import me.proton.core.account.data.entity.SessionEntity
import me.proton.core.accountmanager.data.db.AccountManagerDatabase
import me.proton.core.crypto.android.keystore.CryptoConverters
import me.proton.core.data.room.db.BaseDatabase
import me.proton.core.data.room.db.CommonConverters
import me.proton.core.humanverification.data.db.HumanVerificationConverters
import me.proton.core.humanverification.data.db.HumanVerificationDatabase
import me.proton.core.humanverification.data.entity.HumanVerificationEntity
import me.proton.core.key.data.db.KeySaltDatabase
import me.proton.core.key.data.db.PublicAddressDatabase
import me.proton.core.key.data.entity.KeySaltEntity
import me.proton.core.key.data.entity.PublicAddressEntity
import me.proton.core.key.data.entity.PublicAddressKeyEntity
import me.proton.core.mailsettings.data.db.MailSettingsDatabase
import me.proton.core.mailsettings.data.entity.MailSettingsEntity
import me.proton.core.user.data.db.AddressDatabase
import me.proton.core.user.data.db.UserConverters
import me.proton.core.user.data.db.UserDatabase
import me.proton.core.user.data.entity.AddressEntity
import me.proton.core.user.data.entity.AddressKeyEntity
import me.proton.core.user.data.entity.UserEntity
import me.proton.core.user.data.entity.UserKeyEntity
import timber.log.Timber
@Database(
entities = [
// Core
AccountEntity::class,
AccountMetadataEntity::class,
AddressEntity::class,
AddressKeyEntity::class,
HumanVerificationEntity::class,
KeySaltEntity::class,
MailSettingsEntity::class,
PublicAddressEntity::class,
PublicAddressKeyEntity::class,
SessionEntity::class,
SessionDetailsEntity::class,
UserEntity::class,
UserKeyEntity::class,
// Mail - Contacts
ContactData::class,
ContactEmail::class,
LabelEntity::class,
FullContactDetails::class,
ContactEmailContactLabelJoin::class
],
version = AppDatabase.version,
exportSchema = true
)
@TypeConverters(
// Core
CommonConverters::class,
AccountConverters::class,
UserConverters::class,
CryptoConverters::class,
HumanVerificationConverters::class,
// Mail - Contacts
FullContactDetailsConverter::class
)
abstract class AppDatabase :
BaseDatabase(),
AccountDatabase,
UserDatabase,
AddressDatabase,
KeySaltDatabase,
HumanVerificationDatabase,
PublicAddressDatabase,
MailSettingsDatabase {
abstract fun contactDao(): ContactDao
companion object {
const val version = 1
private const val name = "db-proton-mail"
private fun getDbCreationCallback(context: Context): Callback = object : Callback() {
override fun onCreate(db: SupportSQLiteDatabase) {
super.onCreate(db)
Timber.v("New $name DB created")
// Initial migration from "old" core DB to the new Mail app db.
val accountManagerDatabase = AccountManagerDatabase.databaseBuilder(context)
.allowMainThreadQueries()
.build()
val migration01 = AppDatabaseMigrations.initialMigration(context, accountManagerDatabase)
migration01.migrate(db)
}
override fun onOpen(db: SupportSQLiteDatabase) {
super.onOpen(db)
Timber.v("$name DB open")
}
}
private fun getMigrations(): Array<Migration> {
val migrations = emptyArray<Migration>()
Timber.v("Db migrations list size ${migrations.size}")
return migrations
}
fun buildDatabase(context: Context): AppDatabase {
Timber.v("Building $name database")
return databaseBuilder<AppDatabase>(context, name)
.apply {
addCallback(getDbCreationCallback(context))
addMigrations(*getMigrations())
}
.build()
}
}
}

View File

@ -0,0 +1,99 @@
/*
* Copyright (c) 2020 Proton Technologies AG
*
* This file is part of ProtonMail.
*
* ProtonMail is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ProtonMail is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ProtonMail. If not, see https://www.gnu.org/licenses/.
*/
package ch.protonmail.android.data
import android.content.Context
import androidx.room.migration.Migration
import androidx.sqlite.db.SupportSQLiteDatabase
import me.proton.core.account.data.entity.AccountEntity
import me.proton.core.account.data.entity.AccountMetadataEntity
import me.proton.core.account.data.entity.SessionDetailsEntity
import me.proton.core.account.data.entity.SessionEntity
import me.proton.core.accountmanager.data.db.AccountManagerDatabase
import me.proton.core.data.room.db.extension.open
import me.proton.core.data.room.db.extension.openAndClose
import me.proton.core.humanverification.data.entity.HumanVerificationEntity
import me.proton.core.key.data.entity.KeySaltEntity
import me.proton.core.key.data.entity.PublicAddressEntity
import me.proton.core.key.data.entity.PublicAddressKeyEntity
import me.proton.core.mailsettings.data.entity.MailSettingsEntity
import me.proton.core.user.data.entity.AddressEntity
import me.proton.core.user.data.entity.AddressKeyEntity
import me.proton.core.user.data.entity.UserEntity
import me.proton.core.user.data.entity.UserKeyEntity
import timber.log.Timber
object AppDatabaseMigrations {
/**
* Copy Core DB into Proton Mail DB.
*/
fun initialMigration(context: Context, coreDatabase: AccountManagerDatabase) = object : Migration(0, 1) {
override fun migrate(database: SupportSQLiteDatabase) {
Timber.v("Initial core db migration")
// Force any migration for coreDatabase by opening then closing it.
coreDatabase.openAndClose()
// End current transaction (from FrameworkSQLiteOpenHelper.onUpgrade(db, version, mNewVersion))
if (database.inTransaction()) {
database.setTransactionSuccessful()
database.endTransaction()
}
// Attach old Core DB to current DB (cannot be done within a transaction).
val coreDbPath = context.getDatabasePath(AccountManagerDatabase.name).path
database.execSQL("ATTACH DATABASE '$coreDbPath' AS coreDb")
// Begin transaction for attached migration.
database.beginTransaction()
// Import all data from Core DB to current DB.
listOf(
AccountEntity::class.simpleName,
AccountMetadataEntity::class.simpleName,
AddressEntity::class.simpleName,
AddressKeyEntity::class.simpleName,
UserEntity::class.simpleName,
UserKeyEntity::class.simpleName,
HumanVerificationEntity::class.simpleName,
KeySaltEntity::class.simpleName,
MailSettingsEntity::class.simpleName,
PublicAddressEntity::class.simpleName,
PublicAddressKeyEntity::class.simpleName,
SessionDetailsEntity::class.simpleName,
SessionEntity::class.simpleName
).forEach { table ->
Timber.v("Insert table $table")
database.execSQL("INSERT INTO main.$table SELECT * FROM coreDb.$table")
}
// End current transaction to detach coreDb.
if (database.inTransaction()) {
database.setTransactionSuccessful()
database.endTransaction()
}
database.execSQL("DETACH DATABASE coreDb")
database.beginTransaction()
// Clear old Core tables.
coreDatabase.open()
coreDatabase.runInTransaction { coreDatabase.clearAllTables() }
coreDatabase.close()
}
}
}

View File

@ -18,15 +18,12 @@
package ch.protonmail.android.di
import android.content.Context
import ch.protonmail.android.data.AppDatabase
import dagger.Binds
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import me.proton.core.account.data.db.AccountDatabase
import me.proton.core.accountmanager.data.db.AccountManagerDatabase
import me.proton.core.humanverification.data.db.HumanVerificationDatabase
import me.proton.core.key.data.db.KeySaltDatabase
import me.proton.core.key.data.db.PublicAddressDatabase
@ -34,41 +31,31 @@ import me.proton.core.mailsettings.data.db.MailSettingsDatabase
import me.proton.core.user.data.db.AddressDatabase
import me.proton.core.user.data.db.UserDatabase
import me.proton.core.usersettings.data.db.UserSettingsDatabase
import javax.inject.Singleton
@Module
@InstallIn(SingletonComponent::class)
object AppDatabaseModule {
@Provides
@Singleton
fun provideAccountManagerDatabase(@ApplicationContext context: Context): AccountManagerDatabase =
AccountManagerDatabase.buildDatabase(context)
}
@Module
@InstallIn(SingletonComponent::class)
abstract class AppDatabaseBindsModule {
abstract class CoreDatabaseBindsModule {
@Binds
abstract fun provideAccountDatabase(db: AccountManagerDatabase): AccountDatabase
abstract fun provideAccountDatabase(db: AppDatabase): AccountDatabase
@Binds
abstract fun provideUserDatabase(db: AccountManagerDatabase): UserDatabase
abstract fun provideUserDatabase(db: AppDatabase): UserDatabase
@Binds
abstract fun provideAddressDatabase(db: AccountManagerDatabase): AddressDatabase
abstract fun provideAddressDatabase(db: AppDatabase): AddressDatabase
@Binds
abstract fun provideKeySaltDatabase(db: AccountManagerDatabase): KeySaltDatabase
abstract fun provideKeySaltDatabase(db: AppDatabase): KeySaltDatabase
@Binds
abstract fun providePublicAddressDatabase(db: AccountManagerDatabase): PublicAddressDatabase
abstract fun providePublicAddressDatabase(db: AppDatabase): PublicAddressDatabase
@Binds
abstract fun provideHumanVerificationDatabase(db: AccountManagerDatabase): HumanVerificationDatabase
abstract fun provideHumanVerificationDatabase(db: AppDatabase): HumanVerificationDatabase
@Binds
abstract fun provideMailSettingsDatabase(db: AccountManagerDatabase): MailSettingsDatabase
abstract fun provideMailSettingsDatabase(db: AppDatabase): MailSettingsDatabase
@Binds
abstract fun provideUserSettingsDatabase(db: AccountManagerDatabase): UserSettingsDatabase

View File

@ -21,6 +21,7 @@ package ch.protonmail.android.di
import android.content.Context
import ch.protonmail.android.core.UserManager
import ch.protonmail.android.data.AppDatabase
import ch.protonmail.android.data.local.AttachmentMetadataDao
import ch.protonmail.android.data.local.AttachmentMetadataDatabase
import ch.protonmail.android.data.local.ContactDao
@ -31,18 +32,26 @@ import ch.protonmail.android.data.local.MessageDao
import ch.protonmail.android.data.local.MessageDatabase
import ch.protonmail.android.data.local.PendingActionDao
import ch.protonmail.android.data.local.PendingActionDatabase
import me.proton.core.domain.entity.UserId
import ch.protonmail.android.mailbox.data.local.ConversationDao
import ch.protonmail.android.mailbox.data.local.UnreadCounterDao
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import me.proton.core.domain.entity.UserId
import javax.inject.Singleton
@Module
@InstallIn(SingletonComponent::class)
internal object DatabaseModule {
@Provides
@Singleton
fun provideAppDatabase(
@ApplicationContext context: Context
): AppDatabase = AppDatabase.buildDatabase(context)
@Provides
fun provideAttachmentMetadataDao(
context: Context,