Better Action runnable implementation

This commit is contained in:
J-Jamet
2019-10-30 14:49:40 +01:00
parent e088f4a4ad
commit 8c0d7ab9ed
17 changed files with 199 additions and 292 deletions

View File

@@ -430,7 +430,7 @@ class EntryActivity : LockingHideActivity() {
TODO Slowdown when add entry as result
Intent intent = new Intent();
intent.putExtra(EntryEditActivity.ADD_OR_UPDATE_ENTRY_KEY, mEntry);
setResult(EntryEditActivity.UPDATE_ENTRY_RESULT_CODE, intent);
onFinish(EntryEditActivity.UPDATE_ENTRY_RESULT_CODE, intent);
*/
super.finish()
}

View File

@@ -175,6 +175,23 @@ class PasswordActivity : StylishActivity() {
}
}
// Remove the password in view in all cases
removePassword()
if (result.isSuccess) {
launchGroupActivity()
} else {
var resultError = ""
val resultException = result.exception
val resultMessage = result.message
if (resultException != null) {
resultError = resultException.getLocalizedMessage(resources)
// Relaunch loading if we need to fix UUID
if (resultException is LoadDatabaseDuplicateUuidException) {
showLoadDatabaseDuplicateUuidMessage {
var databaseUri: Uri? = null
var masterPassword: String? = null
var keyFileUri: Uri? = null
@@ -190,20 +207,6 @@ class PasswordActivity : StylishActivity() {
}
databaseUri?.let { databaseFileUri ->
// Remove the password in view in all cases
removePassword()
if (result.isSuccess) {
launchGroupActivity()
} else {
var resultError = ""
val resultException = result.exception
val resultMessage = result.message
if (resultException != null) {
resultError = resultException.getLocalizedMessage(resources)
if (resultException is LoadDatabaseDuplicateUuidException)
showLoadDatabaseDuplicateUuidMessage {
showProgressDialogAndLoadDatabase(
databaseFileUri,
masterPassword,
@@ -213,13 +216,14 @@ class PasswordActivity : StylishActivity() {
true)
}
}
}
}
// Show error message
if (resultMessage != null && resultMessage.isNotEmpty()) {
resultError = "$resultError $resultMessage"
}
Log.e(TAG, resultError, resultException)
Snackbar.make(activity_password_coordinator_layout,
resultError,
Snackbar.LENGTH_LONG).asError().show()
@@ -228,7 +232,6 @@ class PasswordActivity : StylishActivity() {
}
}
}
}
private fun launchGroupActivity() {
EntrySelectionHelper.doEntrySelectionAction(intent,

View File

@@ -22,22 +22,20 @@ package com.kunzisoft.keepass.database.action
import android.content.Context
import android.net.Uri
import com.kunzisoft.keepass.database.element.Database
import com.kunzisoft.keepass.tasks.ActionRunnable
import com.kunzisoft.keepass.utils.UriUtil
open class AssignPasswordInDatabaseRunnable @JvmOverloads constructor(
open class AssignPasswordInDatabaseRunnable (
context: Context,
database: Database,
withMasterPassword: Boolean,
masterPassword: String?,
withKeyFile: Boolean,
keyFile: Uri?,
save: Boolean,
actionRunnable: ActionRunnable? = null)
: SaveDatabaseRunnable(context, database, save, actionRunnable) {
save: Boolean)
: SaveDatabaseRunnable(context, database, save) {
private var mMasterPassword: String? = null
private var mKeyFile: Uri? = null
protected var mKeyFile: Uri? = null
private var mBackupKey: ByteArray? = null
@@ -48,7 +46,7 @@ open class AssignPasswordInDatabaseRunnable @JvmOverloads constructor(
this.mKeyFile = keyFile
}
override fun run() {
override fun onStartRun() {
// Set key
try {
// TODO move master key methods
@@ -57,17 +55,17 @@ open class AssignPasswordInDatabaseRunnable @JvmOverloads constructor(
val uriInputStream = UriUtil.getUriInputStream(context.contentResolver, mKeyFile)
database.retrieveMasterKey(mMasterPassword, uriInputStream)
// To save the database
super.run()
finishRun(true)
} catch (e: Exception) {
erase(mBackupKey)
finishRun(false, e.message)
}
setError(e.message)
}
override fun onFinishRun(result: Result) {
super.onStartRun()
}
override fun onFinishRun() {
super.onFinishRun()
if (!result.isSuccess) {
// Erase the current master key
erase(database.masterKey)
@@ -75,8 +73,6 @@ open class AssignPasswordInDatabaseRunnable @JvmOverloads constructor(
database.masterKey = it
}
}
super.onFinishRun(result)
}
/**

View File

@@ -21,8 +21,9 @@ package com.kunzisoft.keepass.database.action
import android.content.Context
import android.net.Uri
import android.util.Log
import com.kunzisoft.keepass.app.database.FileDatabaseHistoryAction
import com.kunzisoft.keepass.database.element.Database
import com.kunzisoft.keepass.tasks.ActionRunnable
class CreateDatabaseRunnable(context: Context,
private val mDatabaseUri: Uri,
@@ -31,28 +32,34 @@ class CreateDatabaseRunnable(context: Context,
masterPassword: String?,
withKeyFile: Boolean,
keyFile: Uri?,
save: Boolean,
actionRunnable: ActionRunnable? = null)
: AssignPasswordInDatabaseRunnable(context, mDatabase, withMasterPassword, masterPassword, withKeyFile, keyFile, save, actionRunnable) {
save: Boolean)
: AssignPasswordInDatabaseRunnable(context, mDatabase, withMasterPassword, masterPassword, withKeyFile, keyFile, save) {
override fun run() {
override fun onStartRun() {
try {
// Create new database record
mDatabase.apply {
createData(mDatabaseUri)
// Set Database state
loaded = true
// Commit changes
super.run()
}
finishRun(true)
} catch (e: Exception) {
mDatabase.closeAndClear()
finishRun(false, e.message)
}
setError(e.message)
}
override fun onFinishRun(result: Result) {}
super.onStartRun()
}
override fun onFinishRun() {
super.onFinishRun()
if (result.isSuccess) {
// Add database to recent files
FileDatabaseHistoryAction.getInstance(context.applicationContext)
.addOrUpdateDatabaseUri(mDatabaseUri, mKeyFile)
} else {
Log.e("CreateDatabaseRunnable", "Unable to create the database")
}
}
}

View File

@@ -26,6 +26,7 @@ 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.LoadDatabaseDuplicateUuidException
import com.kunzisoft.keepass.database.exception.LoadDatabaseException
import com.kunzisoft.keepass.notifications.DatabaseOpenNotificationService
import com.kunzisoft.keepass.settings.PreferencesUtil
@@ -42,16 +43,18 @@ class LoadDatabaseRunnable(private val context: Context,
private val mOmitBackup: Boolean,
private val mFixDuplicateUUID: Boolean,
private val progressTaskUpdater: ProgressTaskUpdater?,
private val mOnFinish: ((Result) -> Unit)?)
: ActionRunnable(null, executeNestedActionIfResultFalse = true) {
private val mDuplicateUuidAction: ((Result) -> Unit)?)
: ActionRunnable() {
private val cacheDirectory = context.applicationContext.filesDir
override fun run() {
try {
override fun onStartRun() {
// Clear before we load
mDatabase.closeAndClear(cacheDirectory)
}
override fun onActionRun() {
try {
mDatabase.loadData(mUri, mPass, mKey,
mReadonly,
context.contentResolver,
@@ -59,7 +62,18 @@ class LoadDatabaseRunnable(private val context: Context,
mOmitBackup,
mFixDuplicateUUID,
progressTaskUpdater)
}
catch (e: LoadDatabaseDuplicateUuidException) {
mDuplicateUuidAction?.invoke(result)
setError(e)
}
catch (e: LoadDatabaseException) {
setError(e)
}
}
override fun onFinishRun() {
if (result.isSuccess) {
// Save keyFile in app database
val rememberKeyFile = PreferencesUtil.rememberKeyFiles(context)
if (rememberKeyFile) {
@@ -71,28 +85,15 @@ class LoadDatabaseRunnable(private val context: Context,
.addOrUpdateDatabaseUri(mUri, keyUri)
}
mOnFinish?.invoke(result)
// Register the biometric
mCipherEntity?.let { cipherDatabaseEntity ->
CipherDatabaseAction.getInstance(context)
.addOrUpdateCipherDatabase(cipherDatabaseEntity) {
finishRun(true)
}
} ?: run {
finishRun(true)
}
}
catch (e: LoadDatabaseException) {
finishRun(false, e)
.addOrUpdateCipherDatabase(cipherDatabaseEntity) // return value not called
}
// Start the opening notification
context.startService(Intent(context, DatabaseOpenNotificationService::class.java))
}
override fun onFinishRun(result: Result) {
if (!result.isSuccess) {
} else {
mDatabase.closeAndClear(cacheDirectory)
}
}

View File

@@ -25,39 +25,29 @@ import com.kunzisoft.keepass.database.exception.DatabaseOutputException
import com.kunzisoft.keepass.tasks.ActionRunnable
import java.io.IOException
abstract class SaveDatabaseRunnable(protected var context: Context,
open class SaveDatabaseRunnable(protected var context: Context,
protected var database: Database,
protected var saveDatabase: Boolean,
nestedAction: ActionRunnable? = null)
: ActionRunnable(nestedAction) {
private var saveDatabase: Boolean)
: ActionRunnable() {
override fun run() {
if (saveDatabase) {
var mAfterSaveDatabase: ((Result) -> Unit)? = null
override fun onStartRun() {}
override fun onActionRun() {
if (saveDatabase && result.isSuccess) {
try {
database.saveData(context.contentResolver)
} catch (e: IOException) {
finishRun(false, e.message)
setError(e.message)
} catch (e: DatabaseOutputException) {
finishRun(false, e.message)
setError(e.message)
}
}
}
// Need to call super.run() in child class
}
override fun onFinishRun(result: Result) {
// Need to call super.onFinishRun(result) in child class
}
}
class SaveDatabaseActionRunnable(context: Context,
database: Database,
save: Boolean,
nestedAction: ActionRunnable? = null)
: SaveDatabaseRunnable(context, database, save, nestedAction) {
override fun run() {
super.run()
finishRun(true)
override fun onFinishRun() {
// Need to call super.onFinishRun() in child class
mAfterSaveDatabase?.invoke(result)
}
}

View File

@@ -3,44 +3,33 @@ package com.kunzisoft.keepass.database.action.node
import android.content.Context
import com.kunzisoft.keepass.database.action.SaveDatabaseRunnable
import com.kunzisoft.keepass.database.element.Database
import com.kunzisoft.keepass.database.exception.LoadDatabaseException
abstract class ActionNodeDatabaseRunnable(
context: Context,
database: Database,
private val callbackRunnable: AfterActionNodeFinishRunnable?,
private val afterActionNodesFinish: AfterActionNodesFinish?,
save: Boolean)
: SaveDatabaseRunnable(context, database, save) {
/**
* Function do to a node action, don't implements run() if used this
* Function do to a node action
*/
abstract fun nodeAction()
protected fun saveDatabaseAndFinish() {
if (result.isSuccess) {
super.run()
finishRun(true)
}
}
protected fun throwErrorAndFinish(throwable: LoadDatabaseException) {
finishRun(false, throwable)
}
override fun run() {
override fun onStartRun() {
nodeAction()
super.onStartRun()
}
/**
* Function do get the finish node action, don't implements onFinishRun() if used this
* Function do get the finish node action
*/
abstract fun nodeFinish(result: Result): ActionNodeValues
abstract fun nodeFinish(): ActionNodesValues
override fun onFinishRun(result: Result) {
callbackRunnable?.apply {
onActionNodeFinish(nodeFinish(result))
}
super.onFinishRun(result)
override fun onFinishRun() {
super.onFinishRun()
afterActionNodesFinish?.apply {
onActionNodesFinish(result, nodeFinish())
}
}
}

View File

@@ -31,17 +31,16 @@ class AddEntryRunnable constructor(
private val mNewEntry: EntryVersioned,
private val mParent: GroupVersioned,
save: Boolean,
finishRunnable: AfterActionNodeFinishRunnable?)
: ActionNodeDatabaseRunnable(context, database, finishRunnable, save) {
afterActionNodesFinish: AfterActionNodesFinish?)
: ActionNodeDatabaseRunnable(context, database, afterActionNodesFinish, save) {
override fun nodeAction() {
mNewEntry.touch(modified = true, touchParents = true)
mParent.touch(modified = true, touchParents = true)
database.addEntryTo(mNewEntry, mParent)
saveDatabaseAndFinish()
}
override fun nodeFinish(result: Result): ActionNodeValues {
override fun nodeFinish(): ActionNodesValues {
if (!result.isSuccess) {
mNewEntry.parent?.let {
database.removeEntryFrom(mNewEntry, it)
@@ -51,6 +50,6 @@ class AddEntryRunnable constructor(
val oldNodesReturn = ArrayList<NodeVersioned>()
val newNodesReturn = ArrayList<NodeVersioned>()
newNodesReturn.add(mNewEntry)
return ActionNodeValues(result, oldNodesReturn, newNodesReturn)
return ActionNodesValues(oldNodesReturn, newNodesReturn)
}
}

View File

@@ -30,17 +30,16 @@ class AddGroupRunnable constructor(
private val mNewGroup: GroupVersioned,
private val mParent: GroupVersioned,
save: Boolean,
afterAddNodeRunnable: AfterActionNodeFinishRunnable?)
: ActionNodeDatabaseRunnable(context, database, afterAddNodeRunnable, save) {
afterActionNodesFinish: AfterActionNodesFinish?)
: ActionNodeDatabaseRunnable(context, database, afterActionNodesFinish, save) {
override fun nodeAction() {
mNewGroup.touch(modified = true, touchParents = true)
mParent.touch(modified = true, touchParents = true)
database.addGroupTo(mNewGroup, mParent)
saveDatabaseAndFinish()
}
override fun nodeFinish(result: Result): ActionNodeValues {
override fun nodeFinish(): ActionNodesValues {
if (!result.isSuccess) {
database.removeGroupFrom(mNewGroup, mParent)
}
@@ -48,6 +47,6 @@ class AddGroupRunnable constructor(
val oldNodesReturn = ArrayList<NodeVersioned>()
val newNodesReturn = ArrayList<NodeVersioned>()
newNodesReturn.add(mNewGroup)
return ActionNodeValues(result, oldNodesReturn, newNodesReturn)
return ActionNodesValues(oldNodesReturn, newNodesReturn)
}
}

View File

@@ -30,8 +30,8 @@ import com.kunzisoft.keepass.tasks.ActionRunnable
* - Move : @param oldNodes empty, @param newNodes NodesToMove
* - Update : @param oldNodes NodesToUpdate, @param newNodes NodesUpdated
*/
class ActionNodeValues(val result: ActionRunnable.Result, val oldNodes: List<NodeVersioned>, val newNodes: List<NodeVersioned>)
class ActionNodesValues(val oldNodes: List<NodeVersioned>, val newNodes: List<NodeVersioned>)
abstract class AfterActionNodeFinishRunnable {
abstract fun onActionNodeFinish(actionNodeValues: ActionNodeValues)
abstract class AfterActionNodesFinish {
abstract fun onActionNodesFinish(result: ActionRunnable.Result, actionNodesValues: ActionNodesValues)
}

View File

@@ -32,20 +32,18 @@ class CopyNodesRunnable constructor(
private val mNodesToCopy: List<NodeVersioned>,
private val mNewParent: GroupVersioned,
save: Boolean,
afterAddNodeRunnable: AfterActionNodeFinishRunnable?)
: ActionNodeDatabaseRunnable(context, database, afterAddNodeRunnable, save) {
afterActionNodesFinish: AfterActionNodesFinish?)
: ActionNodeDatabaseRunnable(context, database, afterActionNodesFinish, save) {
private var mEntriesCopied = ArrayList<EntryVersioned>()
override fun nodeAction() {
var error: LoadDatabaseException? = null
foreachNode@ for(currentNode in mNodesToCopy) {
when (currentNode.type) {
Type.GROUP -> {
Log.e(TAG, "Copy not allowed for group")// Only finish thread
error = CopyDatabaseGroupException()
setError(CopyDatabaseGroupException())
break@foreachNode
}
Type.ENTRY -> {
@@ -60,24 +58,20 @@ class CopyNodesRunnable constructor(
mEntriesCopied.add(entryCopied)
} else {
Log.e(TAG, "Unable to create a copy of the entry")
error = CopyDatabaseEntryException()
setError(CopyDatabaseEntryException())
break@foreachNode
}
} else {
// Only finish thread
error = CopyDatabaseEntryException()
setError(CopyDatabaseEntryException())
break@foreachNode
}
}
}
}
if (error != null)
throwErrorAndFinish(error)
else
saveDatabaseAndFinish()
}
override fun nodeFinish(result: Result): ActionNodeValues {
override fun nodeFinish(): ActionNodesValues {
if (!result.isSuccess) {
// If we fail to save, try to delete the copy
mEntriesCopied.forEach {
@@ -88,7 +82,7 @@ class CopyNodesRunnable constructor(
}
}
}
return ActionNodeValues(result, mNodesToCopy, mEntriesCopied)
return ActionNodesValues(mNodesToCopy, mEntriesCopied)
}
companion object {

View File

@@ -26,8 +26,8 @@ class DeleteNodesRunnable(context: Context,
database: Database,
private val mNodesToDelete: List<NodeVersioned>,
save: Boolean,
finish: AfterActionNodeFinishRunnable)
: ActionNodeDatabaseRunnable(context, database, finish, save) {
afterActionNodesFinish: AfterActionNodesFinish)
: ActionNodeDatabaseRunnable(context, database, afterActionNodesFinish, save) {
private var mParent: GroupVersioned? = null
private var mCanRecycle: Boolean = false
@@ -65,10 +65,9 @@ class DeleteNodesRunnable(context: Context,
}
}
}
saveDatabaseAndFinish()
}
override fun nodeFinish(result: Result): ActionNodeValues {
override fun nodeFinish(): ActionNodesValues {
if (!result.isSuccess) {
if (mCanRecycle) {
mParent?.let {
@@ -92,6 +91,6 @@ class DeleteNodesRunnable(context: Context,
// Return a copy of unchanged nodes as old param
// and nodes deleted or moved in recycle bin as new param
return ActionNodeValues(result, mNodesToDeleteBackup, mNodesToDelete)
return ActionNodesValues(mNodesToDeleteBackup, mNodesToDelete)
}
}

View File

@@ -32,14 +32,13 @@ class MoveNodesRunnable constructor(
private val mNodesToMove: List<NodeVersioned>,
private val mNewParent: GroupVersioned,
save: Boolean,
afterAddNodeRunnable: AfterActionNodeFinishRunnable?)
: ActionNodeDatabaseRunnable(context, database, afterAddNodeRunnable, save) {
afterActionNodesFinish: AfterActionNodesFinish?)
: ActionNodeDatabaseRunnable(context, database, afterActionNodesFinish, save) {
private var mOldParent: GroupVersioned? = null
override fun nodeAction() {
var error: LoadDatabaseException? = null
foreachNode@ for(nodeToMove in mNodesToMove) {
// Move node in new parent
mOldParent = nodeToMove.parent
@@ -54,7 +53,7 @@ class MoveNodesRunnable constructor(
database.moveGroupTo(groupToMove, mNewParent)
} else {
// Only finish thread
error = MoveDatabaseGroupException()
setError(MoveDatabaseGroupException())
break@foreachNode
}
}
@@ -68,19 +67,15 @@ class MoveNodesRunnable constructor(
database.moveEntryTo(entryToMove, mNewParent)
} else {
// Only finish thread
error = MoveDatabaseEntryException()
setError(MoveDatabaseEntryException())
break@foreachNode
}
}
}
}
if (error != null)
throwErrorAndFinish(error)
else
saveDatabaseAndFinish()
}
override fun nodeFinish(result: Result): ActionNodeValues {
override fun nodeFinish(): ActionNodesValues {
if (!result.isSuccess) {
try {
mNodesToMove.forEach { nodeToMove ->
@@ -97,7 +92,7 @@ class MoveNodesRunnable constructor(
Log.i(TAG, "Unable to replace the node")
}
}
return ActionNodeValues(result, ArrayList(), mNodesToMove)
return ActionNodesValues(ArrayList(), mNodesToMove)
}
companion object {

View File

@@ -30,8 +30,8 @@ class UpdateEntryRunnable constructor(
private val mOldEntry: EntryVersioned,
private val mNewEntry: EntryVersioned,
save: Boolean,
finishRunnable: AfterActionNodeFinishRunnable?)
: ActionNodeDatabaseRunnable(context, database, finishRunnable, save) {
afterActionNodesFinish: AfterActionNodesFinish?)
: ActionNodeDatabaseRunnable(context, database, afterActionNodesFinish, save) {
// Keep backup of original values in case save fails
private var mBackupEntryHistory: EntryVersioned = EntryVersioned(mOldEntry)
@@ -50,11 +50,9 @@ class UpdateEntryRunnable constructor(
// Only change data in index
database.updateEntry(mOldEntry)
saveDatabaseAndFinish()
}
override fun nodeFinish(result: Result): ActionNodeValues {
override fun nodeFinish(): ActionNodesValues {
if (!result.isSuccess) {
mOldEntry.updateWith(mBackupEntryHistory)
// If we fail to save, back out changes to global structure
@@ -65,6 +63,6 @@ class UpdateEntryRunnable constructor(
oldNodesReturn.add(mBackupEntryHistory)
val newNodesReturn = ArrayList<NodeVersioned>()
newNodesReturn.add(mOldEntry)
return ActionNodeValues(result, oldNodesReturn, newNodesReturn)
return ActionNodesValues(oldNodesReturn, newNodesReturn)
}
}

View File

@@ -30,8 +30,8 @@ class UpdateGroupRunnable constructor(
private val mOldGroup: GroupVersioned,
private val mNewGroup: GroupVersioned,
save: Boolean,
finishRunnable: AfterActionNodeFinishRunnable?)
: ActionNodeDatabaseRunnable(context, database, finishRunnable, save) {
afterActionNodesFinish: AfterActionNodesFinish?)
: ActionNodeDatabaseRunnable(context, database, afterActionNodesFinish, save) {
// Keep backup of original values in case save fails
private val mBackupGroup: GroupVersioned = GroupVersioned(mOldGroup)
@@ -47,11 +47,9 @@ class UpdateGroupRunnable constructor(
// Only change data in index
database.updateGroup(mOldGroup)
saveDatabaseAndFinish()
}
override fun nodeFinish(result: Result): ActionNodeValues {
override fun nodeFinish(): ActionNodesValues {
if (!result.isSuccess) {
// If we fail to save, back out changes to global structure
mOldGroup.updateWith(mBackupGroup)
@@ -62,6 +60,6 @@ class UpdateGroupRunnable constructor(
oldNodesReturn.add(mBackupGroup)
val newNodesReturn = ArrayList<NodeVersioned>()
newNodesReturn.add(mOldGroup)
return ActionNodeValues(result, oldNodesReturn, newNodesReturn)
return ActionNodesValues(oldNodesReturn, newNodesReturn)
}
}

View File

@@ -6,14 +6,12 @@ import android.os.AsyncTask
import android.os.Binder
import android.os.Bundle
import android.os.IBinder
import android.util.Log
import com.kunzisoft.keepass.R
import com.kunzisoft.keepass.app.database.CipherDatabaseEntity
import com.kunzisoft.keepass.app.database.FileDatabaseHistoryAction
import com.kunzisoft.keepass.database.action.AssignPasswordInDatabaseRunnable
import com.kunzisoft.keepass.database.action.CreateDatabaseRunnable
import com.kunzisoft.keepass.database.action.LoadDatabaseRunnable
import com.kunzisoft.keepass.database.action.SaveDatabaseActionRunnable
import com.kunzisoft.keepass.database.action.SaveDatabaseRunnable
import com.kunzisoft.keepass.database.action.node.*
import com.kunzisoft.keepass.database.element.*
import com.kunzisoft.keepass.settings.PreferencesUtil
@@ -185,22 +183,7 @@ class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdat
intent.getStringExtra(MASTER_PASSWORD_KEY),
intent.getBooleanExtra(KEY_FILE_CHECKED_KEY, false),
keyFileUri,
true, // TODO get readonly
object: ActionRunnable() {
override fun run() {
finishRun(true)
}
override fun onFinishRun(result: Result) {
if (result.isSuccess) {
// Add database to recent files
FileDatabaseHistoryAction.getInstance(applicationContext)
.addOrUpdateDatabaseUri(databaseUri, keyFileUri)
} else {
Log.e(TAG, "Unable to create the database")
}
}
}
true // TODO get readonly
)
} else {
return null
@@ -235,6 +218,7 @@ class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdat
intent.getBooleanExtra(FIX_DUPLICATE_UUID_KEY, false),
this
) { result ->
// Add each info to reload database after thrown duplicate UUID exception
result.data = Bundle().apply {
putParcelable(DATABASE_URI_KEY, databaseUri)
putString(MASTER_PASSWORD_KEY, masterPassword)
@@ -266,13 +250,13 @@ class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdat
}
}
private inner class AfterActionNodeRunnable : AfterActionNodeFinishRunnable() {
override fun onActionNodeFinish(actionNodeValues: ActionNodeValues) {
// TODO Encapsulate
val bundle = actionNodeValues.result.data ?: Bundle()
bundle.putBundle(OLD_NODES_KEY, getBundleFromListNodes(actionNodeValues.oldNodes))
bundle.putBundle(NEW_NODES_KEY, getBundleFromListNodes(actionNodeValues.newNodes))
actionNodeValues.result.data = bundle
private inner class AfterActionNodesRunnable : AfterActionNodesFinish() {
override fun onActionNodesFinish(result: ActionRunnable.Result,
actionNodesValues: ActionNodesValues) {
val bundle = result.data ?: Bundle()
bundle.putBundle(OLD_NODES_KEY, getBundleFromListNodes(actionNodesValues.oldNodes))
bundle.putBundle(NEW_NODES_KEY, getBundleFromListNodes(actionNodesValues.newNodes))
result.data = bundle
}
}
@@ -288,7 +272,7 @@ class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdat
intent.getParcelableExtra(GROUP_KEY),
parent,
intent.getBooleanExtra(SAVE_DATABASE_KEY, false),
AfterActionNodeRunnable())
AfterActionNodesRunnable())
}
} else {
null
@@ -308,7 +292,7 @@ class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdat
oldGroup,
newGroup,
intent.getBooleanExtra(SAVE_DATABASE_KEY, false),
AfterActionNodeRunnable())
AfterActionNodesRunnable())
}
} else {
null
@@ -327,7 +311,7 @@ class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdat
intent.getParcelableExtra(ENTRY_KEY),
parent,
intent.getBooleanExtra(SAVE_DATABASE_KEY, false),
AfterActionNodeRunnable())
AfterActionNodesRunnable())
}
} else {
null
@@ -347,7 +331,7 @@ class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdat
oldEntry,
newEntry,
intent.getBooleanExtra(SAVE_DATABASE_KEY, false),
AfterActionNodeRunnable())
AfterActionNodesRunnable())
}
} else {
null
@@ -367,7 +351,7 @@ class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdat
getListNodesFromBundle(database, intent.extras!!),
newParent,
intent.getBooleanExtra(SAVE_DATABASE_KEY, false),
AfterActionNodeRunnable())
AfterActionNodesRunnable())
}
} else {
@@ -388,7 +372,7 @@ class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdat
getListNodesFromBundle(database, intent.extras!!),
newParent,
intent.getBooleanExtra(SAVE_DATABASE_KEY, false),
AfterActionNodeRunnable())
AfterActionNodesRunnable())
}
} else {
@@ -406,7 +390,7 @@ class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdat
database,
getListNodesFromBundle(database, intent.extras!!),
intent.getBooleanExtra(SAVE_DATABASE_KEY, false),
AfterActionNodeRunnable())
AfterActionNodesRunnable())
} else {
null
@@ -414,14 +398,14 @@ class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdat
}
private fun buildDatabaseSaveElementActionTask(intent: Intent): ActionRunnable? {
return SaveDatabaseActionRunnable(this,
return SaveDatabaseRunnable(this,
Database.getInstance(),
true,
object: ActionRunnable() {
override fun onFinishRun(result: Result) {
true
).apply {
mAfterSaveDatabase = { result ->
result.data = intent.extras
}
})
}
}
private class ActionRunnableAsyncTask(private val progressTaskUpdater: ProgressTaskUpdater,

View File

@@ -25,58 +25,37 @@ import com.kunzisoft.keepass.database.exception.LoadDatabaseException
/**
* Callback after a task is completed.
*/
abstract class ActionRunnable(private var nestedActionRunnable: ActionRunnable? = null,
private var executeNestedActionIfResultFalse: Boolean = false)
: Runnable {
abstract class ActionRunnable: Runnable {
var result: Result = Result()
private fun execute() {
nestedActionRunnable?.let {
// Pass on result on call finish
it.result = result
it.run()
}
onFinishRun(result)
}
override fun run() {
execute()
onStartRun()
onActionRun()
onFinishRun()
}
/**
* If [success] or [executeNestedActionIfResultFalse] true,
* launch the nested action runnable if exists and finish,
* else directly finish
*/
protected fun finishRun(isSuccess: Boolean,
message: String? = null) {
finishRun(isSuccess, null, message)
}
abstract fun onStartRun()
/**
* If [success] or [executeNestedActionIfResultFalse] true,
* launch the nested action runnable if exists and finish,
* else directly finish
*/
protected fun finishRun(isSuccess: Boolean,
exception: LoadDatabaseException?,
message: String? = null) {
result.isSuccess = isSuccess
result.exception = exception
result.message = message
if (isSuccess || executeNestedActionIfResultFalse) {
execute()
}
else
onFinishRun(result)
}
abstract fun onActionRun()
/**
* Method called when the action is finished
* @param result 'true' if success action, 'false' elsewhere, with message
*/
abstract fun onFinishRun(result: Result)
abstract fun onFinishRun()
protected fun setError(message: String? = null) {
setError(null, message)
}
protected fun setError(exception: LoadDatabaseException?,
message: String? = null) {
result.isSuccess = false
result.exception = exception
result.message = message
}
/**
* Class to manage result from ActionRunnable
@@ -84,29 +63,5 @@ abstract class ActionRunnable(private var nestedActionRunnable: ActionRunnable?
data class Result(var isSuccess: Boolean = true,
var message: String? = null,
var exception: LoadDatabaseException? = null,
var data: Bundle? = null) {
fun toBundle(): Bundle {
return Bundle().apply {
putBoolean(IS_SUCCESS_KEY, isSuccess)
putString(MESSAGE_KEY, message)
putSerializable(EXCEPTION_KEY, exception)
putBundle(DATA_KEY, data)
}
}
companion object {
private const val IS_SUCCESS_KEY = "IS_SUCCESS_KEY"
private const val MESSAGE_KEY = "MESSAGE_KEY"
private const val EXCEPTION_KEY = "EXCEPTION_KEY"
private const val DATA_KEY = "DATA_KEY"
fun fromBundle(bundle: Bundle): Result {
return Result(bundle.getBoolean(IS_SUCCESS_KEY),
bundle.getString(MESSAGE_KEY),
bundle.getSerializable(EXCEPTION_KEY) as LoadDatabaseException?,
bundle.getBundle(DATA_KEY))
}
}
}
var data: Bundle? = null)
}