Better database loading code

This commit is contained in:
J-Jamet
2019-10-17 14:07:39 +02:00
parent b25180c617
commit 214e2cf109
7 changed files with 86 additions and 109 deletions

View File

@@ -878,13 +878,18 @@ class GroupActivity : LockingActivity(),
private const val SEARCH_FRAGMENT_TAG = "SEARCH_FRAGMENT_TAG"
private const val OLD_GROUP_TO_UPDATE_KEY = "OLD_GROUP_TO_UPDATE_KEY"
private fun buildAndLaunchIntent(activity: Activity, group: GroupVersioned?, readOnly: Boolean,
private fun buildAndLaunchIntent(context: Context, group: GroupVersioned?, readOnly: Boolean,
intentBuildLauncher: (Intent) -> Unit) {
if (TimeoutHelper.checkTimeAndLockIfTimeout(activity)) {
val intent = Intent(activity, GroupActivity::class.java)
val checkTime = if (context is Activity)
TimeoutHelper.checkTimeAndLockIfTimeout(context)
else
TimeoutHelper.checkTime(context)
if (checkTime) {
val intent = Intent(context, GroupActivity::class.java)
if (group != null) {
intent.putExtra(GROUP_ID_KEY, group.nodeId)
}
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
ReadOnlyHelper.putReadOnlyInIntent(intent, readOnly)
intentBuildLauncher.invoke(intent)
}
@@ -897,10 +902,10 @@ class GroupActivity : LockingActivity(),
*/
@JvmOverloads
fun launch(activity: Activity, readOnly: Boolean = PreferencesUtil.enableReadOnlyDatabase(activity)) {
TimeoutHelper.recordTime(activity)
buildAndLaunchIntent(activity, null, readOnly) { intent ->
activity.startActivity(intent)
fun launch(context: Context, readOnly: Boolean = PreferencesUtil.enableReadOnlyDatabase(context)) {
TimeoutHelper.recordTime(context)
buildAndLaunchIntent(context, null, readOnly) { intent ->
context.startActivity(intent)
}
}
@@ -911,10 +916,10 @@ class GroupActivity : LockingActivity(),
*/
// TODO implement pre search to directly open the direct group
fun launchForKeyboarSelection(activity: Activity, readOnly: Boolean) {
TimeoutHelper.recordTime(activity)
buildAndLaunchIntent(activity, null, readOnly) { intent ->
EntrySelectionHelper.startActivityForEntrySelection(activity, intent)
fun launchForKeyboardSelection(context: Context, readOnly: Boolean) {
TimeoutHelper.recordTime(context)
buildAndLaunchIntent(context, null, readOnly) { intent ->
EntrySelectionHelper.startActivityForEntrySelection(context, intent)
}
}

View File

@@ -22,7 +22,6 @@ package com.kunzisoft.keepass.activities
import android.app.Activity
import android.app.assist.AssistStructure
import android.app.backup.BackupManager
import android.content.DialogInterface
import android.content.Intent
import android.content.SharedPreferences
import android.net.Uri
@@ -49,13 +48,11 @@ import com.google.android.material.snackbar.Snackbar
import com.kunzisoft.keepass.R
import com.kunzisoft.keepass.activities.dialogs.DuplicateUuidDialog
import com.kunzisoft.keepass.activities.dialogs.FingerPrintExplanationDialog
import com.kunzisoft.keepass.activities.dialogs.PasswordEncodingDialogFragment
import com.kunzisoft.keepass.activities.helpers.EntrySelectionHelper
import com.kunzisoft.keepass.activities.helpers.OpenFileHelper
import com.kunzisoft.keepass.activities.helpers.ReadOnlyHelper
import com.kunzisoft.keepass.activities.lock.LockingActivity
import com.kunzisoft.keepass.activities.stylish.StylishActivity
import com.kunzisoft.keepass.app.database.CipherDatabaseAction
import com.kunzisoft.keepass.app.database.CipherDatabaseEntity
import com.kunzisoft.keepass.app.database.FileDatabaseHistoryAction
import com.kunzisoft.keepass.autofill.AutofillHelper
@@ -64,8 +61,11 @@ import com.kunzisoft.keepass.database.action.ProgressDialogThread
import com.kunzisoft.keepass.database.element.Database
import com.kunzisoft.keepass.database.exception.LoadDatabaseDuplicateUuidException
import com.kunzisoft.keepass.education.PasswordActivityEducation
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_LOAD_TASK
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.CIPHER_ENTITY_KEY
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.DATABASE_URI_KEY
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.KEY_FILE_KEY
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.MASTER_PASSWORD_KEY
import com.kunzisoft.keepass.settings.PreferencesUtil
import com.kunzisoft.keepass.utils.FileDatabaseInfo
import com.kunzisoft.keepass.utils.MenuUtil
@@ -180,36 +180,31 @@ class PasswordActivity : StylishActivity() {
var cipherEntity: CipherDatabaseEntity? = null
result.data?.let { resultData ->
databaseUri = resultData.getParcelable(DatabaseTaskNotificationService.DATABASE_URI_KEY)
masterPassword = resultData.getString(DatabaseTaskNotificationService.MASTER_PASSWORD_KEY)
keyFileUri = resultData.getParcelable(DatabaseTaskNotificationService.KEY_FILE_KEY)
cipherEntity = resultData.getParcelable(DatabaseTaskNotificationService.CIPHER_ENTITY_KEY)
databaseUri = resultData.getParcelable(DATABASE_URI_KEY)
masterPassword = resultData.getString(MASTER_PASSWORD_KEY)
keyFileUri = resultData.getParcelable(KEY_FILE_KEY)
cipherEntity = resultData.getParcelable(CIPHER_ENTITY_KEY)
}
databaseUri?.let { databaseFileUri ->
// Remove the password in view in all cases
removePassword()
if (result.isSuccess) {
// Save keyFile in app database
if (mRememberKeyFile) {
saveKeyFileData(databaseFileUri, mDatabaseKeyFileUri)
}
// Remove the password in view in all cases
removePassword()
// Register the biometric
cipherEntity?.let { cipherDatabaseEntity ->
CipherDatabaseAction.getInstance(this@PasswordActivity)
.addOrUpdateCipherDatabase(cipherDatabaseEntity) {
checkAndLaunchGroupActivity(Database.getInstance(),
masterPassword,
keyFileUri)
EntrySelectionHelper.doEntrySelectionAction(intent,
{
GroupActivity.launch(this@PasswordActivity, readOnly)
},
{
GroupActivity.launchForKeyboardSelection(this@PasswordActivity, readOnly)
// Do not keep history
finish()
},
{ assistStructure ->
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
GroupActivity.launchForAutofillResult(this@PasswordActivity, assistStructure, readOnly)
}
} ?: run {
checkAndLaunchGroupActivity(Database.getInstance(),
masterPassword,
keyFileUri)
}
})
} else {
var resultError = ""
val resultException = result.exception
@@ -509,10 +504,6 @@ class PasswordActivity : StylishActivity() {
removePassword()
}
// Clear before we load
val database = Database.getInstance()
database.closeAndClear(applicationContext.filesDir)
databaseFileUri?.let { databaseUri ->
// Show the progress dialog and load the database
showProgressDialogAndLoadDatabase(
@@ -534,8 +525,6 @@ class PasswordActivity : StylishActivity() {
password,
keyFile,
cipherDatabaseEntity,
filesDir,
PreferencesUtil.omitBackup(this@PasswordActivity),
fixDuplicateUUID
)
}
@@ -546,44 +535,6 @@ class PasswordActivity : StylishActivity() {
}.show(supportFragmentManager, "duplicateUUIDDialog")
}
private fun saveKeyFileData(databaseUri: Uri, keyUri: Uri?) {
var keyFileUri = keyUri
if (!mRememberKeyFile) {
keyFileUri = null
}
FileDatabaseHistoryAction.getInstance(this).addOrUpdateDatabaseUri(databaseUri, keyFileUri)
}
private fun checkAndLaunchGroupActivity(database: Database, password: String?, keyFileUri: Uri?) {
if (database.validatePasswordEncoding(password, keyFileUri != null)) {
launchGroupActivity()
} else {
PasswordEncodingDialogFragment().apply {
positiveButtonClickListener = DialogInterface.OnClickListener { _, _ ->
launchGroupActivity()
}
show(supportFragmentManager, "passwordEncodingTag")
}
}
}
private fun launchGroupActivity() {
EntrySelectionHelper.doEntrySelectionAction(intent,
{
GroupActivity.launch(this@PasswordActivity, readOnly)
},
{
GroupActivity.launchForKeyboarSelection(this@PasswordActivity, readOnly)
// Do not keep history
finish()
},
{ assistStructure ->
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
GroupActivity.launchForAutofillResult(this@PasswordActivity, assistStructure, readOnly)
}
})
}
// To fix multiple view education
private var performedEductionInProgress = false

View File

@@ -1,7 +1,7 @@
package com.kunzisoft.keepass.activities.helpers
import android.app.Activity
import android.app.assist.AssistStructure
import android.content.Context
import android.content.Intent
import android.os.Build
import com.kunzisoft.keepass.autofill.AutofillHelper
@@ -11,10 +11,10 @@ object EntrySelectionHelper {
private const val EXTRA_ENTRY_SELECTION_MODE = "com.kunzisoft.keepass.extra.ENTRY_SELECTION_MODE"
private const val DEFAULT_ENTRY_SELECTION_MODE = false
fun startActivityForEntrySelection(activity: Activity, intent: Intent) {
fun startActivityForEntrySelection(context: Context, intent: Intent) {
addEntrySelectionModeExtraInIntent(intent)
// only to avoid visible flickering when redirecting
activity.startActivity(intent)
context.startActivity(intent)
}
fun addEntrySelectionModeExtraInIntent(intent: Intent) {

View File

@@ -19,35 +19,63 @@
*/
package com.kunzisoft.keepass.database.action
import android.content.ContentResolver
import android.content.Context
import android.net.Uri
import com.kunzisoft.keepass.app.database.CipherDatabaseAction
import com.kunzisoft.keepass.app.database.CipherDatabaseEntity
import com.kunzisoft.keepass.app.database.FileDatabaseHistoryAction
import com.kunzisoft.keepass.database.element.Database
import com.kunzisoft.keepass.database.exception.LoadDatabaseException
import com.kunzisoft.keepass.settings.PreferencesUtil
import com.kunzisoft.keepass.tasks.ActionRunnable
import com.kunzisoft.keepass.tasks.ProgressTaskUpdater
import java.io.File
class LoadDatabaseRunnable(private val mDatabase: Database,
class LoadDatabaseRunnable(private val context: Context,
private val mDatabase: Database,
private val mUri: Uri,
private val mPass: String?,
private val mKey: Uri?,
private val contentResolver: ContentResolver,
private val cacheDirectory: File,
private val mCipherEntity: CipherDatabaseEntity?,
private val mOmitBackup: Boolean,
private val mFixDuplicateUUID: Boolean,
private val progressTaskUpdater: ProgressTaskUpdater?,
actionFinishRunnable: ActionRunnable?)
: ActionRunnable(actionFinishRunnable, executeNestedActionIfResultFalse = true) {
private val cacheDirectory = context.applicationContext.filesDir
override fun run() {
try {
// Clear before we load
mDatabase.closeAndClear(cacheDirectory)
mDatabase.loadData(mUri, mPass, mKey,
contentResolver,
context.contentResolver,
cacheDirectory,
mOmitBackup,
mFixDuplicateUUID,
progressTaskUpdater)
finishRun(true)
// Save keyFile in app database
val rememberKeyFile = PreferencesUtil.rememberKeyFiles(context)
if (rememberKeyFile) {
var keyUri = mKey
if (!rememberKeyFile) {
keyUri = null
}
FileDatabaseHistoryAction.getInstance(context)
.addOrUpdateDatabaseUri(mUri, keyUri)
}
// Register the biometric
mCipherEntity?.let { cipherDatabaseEntity ->
CipherDatabaseAction.getInstance(context)
.addOrUpdateCipherDatabase(cipherDatabaseEntity) {
finishRun(true)
}
} ?: run {
finishRun(true)
}
}
catch (e: LoadDatabaseException) {
finishRun(false, e)

View File

@@ -29,7 +29,6 @@ import com.kunzisoft.keepass.tasks.ProgressTaskDialogFragment.Companion.retrieve
import com.kunzisoft.keepass.timeout.TimeoutHelper
import com.kunzisoft.keepass.utils.DATABASE_START_TASK_ACTION
import com.kunzisoft.keepass.utils.DATABASE_STOP_TASK_ACTION
import java.io.File
import java.util.*
import kotlin.collections.ArrayList
@@ -119,6 +118,7 @@ class ProgressDialogThread(private val activity: FragmentActivity,
}
fun registerProgressTask() {
ProgressTaskDialogFragment.stop(activity)
// Register a database task receiver to stop loading dialog when service finish the task
databaseTaskBroadcastReceiver = object : BroadcastReceiver() {
@@ -193,16 +193,12 @@ class ProgressDialogThread(private val activity: FragmentActivity,
masterPassword: String?,
keyFile: Uri?,
cipherEntity: CipherDatabaseEntity?,
filesDir: File,
omitBackup: Boolean,
fixDuplicateUuid: Boolean) {
start(Bundle().apply {
putParcelable(DatabaseTaskNotificationService.DATABASE_URI_KEY, databaseUri)
putString(DatabaseTaskNotificationService.MASTER_PASSWORD_KEY, masterPassword)
putParcelable(DatabaseTaskNotificationService.KEY_FILE_KEY, keyFile)
putParcelable(DatabaseTaskNotificationService.CIPHER_ENTITY_KEY, cipherEntity)
putSerializable(DatabaseTaskNotificationService.CACHE_DIR_KEY, filesDir)
putBoolean(DatabaseTaskNotificationService.OMIT_BACKUP_KEY, omitBackup)
putBoolean(DatabaseTaskNotificationService.FIX_DUPLICATE_UUID_KEY, fixDuplicateUuid)
}
, ACTION_DATABASE_LOAD_TASK)

View File

@@ -12,7 +12,7 @@ class KeyboardLauncherActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
if (Database.getInstance().loaded && TimeoutHelper.checkTime(this))
GroupActivity.launchForKeyboarSelection(this, PreferencesUtil.enableReadOnlyDatabase(this))
GroupActivity.launchForKeyboardSelection(this, PreferencesUtil.enableReadOnlyDatabase(this))
else {
// Pass extra to get entry
FileDatabaseSelectActivity.launchForKeyboardSelection(this)

View File

@@ -16,11 +16,11 @@ import com.kunzisoft.keepass.database.action.LoadDatabaseRunnable
import com.kunzisoft.keepass.database.action.SaveDatabaseActionRunnable
import com.kunzisoft.keepass.database.action.node.*
import com.kunzisoft.keepass.database.element.*
import com.kunzisoft.keepass.settings.PreferencesUtil
import com.kunzisoft.keepass.tasks.ActionRunnable
import com.kunzisoft.keepass.tasks.ProgressTaskUpdater
import com.kunzisoft.keepass.utils.DATABASE_START_TASK_ACTION
import com.kunzisoft.keepass.utils.DATABASE_STOP_TASK_ACTION
import java.io.File
import java.util.*
import kotlin.collections.ArrayList
@@ -233,23 +233,22 @@ class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdat
&& intent.hasExtra(MASTER_PASSWORD_KEY)
&& intent.hasExtra(KEY_FILE_KEY)
&& intent.hasExtra(CIPHER_ENTITY_KEY)
&& intent.hasExtra(CACHE_DIR_KEY)
&& intent.hasExtra(OMIT_BACKUP_KEY)
&& intent.hasExtra(FIX_DUPLICATE_UUID_KEY)
) {
val database = Database.getInstance()
val databaseUri: Uri = intent.getParcelableExtra(DATABASE_URI_KEY)
val masterPassword: String? = intent.getStringExtra(MASTER_PASSWORD_KEY)
val keyFileUri: Uri? = intent.getParcelableExtra(KEY_FILE_KEY)
val cipherEntity: CipherDatabaseEntity? = intent.getParcelableExtra(CIPHER_ENTITY_KEY)
return LoadDatabaseRunnable(
Database.getInstance(),
this,
database,
databaseUri,
masterPassword,
keyFileUri,
contentResolver,
intent.getSerializableExtra(CACHE_DIR_KEY) as File,
intent.getBooleanExtra(OMIT_BACKUP_KEY, false),
cipherEntity,
PreferencesUtil.omitBackup(this),
intent.getBooleanExtra(FIX_DUPLICATE_UUID_KEY, false),
this,
object: ActionRunnable() {
@@ -485,8 +484,6 @@ class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdat
const val KEY_FILE_CHECKED_KEY = "KEY_FILE_CHECKED_KEY"
const val KEY_FILE_KEY = "KEY_FILE_KEY"
const val CIPHER_ENTITY_KEY = "CIPHER_ENTITY_KEY"
const val CACHE_DIR_KEY = "CACHE_DIR_KEY"
const val OMIT_BACKUP_KEY = "OMIT_BACKUP_KEY"
const val FIX_DUPLICATE_UUID_KEY = "FIX_DUPLICATE_UUID_KEY"
const val GROUP_KEY = "GROUP_KEY"
const val ENTRY_KEY = "ENTRY_KEY"