From 93948e7c618128081c6c39d97671c32a75f40987 Mon Sep 17 00:00:00 2001 From: J-Jamet Date: Tue, 15 Oct 2019 16:01:50 +0200 Subject: [PATCH 01/16] First commit for async loading --- .../keepass/activities/EntryActivity.kt | 52 +- .../keepass/activities/EntryEditActivity.kt | 95 ++-- .../activities/FileDatabaseSelectActivity.kt | 84 ++-- .../keepass/activities/GroupActivity.kt | 195 ++++---- .../keepass/activities/PasswordActivity.kt | 68 +-- .../database/action/LoadDatabaseRunnable.kt | 10 +- .../ProgressDialogSaveDatabaseThread.kt | 14 - .../database/action/ProgressDialogThread.kt | 302 +++++++++--- .../database/action/SaveDatabaseRunnable.kt | 1 - .../action/node/ActionNodeDatabaseRunnable.kt | 4 +- .../database/action/node/AddEntryRunnable.kt | 8 +- .../database/action/node/AddGroupRunnable.kt | 8 +- .../database/action/node/CopyNodesRunnable.kt | 8 +- .../action/node/DeleteNodesRunnable.kt | 10 +- .../database/action/node/MoveNodesRunnable.kt | 8 +- .../action/node/UpdateEntryRunnable.kt | 32 +- .../action/node/UpdateGroupRunnable.kt | 14 +- .../keepass/database/element/Database.kt | 24 +- .../database/element/GroupVersioned.kt | 18 + .../keepass/database/element/PwDatabase.kt | 22 + .../keepass/database/element/PwGroup.kt | 16 + .../database/element/PwGroupInterface.kt | 4 + .../DatabaseTaskNotificationService.kt | 461 +++++++++++++++++- .../keepass/settings/SettingsActivity.kt | 61 ++- ...abaseSavePreferenceDialogFragmentCompat.kt | 51 +- .../kunzisoft/keepass/tasks/ActionRunnable.kt | 26 +- .../tasks/ProgressTaskDialogFragment.kt | 12 +- .../keepass/utils/BroadcastAction.kt | 6 + .../com/kunzisoft/keepass/view/ViewUtil.kt | 13 - app/src/main/res/values/strings.xml | 1 + 30 files changed, 1180 insertions(+), 448 deletions(-) delete mode 100644 app/src/main/java/com/kunzisoft/keepass/database/action/ProgressDialogSaveDatabaseThread.kt diff --git a/app/src/main/java/com/kunzisoft/keepass/activities/EntryActivity.kt b/app/src/main/java/com/kunzisoft/keepass/activities/EntryActivity.kt index f723df88e..60ed691f2 100644 --- a/app/src/main/java/com/kunzisoft/keepass/activities/EntryActivity.kt +++ b/app/src/main/java/com/kunzisoft/keepass/activities/EntryActivity.kt @@ -60,6 +60,8 @@ class EntryActivity : LockingHideActivity() { private var entryContentsView: EntryContentsView? = null private var toolbar: Toolbar? = null + private var mDatabase: Database? = null + private var mEntry: EntryVersioned? = null private var mIsHistory: Boolean = false @@ -80,34 +82,11 @@ class EntryActivity : LockingHideActivity() { supportActionBar?.setDisplayHomeAsUpEnabled(true) supportActionBar?.setDisplayShowHomeEnabled(true) - val currentDatabase = Database.getInstance() - mReadOnly = currentDatabase.isReadOnly || mReadOnly + mDatabase = Database.getInstance() + mReadOnly = mDatabase!!.isReadOnly || mReadOnly mShowPassword = !PreferencesUtil.isPasswordMask(this) - // Get Entry from UUID - try { - val keyEntry: PwNodeId = intent.getParcelableExtra(KEY_ENTRY) - mEntry = currentDatabase.getEntryById(keyEntry) - } catch (e: ClassCastException) { - Log.e(TAG, "Unable to retrieve the entry key") - } - - val historyPosition = intent.getIntExtra(KEY_ENTRY_HISTORY_POSITION, -1) - if (historyPosition >= 0) { - mIsHistory = true - mEntry = mEntry?.getHistory()?.get(historyPosition) - } - - if (mEntry == null) { - Toast.makeText(this, R.string.entry_not_found, Toast.LENGTH_LONG).show() - finish() - return - } - - // Update last access time. - mEntry?.touch(modified = false, touchParents = false) - // Retrieve the textColor to tint the icon val taIconColor = theme.obtainStyledAttributes(intArrayOf(R.attr.colorAccent)) iconColor = taIconColor.getColor(0, Color.BLACK) @@ -131,6 +110,29 @@ class EntryActivity : LockingHideActivity() { override fun onResume() { super.onResume() + // Get Entry from UUID + try { + val keyEntry: PwNodeId = intent.getParcelableExtra(KEY_ENTRY) + mEntry = mDatabase?.getEntryById(keyEntry) + } catch (e: ClassCastException) { + Log.e(TAG, "Unable to retrieve the entry key") + } + + val historyPosition = intent.getIntExtra(KEY_ENTRY_HISTORY_POSITION, -1) + if (historyPosition >= 0) { + mIsHistory = true + mEntry = mEntry?.getHistory()?.get(historyPosition) + } + + if (mEntry == null) { + Toast.makeText(this, R.string.entry_not_found, Toast.LENGTH_LONG).show() + finish() + return + } + + // Update last access time. + mEntry?.touch(modified = false, touchParents = false) + mEntry?.let { entry -> // Fill data in resume to update from EntryEditActivity fillEntryDataInContentsView(entry) diff --git a/app/src/main/java/com/kunzisoft/keepass/activities/EntryEditActivity.kt b/app/src/main/java/com/kunzisoft/keepass/activities/EntryEditActivity.kt index 86534eeba..28124050d 100644 --- a/app/src/main/java/com/kunzisoft/keepass/activities/EntryEditActivity.kt +++ b/app/src/main/java/com/kunzisoft/keepass/activities/EntryEditActivity.kt @@ -22,22 +22,22 @@ import android.app.Activity import android.content.Intent import android.os.Bundle import android.os.Handler -import androidx.appcompat.widget.Toolbar import android.util.Log import android.view.Menu import android.view.MenuItem import android.view.View import android.widget.ScrollView +import androidx.appcompat.widget.Toolbar import com.kunzisoft.keepass.R import com.kunzisoft.keepass.activities.dialogs.GeneratePasswordDialogFragment import com.kunzisoft.keepass.activities.dialogs.IconPickerDialogFragment import com.kunzisoft.keepass.activities.lock.LockingHideActivity -import com.kunzisoft.keepass.database.action.ProgressDialogSaveDatabaseThread -import com.kunzisoft.keepass.database.action.node.* +import com.kunzisoft.keepass.database.action.ProgressDialogThread import com.kunzisoft.keepass.database.element.* import com.kunzisoft.keepass.education.EntryEditActivityEducation +import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_CREATE_ENTRY_TASK +import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_UPDATE_ENTRY_TASK import com.kunzisoft.keepass.settings.PreferencesUtil -import com.kunzisoft.keepass.tasks.ActionRunnable import com.kunzisoft.keepass.timeout.TimeoutHelper import com.kunzisoft.keepass.utils.MenuUtil import com.kunzisoft.keepass.view.EntryEditContentsView @@ -58,11 +58,12 @@ class EntryEditActivity : LockingHideActivity(), // Views private var scrollView: ScrollView? = null - private var entryEditContentsView: EntryEditContentsView? = null - private var saveView: View? = null + // Dialog thread + private var progressDialogThread: ProgressDialogThread? = null + // Education private var entryEditActivityEducation: EntryEditActivityEducation? = null @@ -162,6 +163,17 @@ class EntryEditActivity : LockingHideActivity(), // Verify the education views entryEditActivityEducation = EntryEditActivityEducation(this) + + // Create progress dialog + progressDialogThread = ProgressDialogThread(this) { actionTask, result -> + when (actionTask) { + ACTION_DATABASE_CREATE_ENTRY_TASK, + ACTION_DATABASE_UPDATE_ENTRY_TASK -> { + if (result.isSuccess) + finish() + } + } + } } private fun populateViewsWithEntry(newEntry: EntryVersioned) { @@ -237,53 +249,50 @@ class EntryEditActivity : LockingHideActivity(), // Launch a validation and show the error if present if (entryEditContentsView?.isValid() == true) { // Clone the entry - mDatabase?.let { database -> - mNewEntry?.let { newEntry -> + mNewEntry?.let { newEntry -> - // WARNING Add the parent previously deleted - newEntry.parent = mEntry?.parent - // Build info - newEntry.lastAccessTime = PwDate() - newEntry.lastModificationTime = PwDate() + // WARNING Add the parent previously deleted + newEntry.parent = mEntry?.parent + // Build info + newEntry.lastAccessTime = PwDate() + newEntry.lastModificationTime = PwDate() - populateEntryWithViews(newEntry) + populateEntryWithViews(newEntry) - // Open a progress dialog and save entry - var actionRunnable: ActionRunnable? = null - val afterActionNodeFinishRunnable = object : AfterActionNodeFinishRunnable() { - override fun onActionNodeFinish(actionNodeValues: ActionNodeValues) { - if (actionNodeValues.result.isSuccess) - finish() - } + // Open a progress dialog and save entry + if (mIsNew) { + mParent?.let { parent -> + progressDialogThread?.startDatabaseCreateEntry( + newEntry, + parent, + !mReadOnly + ) } - if (mIsNew) { - mParent?.let { parent -> - actionRunnable = AddEntryRunnable(this@EntryEditActivity, - database, - newEntry, - parent, - afterActionNodeFinishRunnable, - !mReadOnly) - } - - } else { - mEntry?.let { oldEntry -> - actionRunnable = UpdateEntryRunnable(this@EntryEditActivity, - database, - oldEntry, - newEntry, - afterActionNodeFinishRunnable, - !mReadOnly) - } - } - actionRunnable?.let { runnable -> - ProgressDialogSaveDatabaseThread(this@EntryEditActivity) { runnable }.start() + } else { + mEntry?.let { oldEntry -> + progressDialogThread?.startDatabaseUpdateEntry( + oldEntry, + newEntry, + !mReadOnly + ) } } } } } + override fun onResume() { + super.onResume() + + progressDialogThread?.registerProgressTask() + } + + override fun onPause() { + progressDialogThread?.unregisterProgressTask() + + super.onPause() + } + override fun onCreateOptionsMenu(menu: Menu): Boolean { super.onCreateOptionsMenu(menu) diff --git a/app/src/main/java/com/kunzisoft/keepass/activities/FileDatabaseSelectActivity.kt b/app/src/main/java/com/kunzisoft/keepass/activities/FileDatabaseSelectActivity.kt index 69d45b087..9f7ee13f3 100644 --- a/app/src/main/java/com/kunzisoft/keepass/activities/FileDatabaseSelectActivity.kt +++ b/app/src/main/java/com/kunzisoft/keepass/activities/FileDatabaseSelectActivity.kt @@ -29,17 +29,17 @@ import android.os.Bundle import android.os.Environment import android.os.Handler import android.preference.PreferenceManager -import androidx.annotation.RequiresApi -import com.google.android.material.snackbar.Snackbar -import androidx.recyclerview.widget.LinearLayoutManager -import androidx.recyclerview.widget.RecyclerView -import androidx.recyclerview.widget.SimpleItemAnimator -import androidx.appcompat.widget.Toolbar import android.util.Log import android.view.Menu import android.view.MenuItem import android.view.View import android.widget.TextView +import androidx.annotation.RequiresApi +import androidx.appcompat.widget.Toolbar +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView +import androidx.recyclerview.widget.SimpleItemAnimator +import com.google.android.material.snackbar.Snackbar import com.kunzisoft.keepass.R import com.kunzisoft.keepass.activities.dialogs.AssignMasterKeyDialogFragment import com.kunzisoft.keepass.activities.dialogs.BrowserDialogFragment @@ -49,11 +49,9 @@ import com.kunzisoft.keepass.activities.stylish.StylishActivity import com.kunzisoft.keepass.adapters.FileDatabaseHistoryAdapter import com.kunzisoft.keepass.app.database.FileDatabaseHistoryAction import com.kunzisoft.keepass.autofill.AutofillHelper -import com.kunzisoft.keepass.database.action.CreateDatabaseRunnable import com.kunzisoft.keepass.database.action.ProgressDialogThread -import com.kunzisoft.keepass.database.element.Database import com.kunzisoft.keepass.education.FileDatabaseSelectActivityEducation -import com.kunzisoft.keepass.tasks.ActionRunnable +import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_CREATE_TASK import com.kunzisoft.keepass.utils.MenuUtil import com.kunzisoft.keepass.utils.UriUtil import com.kunzisoft.keepass.view.asError @@ -77,6 +75,8 @@ class FileDatabaseSelectActivity : StylishActivity(), private var mOpenFileHelper: OpenFileHelper? = null + private var progressDialogThread: ProgressDialogThread? = null + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -160,6 +160,18 @@ class FileDatabaseSelectActivity : StylishActivity(), && savedInstanceState.containsKey(EXTRA_DATABASE_URI)) { mDatabaseFileUri = savedInstanceState.getParcelable(EXTRA_DATABASE_URI) } + + // Attach the dialog thread to this activity + progressDialogThread = ProgressDialogThread(this) { actionTask, result -> + when (actionTask) { + ACTION_DATABASE_CREATE_TASK -> { + // TODO Check + // mAdapterDatabaseHistory?.notifyDataSetChanged() + // updateFileListVisibility() + GroupActivity.launch(this) + } + } + } } /** @@ -259,6 +271,16 @@ class FileDatabaseSelectActivity : StylishActivity(), mAdapterDatabaseHistory?.notifyDataSetChanged() } } + + // Register progress task + progressDialogThread?.registerProgressTask() + } + + override fun onPause() { + // Unregister progress task + progressDialogThread?.unregisterProgressTask() + + super.onPause() } override fun onSaveInstanceState(outState: Bundle) { @@ -284,21 +306,13 @@ class FileDatabaseSelectActivity : StylishActivity(), mDatabaseFileUri?.let { databaseUri -> // Create the new database - ProgressDialogThread(this@FileDatabaseSelectActivity, - { - CreateDatabaseRunnable(this@FileDatabaseSelectActivity, - databaseUri, - Database.getInstance(), - masterPasswordChecked, - masterPassword, - keyFileChecked, - keyFile, - true, // TODO get readonly - LaunchGroupActivityFinish(databaseUri, keyFile) - ) - }, - R.string.progress_create) - .start() + progressDialogThread?.startDatabaseCreate( + databaseUri, + masterPasswordChecked, + masterPassword, + keyFileChecked, + keyFile + ) } } catch (e: Exception) { val error = getString(R.string.error_create_database_file) @@ -307,28 +321,6 @@ class FileDatabaseSelectActivity : StylishActivity(), } } - private inner class LaunchGroupActivityFinish(private val databaseFileUri: Uri, - private val keyFileUri: Uri?) : ActionRunnable() { - - override fun run() { - finishRun(true) - } - - override fun onFinishRun(result: Result) { - runOnUiThread { - if (result.isSuccess) { - // Add database to recent files - mFileDatabaseHistoryAction?.addOrUpdateDatabaseUri(databaseFileUri, keyFileUri) - mAdapterDatabaseHistory?.notifyDataSetChanged() - updateFileListVisibility() - GroupActivity.launch(this@FileDatabaseSelectActivity) - } else { - Log.e(TAG, "Unable to open the database") - } - } - } - } - override fun onAssignKeyDialogNegativeClick( masterPasswordChecked: Boolean, masterPassword: String?, keyFileChecked: Boolean, keyFile: Uri?) { diff --git a/app/src/main/java/com/kunzisoft/keepass/activities/GroupActivity.kt b/app/src/main/java/com/kunzisoft/keepass/activities/GroupActivity.kt index 79caaf0f0..54836e296 100644 --- a/app/src/main/java/com/kunzisoft/keepass/activities/GroupActivity.kt +++ b/app/src/main/java/com/kunzisoft/keepass/activities/GroupActivity.kt @@ -50,12 +50,19 @@ import com.kunzisoft.keepass.activities.lock.LockingActivity import com.kunzisoft.keepass.adapters.SearchEntryCursorAdapter import com.kunzisoft.keepass.autofill.AutofillHelper import com.kunzisoft.keepass.database.SortNodeEnum -import com.kunzisoft.keepass.database.action.ProgressDialogSaveDatabaseThread -import com.kunzisoft.keepass.database.action.node.* +import com.kunzisoft.keepass.database.action.ProgressDialogThread import com.kunzisoft.keepass.database.element.* import com.kunzisoft.keepass.education.GroupActivityEducation import com.kunzisoft.keepass.icons.assignDatabaseIcon import com.kunzisoft.keepass.magikeyboard.MagikIME +import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_COPY_NODES_TASK +import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_CREATE_GROUP_TASK +import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_DELETE_NODES_TASK +import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_MOVE_NODES_TASK +import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_UPDATE_GROUP_TASK +import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.NEW_NODES_KEY +import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.OLD_NODES_KEY +import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.getListNodesFromBundle import com.kunzisoft.keepass.settings.PreferencesUtil import com.kunzisoft.keepass.timeout.TimeoutHelper import com.kunzisoft.keepass.utils.MenuUtil @@ -85,6 +92,8 @@ class GroupActivity : LockingActivity(), private var mListNodesFragment: ListNodesFragment? = null private var mCurrentGroupIsASearch: Boolean = false + private var progressDialogThread: ProgressDialogThread? = null + // Nodes private var mRootGroup: GroupVersioned? = null private var mCurrentGroup: GroupVersioned? = null @@ -188,9 +197,64 @@ class GroupActivity : LockingActivity(), } }) - // Search suggestion mDatabase?.let { database -> + // Search suggestion mSearchSuggestionAdapter = SearchEntryCursorAdapter(this, database) + + // Init dialog thread + progressDialogThread = ProgressDialogThread(this) { actionTask, result -> + + var oldNodes: List = ArrayList() + result.data?.getBundle(OLD_NODES_KEY)?.let { oldNodesBundle -> + oldNodes = getListNodesFromBundle(database, oldNodesBundle) + } + var newNodes: List = ArrayList() + result.data?.getBundle(NEW_NODES_KEY)?.let { newNodesBundle -> + newNodes = getListNodesFromBundle(database, newNodesBundle) + } + + when (actionTask) { + ACTION_DATABASE_UPDATE_GROUP_TASK -> { + if (result.isSuccess) { + mListNodesFragment?.updateNodes(oldNodes, newNodes) + } + } + ACTION_DATABASE_CREATE_GROUP_TASK, + ACTION_DATABASE_COPY_NODES_TASK, + ACTION_DATABASE_MOVE_NODES_TASK -> { + if (result.isSuccess) { + mListNodesFragment?.addNodes(newNodes) + } + } + ACTION_DATABASE_DELETE_NODES_TASK -> { + if (result.isSuccess) { + + // Rebuild all the list the avoid bug when delete node from db sort + if (PreferencesUtil.getListSort(this@GroupActivity) == SortNodeEnum.DB) { + mListNodesFragment?.rebuildList() + } else { + // Use the old Nodes / entries unchanged with the old parent + mListNodesFragment?.removeNodes(oldNodes) + } + + // Add trash in views list if it doesn't exists + if (database.isRecycleBinEnabled) { + val recycleBin = database.recycleBin + if (mCurrentGroup != null && recycleBin != null + && mCurrentGroup!!.parent == null + && mCurrentGroup != recycleBin) { + if (mListNodesFragment?.contains(recycleBin) == true) + mListNodesFragment?.updateNode(recycleBin) + else + mListNodesFragment?.addNode(recycleBin) + } + } + } + } + } + + finishNodeAction() + } } Log.i(TAG, "Finished creating tree") @@ -487,28 +551,21 @@ class GroupActivity : LockingActivity(), ListNodesFragment.PasteMode.PASTE_FROM_COPY -> { // Copy mCurrentGroup?.let { newParent -> - ProgressDialogSaveDatabaseThread(this) { - CopyNodesRunnable(this, - Database.getInstance(), - nodes, - newParent, - AfterAddNodeRunnable(), - !mReadOnly) - }.start() + progressDialogThread?.startDatabaseCopyNodes( + nodes, + newParent, + !mReadOnly + ) } } ListNodesFragment.PasteMode.PASTE_FROM_MOVE -> { // Move mCurrentGroup?.let { newParent -> - ProgressDialogSaveDatabaseThread(this) { - MoveNodesRunnable( - this, - Database.getInstance(), - nodes, - newParent, - AfterAddNodeRunnable(), - !mReadOnly) - }.start() + progressDialogThread?.startDatabaseMoveNodes( + nodes, + newParent, + !mReadOnly + ) } } } @@ -516,14 +573,10 @@ class GroupActivity : LockingActivity(), } override fun onDeleteMenuClick(nodes: List): Boolean { - ProgressDialogSaveDatabaseThread(this) { - DeleteNodesRunnable( - this, - Database.getInstance(), - nodes, - AfterDeleteNodeRunnable(), - !mReadOnly) - }.start() + progressDialogThread?.startDatabaseDeleteNodes( + nodes, + !mReadOnly + ) return true } @@ -533,9 +586,13 @@ class GroupActivity : LockingActivity(), assignGroupViewElements() // Refresh suggestions to change preferences mSearchSuggestionAdapter?.reInit(this) + + progressDialogThread?.registerProgressTask() } override fun onPause() { + progressDialogThread?.unregisterProgressTask() + super.onPause() finishNodeAction() @@ -670,7 +727,6 @@ class GroupActivity : LockingActivity(), override fun approveEditGroup(action: GroupEditDialogFragment.EditGroupDialogAction?, name: String?, icon: PwIcon?) { - val database = Database.getInstance() if (name != null && name.isNotEmpty() && icon != null) { when (action) { @@ -678,25 +734,18 @@ class GroupActivity : LockingActivity(), // If group creation mCurrentGroup?.let { currentGroup -> // Build the group - database.createGroup()?.let { newGroup -> + mDatabase?.createGroup()?.let { newGroup -> newGroup.title = name newGroup.icon = icon // Not really needed here because added in runnable but safe newGroup.parent = currentGroup - // If group created save it in the database - ProgressDialogSaveDatabaseThread(this) { - AddGroupRunnable(this, - Database.getInstance(), - newGroup, - currentGroup, - AfterAddNodeRunnable(), - !mReadOnly) - }.start() + progressDialogThread?.startDatabaseCreateGroup( + newGroup, currentGroup, !mReadOnly) } } } - GroupEditDialogFragment.EditGroupDialogAction.UPDATE -> + GroupEditDialogFragment.EditGroupDialogAction.UPDATE -> { // If update add new elements mOldGroupToUpdate?.let { oldGroupToUpdate -> GroupVersioned(oldGroupToUpdate).let { updateGroup -> @@ -705,77 +754,17 @@ class GroupActivity : LockingActivity(), updateGroup.icon = icon mListNodesFragment?.removeNode(oldGroupToUpdate) - // If group updated save it in the database - ProgressDialogSaveDatabaseThread(this) { - UpdateGroupRunnable(this, - Database.getInstance(), - oldGroupToUpdate, - updateGroup, - AfterUpdateNodeRunnable(), - !mReadOnly) - }.start() + progressDialogThread?.startDatabaseUpdateGroup( + oldGroupToUpdate, updateGroup, !mReadOnly) } } + } else -> {} } } } - internal inner class AfterAddNodeRunnable : AfterActionNodeFinishRunnable() { - override fun onActionNodeFinish(actionNodeValues: ActionNodeValues) { - runOnUiThread { - if (actionNodeValues.result.isSuccess) { - mListNodesFragment?.addNodes(actionNodeValues.newNodes) - } - finishNodeAction() - } - } - } - - internal inner class AfterUpdateNodeRunnable : AfterActionNodeFinishRunnable() { - override fun onActionNodeFinish(actionNodeValues: ActionNodeValues) { - runOnUiThread { - if (actionNodeValues.result.isSuccess) { - mListNodesFragment?.updateNodes(actionNodeValues.oldNodes, actionNodeValues.newNodes) - } - finishNodeAction() - } - } - } - - internal inner class AfterDeleteNodeRunnable : AfterActionNodeFinishRunnable() { - override fun onActionNodeFinish(actionNodeValues: ActionNodeValues) { - runOnUiThread { - if (actionNodeValues.result.isSuccess) { - - // Rebuold all the list the avoid bug when delete node from db sort - if (PreferencesUtil.getListSort(this@GroupActivity) == SortNodeEnum.DB) { - mListNodesFragment?.rebuildList() - } else { - // Use the old Nodes / entries unchanged with the old parent - mListNodesFragment?.removeNodes(actionNodeValues.oldNodes) - } - - // Add trash in views list if it doesn't exists - val database = Database.getInstance() - if (database.isRecycleBinEnabled) { - val recycleBin = database.recycleBin - if (mCurrentGroup != null && recycleBin != null - && mCurrentGroup!!.parent == null - && mCurrentGroup != recycleBin) { - if (mListNodesFragment?.contains(recycleBin) == true) - mListNodesFragment?.updateNode(recycleBin) - else - mListNodesFragment?.addNode(recycleBin) - } - } - } - finishNodeAction() - } - } - } - override fun cancelEditGroup(action: GroupEditDialogFragment.EditGroupDialogAction?, name: String?, icon: PwIcon?) { diff --git a/app/src/main/java/com/kunzisoft/keepass/activities/PasswordActivity.kt b/app/src/main/java/com/kunzisoft/keepass/activities/PasswordActivity.kt index dee51828b..b95d558d8 100644 --- a/app/src/main/java/com/kunzisoft/keepass/activities/PasswordActivity.kt +++ b/app/src/main/java/com/kunzisoft/keepass/activities/PasswordActivity.kt @@ -57,13 +57,12 @@ import com.kunzisoft.keepass.app.database.CipherDatabaseEntity import com.kunzisoft.keepass.utils.FileDatabaseInfo import com.kunzisoft.keepass.app.database.FileDatabaseHistoryAction import com.kunzisoft.keepass.autofill.AutofillHelper -import com.kunzisoft.keepass.database.action.LoadDatabaseRunnable -import com.kunzisoft.keepass.database.action.ProgressDialogThread import com.kunzisoft.keepass.database.element.Database import com.kunzisoft.keepass.education.PasswordActivityEducation import com.kunzisoft.keepass.biometric.AdvancedUnlockedManager +import com.kunzisoft.keepass.database.action.ProgressDialogThread import com.kunzisoft.keepass.database.exception.LoadDatabaseDuplicateUuidException -import com.kunzisoft.keepass.database.search.SearchDbHelper +import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_LOAD_TASK import com.kunzisoft.keepass.settings.PreferencesUtil import com.kunzisoft.keepass.tasks.ActionRunnable import com.kunzisoft.keepass.utils.MenuUtil @@ -99,6 +98,8 @@ class PasswordActivity : StylishActivity() { private var readOnly: Boolean = false + private var progressDialogThread: ProgressDialogThread? = null + private var advancedUnlockedManager: AdvancedUnlockedManager? = null override fun onCreate(savedInstanceState: Bundle?) { @@ -158,6 +159,15 @@ class PasswordActivity : StylishActivity() { enableButtonOnCheckedChangeListener = CompoundButton.OnCheckedChangeListener { _, _ -> enableOrNotTheConfirmationButton() } + + progressDialogThread = ProgressDialogThread(this) { actionTask, result -> + when (actionTask) { + ACTION_DATABASE_LOAD_TASK -> { + // TODO + onFinishLoadDatabase?.onFinishRun(result) + } + } + } } private val onEditorActionListener = object : TextView.OnEditorActionListener { @@ -180,6 +190,8 @@ class PasswordActivity : StylishActivity() { // For check shutdown super.onResume() + progressDialogThread?.registerProgressTask() + initUriFromIntent() } @@ -372,6 +384,9 @@ class PasswordActivity : StylishActivity() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { advancedUnlockedManager?.pause() } + + progressDialogThread?.unregisterProgressTask() + super.onPause() } @@ -411,6 +426,8 @@ class PasswordActivity : StylishActivity() { checkboxPasswordView?.isChecked = false } + private var onFinishLoadDatabase: ActionRunnable? = null + private fun loadDatabase(databaseFileUri: Uri?, password: String?, keyFileUri: Uri?, @@ -428,7 +445,7 @@ class PasswordActivity : StylishActivity() { databaseFileUri?.let { databaseUri -> - val onFinishLoadDatabase = object: ActionRunnable() { + onFinishLoadDatabase = object: ActionRunnable() { override fun onFinishRun(result: Result) { runOnUiThread { // Recheck fingerprint if error @@ -442,9 +459,7 @@ class PasswordActivity : StylishActivity() { if (result.isSuccess) { // Save keyFile in app database if (mRememberKeyFile) { - mDatabaseFileUri?.let { databaseUri -> - saveKeyFileData(databaseUri, mDatabaseKeyFileUri) - } + saveKeyFileData(databaseFileUri, mDatabaseKeyFileUri) } // Remove the password in view in all cases @@ -469,12 +484,11 @@ class PasswordActivity : StylishActivity() { resultError = resultException.getLocalizedMessage(resources) if (resultException is LoadDatabaseDuplicateUuidException) showLoadDatabaseDuplicateUuidMessage { - showProgressDialogAndLoadDatabase(database, + showProgressDialogAndLoadDatabase( databaseUri, password, keyFileUri, - true, - this) + true) } } @@ -491,36 +505,26 @@ class PasswordActivity : StylishActivity() { } // Show the progress dialog and load the database - showProgressDialogAndLoadDatabase(database, + showProgressDialogAndLoadDatabase( databaseUri, password, keyFileUri, - false, - onFinishLoadDatabase) + false) } } - private fun showProgressDialogAndLoadDatabase(database: Database, - databaseUri: Uri, + private fun showProgressDialogAndLoadDatabase(databaseUri: Uri, password: String?, keyFile: Uri?, - fixDuplicateUUID: Boolean, - onFinishLoadDatabase: ActionRunnable) { - ProgressDialogThread(this, - { progressTaskUpdater -> - LoadDatabaseRunnable( - database, - databaseUri, - password, - keyFile, - this@PasswordActivity.contentResolver, - this@PasswordActivity.filesDir, - SearchDbHelper(PreferencesUtil.omitBackup(this@PasswordActivity)), - fixDuplicateUUID, - progressTaskUpdater, - onFinishLoadDatabase) - }, - R.string.loading_database).start() + fixDuplicateUUID: Boolean) { + progressDialogThread?.startDatabaseLoad( + databaseUri, + password, + keyFile, + filesDir, + PreferencesUtil.omitBackup(this@PasswordActivity), + fixDuplicateUUID + ) } private fun showLoadDatabaseDuplicateUuidMessage(loadDatabaseWithFix: (() -> Unit)? = null) { diff --git a/app/src/main/java/com/kunzisoft/keepass/database/action/LoadDatabaseRunnable.kt b/app/src/main/java/com/kunzisoft/keepass/database/action/LoadDatabaseRunnable.kt index b164fd70c..c63ed3aa6 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/action/LoadDatabaseRunnable.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/action/LoadDatabaseRunnable.kt @@ -23,7 +23,6 @@ import android.content.ContentResolver import android.net.Uri import com.kunzisoft.keepass.database.element.Database import com.kunzisoft.keepass.database.exception.LoadDatabaseException -import com.kunzisoft.keepass.database.search.SearchDbHelper import com.kunzisoft.keepass.tasks.ActionRunnable import com.kunzisoft.keepass.tasks.ProgressTaskUpdater import java.io.File @@ -34,18 +33,17 @@ class LoadDatabaseRunnable(private val mDatabase: Database, private val mKey: Uri?, private val contentResolver: ContentResolver, private val cacheDirectory: File, - private val mSearchHelper: SearchDbHelper, + private val mOmitBackup: Boolean, private val mFixDuplicateUUID: Boolean, - private val progressTaskUpdater: ProgressTaskUpdater?, - nestedAction: ActionRunnable) - : ActionRunnable(nestedAction, executeNestedActionIfResultFalse = true) { + private val progressTaskUpdater: ProgressTaskUpdater?) + : ActionRunnable(null, executeNestedActionIfResultFalse = true) { override fun run() { try { mDatabase.loadData(mUri, mPass, mKey, contentResolver, cacheDirectory, - mSearchHelper, + mOmitBackup, mFixDuplicateUUID, progressTaskUpdater) finishRun(true) diff --git a/app/src/main/java/com/kunzisoft/keepass/database/action/ProgressDialogSaveDatabaseThread.kt b/app/src/main/java/com/kunzisoft/keepass/database/action/ProgressDialogSaveDatabaseThread.kt deleted file mode 100644 index 33f97d9dd..000000000 --- a/app/src/main/java/com/kunzisoft/keepass/database/action/ProgressDialogSaveDatabaseThread.kt +++ /dev/null @@ -1,14 +0,0 @@ -package com.kunzisoft.keepass.database.action - -import androidx.fragment.app.FragmentActivity -import com.kunzisoft.keepass.R -import com.kunzisoft.keepass.tasks.ActionRunnable -import com.kunzisoft.keepass.tasks.ProgressTaskUpdater - -class ProgressDialogSaveDatabaseThread(activity: FragmentActivity, - actionRunnable: (ProgressTaskUpdater?)-> ActionRunnable) - : ProgressDialogThread(activity, - actionRunnable, - R.string.saving_database, - null, - R.string.do_not_kill_app) \ No newline at end of file diff --git a/app/src/main/java/com/kunzisoft/keepass/database/action/ProgressDialogThread.kt b/app/src/main/java/com/kunzisoft/keepass/database/action/ProgressDialogThread.kt index 38ff4ef09..ce559bc0d 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/action/ProgressDialogThread.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/action/ProgressDialogThread.kt @@ -1,86 +1,262 @@ package com.kunzisoft.keepass.database.action +import android.content.BroadcastReceiver +import android.content.Context import android.content.Intent -import android.os.AsyncTask +import android.content.IntentFilter +import android.net.Uri import android.os.Build -import androidx.annotation.StringRes +import android.os.Bundle import androidx.fragment.app.FragmentActivity +import com.kunzisoft.keepass.R +import com.kunzisoft.keepass.database.element.* import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService +import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_ASSIGN_PASSWORD_TASK +import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_COPY_NODES_TASK +import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_CREATE_ENTRY_TASK +import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_CREATE_GROUP_TASK +import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_CREATE_TASK +import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_DELETE_NODES_TASK +import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_LOAD_TASK +import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_MOVE_NODES_TASK +import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_SAVE_TASK +import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_UPDATE_ENTRY_TASK +import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_UPDATE_GROUP_TASK +import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_TASK_KEY +import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.DATABASE_TASK_MESSAGE_KEY +import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.DATABASE_TASK_SUBTITLE_KEY import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.DATABASE_TASK_TITLE_KEY +import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.RESULT_KEY +import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.getBundleFromListNodes import com.kunzisoft.keepass.tasks.ActionRunnable import com.kunzisoft.keepass.tasks.ProgressTaskDialogFragment -import com.kunzisoft.keepass.tasks.ProgressTaskUpdater import com.kunzisoft.keepass.timeout.TimeoutHelper +import com.kunzisoft.keepass.utils.DATABASE_CHECK_TASK_ACTION +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 -open class ProgressDialogThread(private val activity: FragmentActivity, - private val actionRunnable: (ProgressTaskUpdater?)-> ActionRunnable, - @StringRes private val titleId: Int, - @StringRes private val messageId: Int? = null, - @StringRes private val warningId: Int? = null) { +class ProgressDialogThread(private val activity: FragmentActivity, + var onActionFinish: (actionTask: String, + result: ActionRunnable.Result) -> Unit) { - private val progressTaskDialogFragment = ProgressTaskDialogFragment.build( - titleId, - messageId, - warningId) - private var actionRunnableAsyncTask: ActionRunnableAsyncTask? = null - var actionFinishInUIThread: ActionRunnable? = null + private var progressTaskDialogFragment: ProgressTaskDialogFragment? = null - private var intentDatabaseTask:Intent = Intent(activity, DatabaseTaskNotificationService::class.java) + private var databaseTaskBroadcastReceiver: BroadcastReceiver? = null - init { - actionRunnableAsyncTask = ActionRunnableAsyncTask(progressTaskDialogFragment, - { - activity.runOnUiThread { - intentDatabaseTask.putExtra(DATABASE_TASK_TITLE_KEY, titleId) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - activity.startForegroundService(intentDatabaseTask) - } else { - activity.startService(intentDatabaseTask) + private var intentDatabaseTask = Intent(activity, DatabaseTaskNotificationService::class.java) + + private fun startDialog(intent: Intent) { + TimeoutHelper.temporarilyDisableTimeout() + // Show the dialog + progressTaskDialogFragment = ProgressTaskDialogFragment.build( + intent.getIntExtra(DATABASE_TASK_TITLE_KEY, R.string.loading_database), + intent.getIntExtra(DATABASE_TASK_SUBTITLE_KEY, ProgressTaskDialogFragment.UNDEFINED), + intent.getIntExtra(DATABASE_TASK_MESSAGE_KEY, ProgressTaskDialogFragment.UNDEFINED)) + ProgressTaskDialogFragment.start(activity, progressTaskDialogFragment!!) + } + + private fun stopDialog(intent: Intent? = null) { + // Remove the progress task + ProgressTaskDialogFragment.stop(activity) + TimeoutHelper.releaseTemporarilyDisableTimeoutAndLockIfTimeout(activity) + activity.stopService(intentDatabaseTask) + if (intent != null + && intent.hasExtra(ACTION_TASK_KEY) + && intent.hasExtra(RESULT_KEY)) + onActionFinish.invoke( + intent.getStringExtra(ACTION_TASK_KEY), + ActionRunnable.Result.fromBundle(intent.getBundleExtra(RESULT_KEY))) + } + + fun registerProgressTask() { + // Register a database task receiver to stop loading dialog when service finish the task + databaseTaskBroadcastReceiver = object : BroadcastReceiver() { + override fun onReceive(context: Context?, intent: Intent?) { + if (intent == null) + stopDialog() + activity.runOnUiThread { + when (intent?.action) { + DATABASE_START_TASK_ACTION -> { + startDialog(intent) + } + DATABASE_STOP_TASK_ACTION -> { + stopDialog(intent) } - TimeoutHelper.temporarilyDisableTimeout() - // Show the dialog - ProgressTaskDialogFragment.start(activity, progressTaskDialogFragment) } - }, { result -> - activity.runOnUiThread { - actionFinishInUIThread?.onFinishRun(result) - // Remove the progress task - ProgressTaskDialogFragment.stop(activity) - TimeoutHelper.releaseTemporarilyDisableTimeoutAndLockIfTimeout(activity) - activity.stopService(intentDatabaseTask) - } - }) - } - - fun start() { - actionRunnableAsyncTask?.execute(actionRunnable) - } - - - private class ActionRunnableAsyncTask(private val progressTaskUpdater: ProgressTaskUpdater, - private val onPreExecute: () -> Unit, - private val onPostExecute: (result: ActionRunnable.Result) -> Unit) - : AsyncTask<((ProgressTaskUpdater?)-> ActionRunnable), Void, ActionRunnable.Result>() { - - override fun onPreExecute() { - super.onPreExecute() - onPreExecute.invoke() - } - - override fun doInBackground(vararg actionRunnables: ((ProgressTaskUpdater?)-> ActionRunnable)?): ActionRunnable.Result { - var resultTask = ActionRunnable.Result(false) - actionRunnables.forEach { - it?.invoke(progressTaskUpdater)?.apply { - run() - resultTask = result } } - return resultTask } + activity.registerReceiver(databaseTaskBroadcastReceiver, + IntentFilter().apply { + addAction(DATABASE_START_TASK_ACTION) + addAction(DATABASE_STOP_TASK_ACTION) + } + ) - override fun onPostExecute(result: ActionRunnable.Result) { - super.onPostExecute(result) - onPostExecute.invoke(result) + // Check if a service is currently running + activity.sendBroadcast(Intent(DATABASE_CHECK_TASK_ACTION)) + } + + fun unregisterProgressTask() { + activity.unregisterReceiver(databaseTaskBroadcastReceiver) + } + + private fun start(bundle: Bundle? = null, actionTask: String) { + activity.stopService(intentDatabaseTask) + if (bundle != null) + intentDatabaseTask.putExtras(bundle) + activity.runOnUiThread { + intentDatabaseTask.action = actionTask + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + activity.startForegroundService(intentDatabaseTask) + } else { + activity.startService(intentDatabaseTask) + } } } + + fun startDatabaseCreate(databaseUri: Uri, + masterPasswordChecked: Boolean, + masterPassword: String?, + keyFileChecked: Boolean, + keyFile: Uri?) { + start(Bundle().apply { + putParcelable(DatabaseTaskNotificationService.DATABASE_URI_KEY, databaseUri) + putBoolean(DatabaseTaskNotificationService.MASTER_PASSWORD_CHECKED_KEY, masterPasswordChecked) + putString(DatabaseTaskNotificationService.MASTER_PASSWORD_KEY, masterPassword) + putBoolean(DatabaseTaskNotificationService.KEY_FILE_CHECKED_KEY, keyFileChecked) + putParcelable(DatabaseTaskNotificationService.KEY_FILE_KEY, keyFile) + } + , ACTION_DATABASE_CREATE_TASK) + } + + fun startDatabaseSave() { + start(null, ACTION_DATABASE_SAVE_TASK) + } + + fun startDatabaseLoad(databaseUri: Uri, + masterPassword: String?, + keyFile: Uri?, + 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) + putSerializable(DatabaseTaskNotificationService.CACHE_DIR_KEY, filesDir) + putBoolean(DatabaseTaskNotificationService.OMIT_BACKUP_KEY, omitBackup) + putBoolean(DatabaseTaskNotificationService.FIX_DUPLICATE_UUID_KEY, fixDuplicateUuid) + } + , ACTION_DATABASE_LOAD_TASK) + } + + fun startDatabaseAssignPassword(masterPasswordChecked: Boolean, + masterPassword: String?, + keyFileChecked: Boolean, + keyFile: Uri?) { + + start(Bundle().apply { + putBoolean(DatabaseTaskNotificationService.MASTER_PASSWORD_CHECKED_KEY, masterPasswordChecked) + putString(DatabaseTaskNotificationService.MASTER_PASSWORD_KEY, masterPassword) + putBoolean(DatabaseTaskNotificationService.KEY_FILE_CHECKED_KEY, keyFileChecked) + putParcelable(DatabaseTaskNotificationService.KEY_FILE_KEY, keyFile) + } + , ACTION_DATABASE_ASSIGN_PASSWORD_TASK) + } + + fun startDatabaseCreateGroup(newGroup: GroupVersioned, + parent: GroupVersioned, + save: Boolean) { + start(Bundle().apply { + putParcelable(DatabaseTaskNotificationService.GROUP_KEY, newGroup) + putParcelable(DatabaseTaskNotificationService.PARENT_ID_KEY, parent.nodeId) + putBoolean(DatabaseTaskNotificationService.SAVE_DATABASE_KEY, save) + } + , ACTION_DATABASE_CREATE_GROUP_TASK) + } + + fun startDatabaseUpdateGroup(oldGroup: GroupVersioned, + groupToUpdate: GroupVersioned, + save: Boolean) { + start(Bundle().apply { + putParcelable(DatabaseTaskNotificationService.OLD_GROUP_KEY, oldGroup) + putParcelable(DatabaseTaskNotificationService.GROUP_KEY, groupToUpdate) + putBoolean(DatabaseTaskNotificationService.SAVE_DATABASE_KEY, save) + } + , ACTION_DATABASE_UPDATE_GROUP_TASK) + } + + fun startDatabaseCreateEntry(newEntry: EntryVersioned, + parent: GroupVersioned, + save: Boolean) { + start(Bundle().apply { + putParcelable(DatabaseTaskNotificationService.ENTRY_KEY, newEntry) + putParcelable(DatabaseTaskNotificationService.PARENT_ID_KEY, parent.nodeId) + putBoolean(DatabaseTaskNotificationService.SAVE_DATABASE_KEY, save) + } + , ACTION_DATABASE_CREATE_ENTRY_TASK) + } + + fun startDatabaseUpdateEntry(oldEntry: EntryVersioned, + entryToUpdate: EntryVersioned, + save: Boolean) { + start(Bundle().apply { + putParcelable(DatabaseTaskNotificationService.OLD_ENTRY_KEY, oldEntry) + putParcelable(DatabaseTaskNotificationService.ENTRY_KEY, entryToUpdate) + putBoolean(DatabaseTaskNotificationService.SAVE_DATABASE_KEY, save) + } + , ACTION_DATABASE_UPDATE_ENTRY_TASK) + } + + private fun startDatabaseActionListNodes(actionTask: String, + nodesPaste: List, + newParent: GroupVersioned?, + save: Boolean) { + val groupsIdToCopy = ArrayList>() + val entriesIdToCopy = ArrayList>() + nodesPaste.forEach { nodeVersioned -> + when (nodeVersioned.type) { + Type.GROUP -> { + (nodeVersioned as GroupVersioned).nodeId?.let { groupId -> + groupsIdToCopy.add(groupId) + } + } + Type.ENTRY -> { + entriesIdToCopy.add((nodeVersioned as EntryVersioned).nodeId) + } + } + } + val newParentId = newParent?.nodeId + + start(Bundle().apply { + putAll(getBundleFromListNodes(nodesPaste)) + putParcelableArrayList(DatabaseTaskNotificationService.GROUPS_ID_KEY, groupsIdToCopy) + putParcelableArrayList(DatabaseTaskNotificationService.ENTRIES_ID_KEY, entriesIdToCopy) + if (newParentId != null) + putParcelable(DatabaseTaskNotificationService.PARENT_ID_KEY, newParentId) + putBoolean(DatabaseTaskNotificationService.SAVE_DATABASE_KEY, save) + } + , actionTask) + } + + fun startDatabaseCopyNodes(nodesToCopy: List, + newParent: GroupVersioned, + save: Boolean) { + startDatabaseActionListNodes(ACTION_DATABASE_COPY_NODES_TASK, nodesToCopy, newParent, save) + } + + fun startDatabaseMoveNodes(nodesToMove: List, + newParent: GroupVersioned, + save: Boolean) { + startDatabaseActionListNodes(ACTION_DATABASE_MOVE_NODES_TASK, nodesToMove, newParent, save) + } + + fun startDatabaseDeleteNodes(nodesToDelete: List, + save: Boolean) { + startDatabaseActionListNodes(ACTION_DATABASE_DELETE_NODES_TASK, nodesToDelete, null, save) + } } \ No newline at end of file diff --git a/app/src/main/java/com/kunzisoft/keepass/database/action/SaveDatabaseRunnable.kt b/app/src/main/java/com/kunzisoft/keepass/database/action/SaveDatabaseRunnable.kt index 62aa0956e..608326421 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/action/SaveDatabaseRunnable.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/action/SaveDatabaseRunnable.kt @@ -30,7 +30,6 @@ abstract class SaveDatabaseRunnable(protected var context: Context, private val save: Boolean, nestedAction: ActionRunnable? = null) : ActionRunnable(nestedAction) { - // TODO Service to prevent background thread kill override fun run() { if (save) { try { diff --git a/app/src/main/java/com/kunzisoft/keepass/database/action/node/ActionNodeDatabaseRunnable.kt b/app/src/main/java/com/kunzisoft/keepass/database/action/node/ActionNodeDatabaseRunnable.kt index 17ac47642..7314f59f6 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/action/node/ActionNodeDatabaseRunnable.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/action/node/ActionNodeDatabaseRunnable.kt @@ -1,12 +1,12 @@ package com.kunzisoft.keepass.database.action.node -import androidx.fragment.app.FragmentActivity +import android.content.Context import android.util.Log import com.kunzisoft.keepass.database.action.SaveDatabaseRunnable import com.kunzisoft.keepass.database.element.Database abstract class ActionNodeDatabaseRunnable( - context: FragmentActivity, + context: Context, database: Database, private val callbackRunnable: AfterActionNodeFinishRunnable?, save: Boolean) diff --git a/app/src/main/java/com/kunzisoft/keepass/database/action/node/AddEntryRunnable.kt b/app/src/main/java/com/kunzisoft/keepass/database/action/node/AddEntryRunnable.kt index 2442fe3f3..aed325030 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/action/node/AddEntryRunnable.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/action/node/AddEntryRunnable.kt @@ -19,19 +19,19 @@ */ package com.kunzisoft.keepass.database.action.node -import androidx.fragment.app.FragmentActivity +import android.content.Context import com.kunzisoft.keepass.database.element.Database import com.kunzisoft.keepass.database.element.EntryVersioned import com.kunzisoft.keepass.database.element.GroupVersioned import com.kunzisoft.keepass.database.element.NodeVersioned class AddEntryRunnable constructor( - context: FragmentActivity, + context: Context, database: Database, private val mNewEntry: EntryVersioned, private val mParent: GroupVersioned, - finishRunnable: AfterActionNodeFinishRunnable?, - save: Boolean) + save: Boolean, + finishRunnable: AfterActionNodeFinishRunnable?) : ActionNodeDatabaseRunnable(context, database, finishRunnable, save) { override fun nodeAction() { diff --git a/app/src/main/java/com/kunzisoft/keepass/database/action/node/AddGroupRunnable.kt b/app/src/main/java/com/kunzisoft/keepass/database/action/node/AddGroupRunnable.kt index 45be065c8..629cfaab0 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/action/node/AddGroupRunnable.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/action/node/AddGroupRunnable.kt @@ -19,18 +19,18 @@ */ package com.kunzisoft.keepass.database.action.node -import androidx.fragment.app.FragmentActivity +import android.content.Context import com.kunzisoft.keepass.database.element.Database import com.kunzisoft.keepass.database.element.GroupVersioned import com.kunzisoft.keepass.database.element.NodeVersioned class AddGroupRunnable constructor( - context: FragmentActivity, + context: Context, database: Database, private val mNewGroup: GroupVersioned, private val mParent: GroupVersioned, - afterAddNodeRunnable: AfterActionNodeFinishRunnable?, - save: Boolean) + save: Boolean, + afterAddNodeRunnable: AfterActionNodeFinishRunnable?) : ActionNodeDatabaseRunnable(context, database, afterAddNodeRunnable, save) { override fun nodeAction() { diff --git a/app/src/main/java/com/kunzisoft/keepass/database/action/node/CopyNodesRunnable.kt b/app/src/main/java/com/kunzisoft/keepass/database/action/node/CopyNodesRunnable.kt index fccda23ca..13f7f005f 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/action/node/CopyNodesRunnable.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/action/node/CopyNodesRunnable.kt @@ -19,18 +19,18 @@ */ package com.kunzisoft.keepass.database.action.node +import android.content.Context import android.util.Log -import androidx.fragment.app.FragmentActivity import com.kunzisoft.keepass.R import com.kunzisoft.keepass.database.element.* class CopyNodesRunnable constructor( - context: FragmentActivity, + context: Context, database: Database, private val mNodesToCopy: List, private val mNewParent: GroupVersioned, - afterAddNodeRunnable: AfterActionNodeFinishRunnable?, - save: Boolean) + save: Boolean, + afterAddNodeRunnable: AfterActionNodeFinishRunnable?) : ActionNodeDatabaseRunnable(context, database, afterAddNodeRunnable, save) { private var mEntriesCopied = ArrayList() diff --git a/app/src/main/java/com/kunzisoft/keepass/database/action/node/DeleteNodesRunnable.kt b/app/src/main/java/com/kunzisoft/keepass/database/action/node/DeleteNodesRunnable.kt index 1b1a7d21e..8b9e19719 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/action/node/DeleteNodesRunnable.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/action/node/DeleteNodesRunnable.kt @@ -19,14 +19,16 @@ */ package com.kunzisoft.keepass.database.action.node -import androidx.fragment.app.FragmentActivity +import android.content.Context import com.kunzisoft.keepass.database.element.* -class DeleteNodesRunnable(context: FragmentActivity, +class DeleteNodesRunnable(context: Context, database: Database, private val mNodesToDelete: List, - finish: AfterActionNodeFinishRunnable, - save: Boolean) : ActionNodeDatabaseRunnable(context, database, finish, save) { + save: Boolean, + finish: AfterActionNodeFinishRunnable) + : ActionNodeDatabaseRunnable(context, database, finish, save) { + private var mParent: GroupVersioned? = null private var mCanRecycle: Boolean = false diff --git a/app/src/main/java/com/kunzisoft/keepass/database/action/node/MoveNodesRunnable.kt b/app/src/main/java/com/kunzisoft/keepass/database/action/node/MoveNodesRunnable.kt index 7ef2ea0e6..eae67f0d2 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/action/node/MoveNodesRunnable.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/action/node/MoveNodesRunnable.kt @@ -19,18 +19,18 @@ */ package com.kunzisoft.keepass.database.action.node -import androidx.fragment.app.FragmentActivity +import android.content.Context import android.util.Log import com.kunzisoft.keepass.R import com.kunzisoft.keepass.database.element.* class MoveNodesRunnable constructor( - context: FragmentActivity, + context: Context, database: Database, private val mNodesToMove: List, private val mNewParent: GroupVersioned, - afterAddNodeRunnable: AfterActionNodeFinishRunnable?, - save: Boolean) + save: Boolean, + afterAddNodeRunnable: AfterActionNodeFinishRunnable?) : ActionNodeDatabaseRunnable(context, database, afterAddNodeRunnable, save) { private var mOldParent: GroupVersioned? = null diff --git a/app/src/main/java/com/kunzisoft/keepass/database/action/node/UpdateEntryRunnable.kt b/app/src/main/java/com/kunzisoft/keepass/database/action/node/UpdateEntryRunnable.kt index 292cb8a45..042729e97 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/action/node/UpdateEntryRunnable.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/action/node/UpdateEntryRunnable.kt @@ -19,42 +19,42 @@ */ package com.kunzisoft.keepass.database.action.node -import androidx.fragment.app.FragmentActivity +import android.content.Context import com.kunzisoft.keepass.database.element.Database import com.kunzisoft.keepass.database.element.EntryVersioned import com.kunzisoft.keepass.database.element.NodeVersioned class UpdateEntryRunnable constructor( - context: FragmentActivity, + context: Context, database: Database, private val mOldEntry: EntryVersioned, private val mNewEntry: EntryVersioned, - finishRunnable: AfterActionNodeFinishRunnable?, - save: Boolean) + save: Boolean, + finishRunnable: AfterActionNodeFinishRunnable?) : ActionNodeDatabaseRunnable(context, database, finishRunnable, save) { // Keep backup of original values in case save fails - private var mBackupEntryHistory: EntryVersioned? = null + private var mBackupEntryHistory: EntryVersioned = EntryVersioned(mOldEntry) override fun nodeAction() { - mNewEntry.touch(modified = true, touchParents = true) - - mBackupEntryHistory = EntryVersioned(mOldEntry) - - // Create an entry history (an entry history don't have history) - mNewEntry.addEntryToHistory(EntryVersioned(mOldEntry, copyHistory = false)) - - database.removeOldestHistory(mNewEntry) // Update entry with new values mOldEntry.updateWith(mNewEntry) + mNewEntry.touch(modified = true, touchParents = true) + + // Create an entry history (an entry history don't have history) + mOldEntry.addEntryToHistory(EntryVersioned(mBackupEntryHistory, copyHistory = false)) + + database.removeOldestHistory(mOldEntry) + + // Only change data un index + // TODO + database.updateEntry(mOldEntry) } override fun nodeFinish(result: Result): ActionNodeValues { if (!result.isSuccess) { // If we fail to save, back out changes to global structure - mBackupEntryHistory?.let { - mOldEntry.updateWith(it) - } + database.updateEntry(mOldEntry) } val oldNodesReturn = ArrayList() diff --git a/app/src/main/java/com/kunzisoft/keepass/database/action/node/UpdateGroupRunnable.kt b/app/src/main/java/com/kunzisoft/keepass/database/action/node/UpdateGroupRunnable.kt index eb766a4e0..1fec741e1 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/action/node/UpdateGroupRunnable.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/action/node/UpdateGroupRunnable.kt @@ -19,18 +19,18 @@ */ package com.kunzisoft.keepass.database.action.node -import androidx.fragment.app.FragmentActivity +import android.content.Context import com.kunzisoft.keepass.database.element.Database import com.kunzisoft.keepass.database.element.GroupVersioned import com.kunzisoft.keepass.database.element.NodeVersioned class UpdateGroupRunnable constructor( - context: FragmentActivity, + context: Context, database: Database, private val mOldGroup: GroupVersioned, private val mNewGroup: GroupVersioned, - finishRunnable: AfterActionNodeFinishRunnable?, - save: Boolean) + save: Boolean, + finishRunnable: AfterActionNodeFinishRunnable?) : ActionNodeDatabaseRunnable(context, database, finishRunnable, save) { // Keep backup of original values in case save fails @@ -38,8 +38,12 @@ class UpdateGroupRunnable constructor( override fun nodeAction() { // Update group with new values - mOldGroup.touch(modified = true, touchParents = true) mOldGroup.updateWith(mNewGroup) + mOldGroup.touch(modified = true, touchParents = true) + + // Only change data un index + // TODO + database.updateGroup(mOldGroup) } override fun nodeFinish(result: Result): ActionNodeValues { diff --git a/app/src/main/java/com/kunzisoft/keepass/database/element/Database.kt b/app/src/main/java/com/kunzisoft/keepass/database/element/Database.kt index 111c5cb77..7645b7f14 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/element/Database.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/element/Database.kt @@ -290,7 +290,7 @@ class Database { fun loadData(uri: Uri, password: String?, keyfile: Uri?, contentResolver: ContentResolver, cacheDirectory: File, - searchHelper: SearchDbHelper, + omitBackup: Boolean, fixDuplicateUUID: Boolean, progressTaskUpdater: ProgressTaskUpdater?) { @@ -359,7 +359,7 @@ class Database { else -> throw LoadDatabaseSignatureException() } - this.mSearchHelper = searchHelper + this.mSearchHelper = SearchDbHelper(omitBackup) loaded = true } @@ -488,7 +488,7 @@ class Database { // In all cases, delete all the files in the temp dir try { FileUtils.cleanDirectory(filesDirectory) - } catch (e: IOException) { + } catch (e: Exception) { Log.e(TAG, "Unable to clear the directory cache.", e) } @@ -576,6 +576,15 @@ class Database { entry.afterAssignNewParent() } + fun updateEntry(entry: EntryVersioned) { + entry.pwEntryV3?.let { entryV3 -> + pwDatabaseV3?.updateEntry(entryV3) + } + entry.pwEntryV4?.let { entryV4 -> + pwDatabaseV4?.updateEntry(entryV4) + } + } + fun removeEntryFrom(entry: EntryVersioned, parent: GroupVersioned) { entry.pwEntryV3?.let { entryV3 -> pwDatabaseV3?.removeEntryFrom(entryV3, parent.pwGroupV3) @@ -596,6 +605,15 @@ class Database { group.afterAssignNewParent() } + fun updateGroup(group: GroupVersioned) { + group.pwGroupV3?.let { groupV3 -> + pwDatabaseV3?.updateGroup(groupV3) + } + group.pwGroupV4?.let { groupV4 -> + pwDatabaseV4?.updateGroup(groupV4) + } + } + fun removeGroupFrom(group: GroupVersioned, parent: GroupVersioned) { group.pwGroupV3?.let { groupV3 -> pwDatabaseV3?.removeGroupFrom(groupV3, parent.pwGroupV3) diff --git a/app/src/main/java/com/kunzisoft/keepass/database/element/GroupVersioned.kt b/app/src/main/java/com/kunzisoft/keepass/database/element/GroupVersioned.kt index a7be65c03..995491394 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/element/GroupVersioned.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/element/GroupVersioned.kt @@ -237,6 +237,24 @@ class GroupVersioned : NodeVersioned, PwGroupInterface, Entry> : PwNod fun addChildEntry(entry: Entry) + fun updateChildEntry(entry: Entry) + + fun updateChildGroup(group: Group) + fun removeChildGroup(group: Group) fun removeChildEntry(entry: Entry) diff --git a/app/src/main/java/com/kunzisoft/keepass/notifications/DatabaseTaskNotificationService.kt b/app/src/main/java/com/kunzisoft/keepass/notifications/DatabaseTaskNotificationService.kt index 9c11c6d1d..3d5e34d6c 100644 --- a/app/src/main/java/com/kunzisoft/keepass/notifications/DatabaseTaskNotificationService.kt +++ b/app/src/main/java/com/kunzisoft/keepass/notifications/DatabaseTaskNotificationService.kt @@ -1,20 +1,136 @@ package com.kunzisoft.keepass.notifications +import android.content.BroadcastReceiver +import android.content.Context import android.content.Intent +import android.content.IntentFilter +import android.net.Uri +import android.os.AsyncTask +import android.os.Bundle import android.util.Log import com.kunzisoft.keepass.R +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.node.* +import com.kunzisoft.keepass.database.element.* +import com.kunzisoft.keepass.tasks.ActionRunnable +import com.kunzisoft.keepass.tasks.ProgressTaskUpdater +import com.kunzisoft.keepass.utils.DATABASE_CHECK_TASK_ACTION +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 -class DatabaseTaskNotificationService : NotificationService() { +class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdater { - override var notificationId = 532 + override var notificationId: Int = 575 + + private var actionRunnableAsyncTask: ActionRunnableAsyncTask? = null + + private var checkBroadcastReceiver: BroadcastReceiver? = null + + override fun onCreate() { + super.onCreate() + + checkBroadcastReceiver = object: BroadcastReceiver() { + override fun onReceive(context: Context?, intent: Intent?) { + sendBroadcast(Intent(DATABASE_START_TASK_ACTION)) + } + } + + registerReceiver(checkBroadcastReceiver, IntentFilter().apply { + addAction(DATABASE_CHECK_TASK_ACTION) + } + ) + } + + override fun onDestroy() { + unregisterReceiver(checkBroadcastReceiver) + + super.onDestroy() + } override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { - if (intent == null) { - Log.w(TAG, "null intent") - } else { - newNotification(intent.getIntExtra(DATABASE_TASK_TITLE_KEY, R.string.saving_database)) + + if (intent == null) return START_REDELIVER_INTENT + + val titleId: Int = when (intent.action) { + ACTION_DATABASE_CREATE_TASK -> R.string.creating_database + ACTION_DATABASE_SAVE_TASK, + ACTION_DATABASE_ASSIGN_PASSWORD_TASK, + ACTION_DATABASE_CREATE_GROUP_TASK, + ACTION_DATABASE_UPDATE_GROUP_TASK, + ACTION_DATABASE_CREATE_ENTRY_TASK, + ACTION_DATABASE_UPDATE_ENTRY_TASK, + ACTION_DATABASE_COPY_NODES_TASK, + ACTION_DATABASE_MOVE_NODES_TASK, + ACTION_DATABASE_DELETE_NODES_TASK -> R.string.saving_database + ACTION_DATABASE_LOAD_TASK -> R.string.loading_database + else -> R.string.loading_database } - return START_NOT_STICKY + val subtitleId: Int? = when (intent.action) { + else -> null + } + val messageId: Int? = when (intent.action) { + ACTION_DATABASE_LOAD_TASK -> null + else -> R.string.do_not_kill_app + } + + val actionRunnable: ActionRunnable? = when (intent.action) { + ACTION_DATABASE_CREATE_TASK -> buildDatabaseCreateActionTask(intent) + ACTION_DATABASE_SAVE_TASK -> buildDatabaseSaveActionTask() + ACTION_DATABASE_LOAD_TASK -> buildDatabaseLoadActionTask(intent) + ACTION_DATABASE_ASSIGN_PASSWORD_TASK -> buildDatabaseAssignPasswordActionTask(intent) + ACTION_DATABASE_CREATE_GROUP_TASK -> buildDatabaseCreateGroupActionTask(intent) + ACTION_DATABASE_UPDATE_GROUP_TASK -> buildDatabaseUpdateGroupActionTask(intent) + ACTION_DATABASE_CREATE_ENTRY_TASK -> buildDatabaseCreateEntryActionTask(intent) + ACTION_DATABASE_UPDATE_ENTRY_TASK -> buildDatabaseUpdateEntryActionTask(intent) + ACTION_DATABASE_COPY_NODES_TASK -> buildDatabaseCopyNodesActionTask(intent) + ACTION_DATABASE_MOVE_NODES_TASK -> buildDatabaseMoveNodesActionTask(intent) + ACTION_DATABASE_DELETE_NODES_TASK -> buildDatabaseDeleteNodesActionTask(intent) + else -> null + } + + when (intent.action ) { + ACTION_DATABASE_CREATE_TASK, + ACTION_DATABASE_SAVE_TASK, + ACTION_DATABASE_LOAD_TASK, + ACTION_DATABASE_ASSIGN_PASSWORD_TASK, + ACTION_DATABASE_CREATE_GROUP_TASK, + ACTION_DATABASE_UPDATE_GROUP_TASK, + ACTION_DATABASE_CREATE_ENTRY_TASK, + ACTION_DATABASE_UPDATE_ENTRY_TASK, + ACTION_DATABASE_COPY_NODES_TASK, + ACTION_DATABASE_MOVE_NODES_TASK, + ACTION_DATABASE_DELETE_NODES_TASK -> { + newNotification(intent.getIntExtra(DATABASE_TASK_TITLE_KEY, titleId)) + actionRunnableAsyncTask = ActionRunnableAsyncTask(this, + { + sendBroadcast(Intent(DATABASE_START_TASK_ACTION).apply { + putExtra(DATABASE_TASK_TITLE_KEY, titleId) + putExtra(DATABASE_TASK_SUBTITLE_KEY, subtitleId) + putExtra(DATABASE_TASK_MESSAGE_KEY, messageId) + }) + + }, { result -> + sendBroadcast(Intent(DATABASE_STOP_TASK_ACTION).apply { + putExtra(ACTION_TASK_KEY, intent.action) + putExtra(RESULT_KEY, result.toBundle()) + }) + } + ) + actionRunnable?.let { actionRunnableNotNull -> + actionRunnableAsyncTask?.execute({ actionRunnableNotNull }) + } + } + else -> {} + } + + return START_REDELIVER_INTENT } private fun newNotification(title: Int) { @@ -27,11 +143,340 @@ class DatabaseTaskNotificationService : NotificationService() { startForeground(notificationId, builder.build()) } + override fun updateMessage(resId: Int) { + // TODO + } + + private fun buildDatabaseCreateActionTask(intent: Intent): ActionRunnable? { + + if (intent.hasExtra(DATABASE_URI_KEY) + && intent.hasExtra(MASTER_PASSWORD_CHECKED_KEY) + && intent.hasExtra(MASTER_PASSWORD_KEY) + && intent.hasExtra(KEY_FILE_CHECKED_KEY) + && intent.hasExtra(KEY_FILE_KEY) + ) { + val databaseUri: Uri = intent.getParcelableExtra(DATABASE_URI_KEY) + val keyFileUri: Uri? = intent.getParcelableExtra(KEY_FILE_KEY) + return CreateDatabaseRunnable(this, + databaseUri, + Database.getInstance(), + intent.getBooleanExtra(MASTER_PASSWORD_CHECKED_KEY, false), + 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") + } + } + } + ) + } else { + return null + } + } + + private fun buildDatabaseSaveActionTask(): ActionRunnable? { + return SaveDatabaseActionRunnable(this, + Database.getInstance(), + true) + } + + private fun buildDatabaseLoadActionTask(intent: Intent): ActionRunnable? { + + if (intent.hasExtra(DATABASE_URI_KEY) + && intent.hasExtra(MASTER_PASSWORD_KEY) + && intent.hasExtra(KEY_FILE_KEY) + && intent.hasExtra(CACHE_DIR_KEY) + && intent.hasExtra(OMIT_BACKUP_KEY) + && intent.hasExtra(FIX_DUPLICATE_UUID_KEY) + ) { + return LoadDatabaseRunnable( + Database.getInstance(), + intent.getParcelableExtra(DATABASE_URI_KEY), + intent.getStringExtra(MASTER_PASSWORD_KEY), + intent.getParcelableExtra(KEY_FILE_KEY), + contentResolver, + intent.getSerializableExtra(CACHE_DIR_KEY) as File, + intent.getBooleanExtra(OMIT_BACKUP_KEY, false), + intent.getBooleanExtra(FIX_DUPLICATE_UUID_KEY, false), + this) + } else { + return null + } + } + + private fun buildDatabaseAssignPasswordActionTask(intent: Intent): ActionRunnable? { + return if (intent.hasExtra(MASTER_PASSWORD_CHECKED_KEY) + && intent.hasExtra(MASTER_PASSWORD_KEY) + && intent.hasExtra(KEY_FILE_CHECKED_KEY) + && intent.hasExtra(KEY_FILE_KEY) + ) { + AssignPasswordInDatabaseRunnable(this, + Database.getInstance(), + intent.getBooleanExtra(MASTER_PASSWORD_CHECKED_KEY, false), + intent.getStringExtra(MASTER_PASSWORD_KEY), + intent.getBooleanExtra(KEY_FILE_CHECKED_KEY, false), + intent.getParcelableExtra(KEY_FILE_KEY), + true) + } else { + null + } + } + + private fun buildDatabaseCreateGroupActionTask(intent: Intent): ActionRunnable? { + return if (intent.hasExtra(GROUP_KEY) + && intent.hasExtra(PARENT_ID_KEY) + && intent.hasExtra(SAVE_DATABASE_KEY) + ) { + val database = Database.getInstance() + database.getGroupById(intent.getParcelableExtra(PARENT_ID_KEY))?.let { parent -> + AddGroupRunnable(this, + database, + intent.getParcelableExtra(GROUP_KEY), + parent, + intent.getBooleanExtra(SAVE_DATABASE_KEY, false), + AfterActionNodeRunnable()) + } + } else { + null + } + } + + private fun buildDatabaseUpdateGroupActionTask(intent: Intent): ActionRunnable? { + return if (intent.hasExtra(OLD_GROUP_KEY) + && intent.hasExtra(GROUP_KEY) + && intent.hasExtra(SAVE_DATABASE_KEY) + ) { + UpdateGroupRunnable(this, + Database.getInstance(), + intent.getParcelableExtra(OLD_GROUP_KEY), + intent.getParcelableExtra(GROUP_KEY), + intent.getBooleanExtra(SAVE_DATABASE_KEY, false), + AfterActionNodeRunnable()) + } else { + null + } + } + + private fun buildDatabaseCreateEntryActionTask(intent: Intent): ActionRunnable? { + return if (intent.hasExtra(ENTRY_KEY) + && intent.hasExtra(PARENT_ID_KEY) + && intent.hasExtra(SAVE_DATABASE_KEY) + ) { + val database = Database.getInstance() + database.getGroupById(intent.getParcelableExtra(PARENT_ID_KEY))?.let { parent -> + AddEntryRunnable(this, + database, + intent.getParcelableExtra(ENTRY_KEY), + parent, + intent.getBooleanExtra(SAVE_DATABASE_KEY, false), + AfterActionNodeRunnable()) + } + } else { + null + } + } + + private fun buildDatabaseUpdateEntryActionTask(intent: Intent): ActionRunnable? { + return if (intent.hasExtra(OLD_ENTRY_KEY) + && intent.hasExtra(ENTRY_KEY) + && intent.hasExtra(SAVE_DATABASE_KEY) + ) { + UpdateEntryRunnable(this, + Database.getInstance(), + intent.getParcelableExtra(OLD_ENTRY_KEY), + intent.getParcelableExtra(ENTRY_KEY), + intent.getBooleanExtra(SAVE_DATABASE_KEY, false), + AfterActionNodeRunnable()) + } else { + null + } + } + + 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 fun buildDatabaseCopyNodesActionTask(intent: Intent): ActionRunnable? { + return if (intent.hasExtra(GROUPS_ID_KEY) + && intent.hasExtra(ENTRIES_ID_KEY) + && intent.hasExtra(PARENT_ID_KEY) + && intent.hasExtra(SAVE_DATABASE_KEY) + ) { + val database = Database.getInstance() + database.getGroupById(intent.getParcelableExtra(PARENT_ID_KEY))?.let { newParent -> + CopyNodesRunnable(this, + database, + getListNodesFromBundle(database, intent.extras!!), + newParent, + intent.getBooleanExtra(SAVE_DATABASE_KEY, false), + AfterActionNodeRunnable()) + } + + } else { + null + } + } + + private fun buildDatabaseMoveNodesActionTask(intent: Intent): ActionRunnable? { + return if (intent.hasExtra(GROUPS_ID_KEY) + && intent.hasExtra(ENTRIES_ID_KEY) + && intent.hasExtra(PARENT_ID_KEY) + && intent.hasExtra(SAVE_DATABASE_KEY) + ) { + val database = Database.getInstance() + database.getGroupById(intent.getParcelableExtra(PARENT_ID_KEY))?.let { newParent -> + MoveNodesRunnable(this, + database, + getListNodesFromBundle(database, intent.extras!!), + newParent, + intent.getBooleanExtra(SAVE_DATABASE_KEY, false), + AfterActionNodeRunnable()) + } + + } else { + null + } + } + + private fun buildDatabaseDeleteNodesActionTask(intent: Intent): ActionRunnable? { + return if (intent.hasExtra(GROUPS_ID_KEY) + && intent.hasExtra(ENTRIES_ID_KEY) + && intent.hasExtra(SAVE_DATABASE_KEY) + ) { + val database = Database.getInstance() + DeleteNodesRunnable(this, + database, + getListNodesFromBundle(database, intent.extras!!), + intent.getBooleanExtra(SAVE_DATABASE_KEY, false), + AfterActionNodeRunnable()) + + } else { + null + } + } + + private class ActionRunnableAsyncTask(private val progressTaskUpdater: ProgressTaskUpdater, + private val onPreExecute: () -> Unit, + private val onPostExecute: (result: ActionRunnable.Result) -> Unit) + : AsyncTask<((ProgressTaskUpdater?) -> ActionRunnable), Void, ActionRunnable.Result>() { + + override fun onPreExecute() { + super.onPreExecute() + onPreExecute.invoke() + } + + override fun doInBackground(vararg actionRunnables: ((ProgressTaskUpdater?)-> ActionRunnable)?): ActionRunnable.Result { + var resultTask = ActionRunnable.Result(false) + actionRunnables.forEach { + it?.invoke(progressTaskUpdater)?.apply { + run() + resultTask = result + } + } + return resultTask + } + + override fun onPostExecute(result: ActionRunnable.Result) { + super.onPostExecute(result) + onPostExecute.invoke(result) + } + } + companion object { private val TAG = DatabaseTaskNotificationService::class.java.name - const val DATABASE_TASK_TITLE_KEY = "DatabaseTaskTitle" + const val DATABASE_TASK_TITLE_KEY = "DATABASE_TASK_TITLE_KEY" + const val DATABASE_TASK_SUBTITLE_KEY = "DATABASE_TASK_SUBTITLE_KEY" + const val DATABASE_TASK_MESSAGE_KEY = "DATABASE_TASK_MESSAGE_KEY" + + const val ACTION_DATABASE_CREATE_TASK = "ACTION_DATABASE_CREATE_TASK" + const val ACTION_DATABASE_SAVE_TASK = "ACTION_DATABASE_SAVE_TASK" + const val ACTION_DATABASE_LOAD_TASK = "ACTION_DATABASE_LOAD_TASK" + const val ACTION_DATABASE_ASSIGN_PASSWORD_TASK = "ACTION_DATABASE_ASSIGN_PASSWORD_TASK" + const val ACTION_DATABASE_CREATE_GROUP_TASK = "ACTION_DATABASE_CREATE_GROUP_TASK" + const val ACTION_DATABASE_UPDATE_GROUP_TASK = "ACTION_DATABASE_UPDATE_GROUP_TASK" + const val ACTION_DATABASE_CREATE_ENTRY_TASK = "ACTION_DATABASE_CREATE_ENTRY_TASK" + const val ACTION_DATABASE_UPDATE_ENTRY_TASK = "ACTION_DATABASE_UPDATE_ENTRY_TASK" + const val ACTION_DATABASE_COPY_NODES_TASK = "ACTION_DATABASE_COPY_NODES_TASK" + const val ACTION_DATABASE_MOVE_NODES_TASK = "ACTION_DATABASE_MOVE_NODES_TASK" + const val ACTION_DATABASE_DELETE_NODES_TASK = "ACTION_DATABASE_DELETE_NODES_TASK" + + const val DATABASE_URI_KEY = "DATABASE_URI_KEY" + const val MASTER_PASSWORD_CHECKED_KEY = "MASTER_PASSWORD_CHECKED_KEY" + const val MASTER_PASSWORD_KEY = "MASTER_PASSWORD_KEY" + const val KEY_FILE_CHECKED_KEY = "KEY_FILE_CHECKED_KEY" + const val KEY_FILE_KEY = "KEY_FILE_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" + const val OLD_GROUP_KEY = "OLD_GROUP_KEY" + const val OLD_ENTRY_KEY = "OLD_ENTRY_KEY" + const val GROUPS_ID_KEY = "GROUPS_ID_KEY" + const val ENTRIES_ID_KEY = "ENTRIES_ID_KEY" + const val PARENT_ID_KEY = "PARENT_ID_KEY" + const val SAVE_DATABASE_KEY = "SAVE_DATABASE_KEY" + const val OLD_NODES_KEY = "OLD_NODES_KEY" + const val NEW_NODES_KEY = "NEW_NODES_KEY" + + const val ACTION_TASK_KEY = "ACTION_TASK_KEY" + const val RESULT_KEY = "RESULT_KEY" + + fun getListNodesFromBundle(database: Database, bundle: Bundle): List { + val nodesAction = ArrayList() + bundle.getParcelableArrayList>(GROUPS_ID_KEY)?.forEach { + database.getGroupById(it)?.let { groupRetrieve -> + nodesAction.add(groupRetrieve) + } + } + bundle.getParcelableArrayList>(ENTRIES_ID_KEY)?.forEach { + database.getEntryById(it)?.let { entryRetrieve -> + nodesAction.add(entryRetrieve) + } + } + return nodesAction + } + + fun getBundleFromListNodes(nodes: List): Bundle { + val groupsIdToCopy = ArrayList>() + val entriesIdToCopy = ArrayList>() + nodes.forEach { nodeVersioned -> + when (nodeVersioned.type) { + Type.GROUP -> { + (nodeVersioned as GroupVersioned).nodeId?.let { groupId -> + groupsIdToCopy.add(groupId) + } + } + Type.ENTRY -> { + entriesIdToCopy.add((nodeVersioned as EntryVersioned).nodeId) + } + } + } + return Bundle().apply { + putParcelableArrayList(GROUPS_ID_KEY, groupsIdToCopy) + putParcelableArrayList(ENTRIES_ID_KEY, entriesIdToCopy) + } + } } } \ No newline at end of file diff --git a/app/src/main/java/com/kunzisoft/keepass/settings/SettingsActivity.kt b/app/src/main/java/com/kunzisoft/keepass/settings/SettingsActivity.kt index e28b073b9..ea0067edc 100644 --- a/app/src/main/java/com/kunzisoft/keepass/settings/SettingsActivity.kt +++ b/app/src/main/java/com/kunzisoft/keepass/settings/SettingsActivity.kt @@ -25,17 +25,19 @@ import android.content.DialogInterface import android.content.Intent import android.net.Uri import android.os.Bundle -import androidx.fragment.app.Fragment -import androidx.appcompat.widget.Toolbar import android.view.MenuItem +import android.widget.Toast +import androidx.appcompat.widget.Toolbar +import androidx.fragment.app.Fragment import com.kunzisoft.keepass.R import com.kunzisoft.keepass.activities.dialogs.AssignMasterKeyDialogFragment import com.kunzisoft.keepass.activities.dialogs.PasswordEncodingDialogFragment import com.kunzisoft.keepass.activities.helpers.ReadOnlyHelper import com.kunzisoft.keepass.activities.lock.LockingActivity -import com.kunzisoft.keepass.database.action.AssignPasswordInDatabaseRunnable -import com.kunzisoft.keepass.database.action.ProgressDialogSaveDatabaseThread +import com.kunzisoft.keepass.database.action.ProgressDialogThread import com.kunzisoft.keepass.database.element.Database +import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_ASSIGN_PASSWORD_TASK +import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_SAVE_TASK import com.kunzisoft.keepass.timeout.TimeoutHelper open class SettingsActivity @@ -47,6 +49,8 @@ open class SettingsActivity private var toolbar: Toolbar? = null + var progressDialogThread: ProgressDialogThread? = null + companion object { private const val TAG_NESTED = "TAG_NESTED" @@ -88,6 +92,34 @@ open class SettingsActivity } backupManager = BackupManager(this) + + progressDialogThread = ProgressDialogThread(this) { actionTask, result -> + when (actionTask) { + ACTION_DATABASE_ASSIGN_PASSWORD_TASK -> { + // Nothing here + } + ACTION_DATABASE_SAVE_TASK -> { + if (!result.isSuccess) { + // TODO Log.e(TAG, result.message) + Toast.makeText(this, result.message, Toast.LENGTH_SHORT).show() + } + // TODO actionAfterSaveDatabase?.onFinishRun(result) + } + } + } + } + + override fun onResume() { + super.onResume() + + progressDialogThread?.registerProgressTask() + } + + override fun onPause() { + + progressDialogThread?.unregisterProgressTask() + + super.onPause() } override fun onOptionsItemSelected(item: MenuItem): Boolean { @@ -105,22 +137,23 @@ open class SettingsActivity override fun onAssignKeyDialogPositiveClick(masterPasswordChecked: Boolean, masterPassword: String?, keyFileChecked: Boolean, keyFile: Uri?) { Database.getInstance().let { database -> - val progressDialogThread = ProgressDialogSaveDatabaseThread(this) { - AssignPasswordInDatabaseRunnable(this, - database, + // Show the progress dialog now or after dialog confirmation + if (database.validatePasswordEncoding(masterPassword, keyFileChecked)) { + progressDialogThread?.startDatabaseAssignPassword( masterPasswordChecked, masterPassword, keyFileChecked, - keyFile, - true) - } - // Show the progress dialog now or after dialog confirmation - if (database.validatePasswordEncoding(masterPassword, keyFileChecked)) { - progressDialogThread.start() + keyFile + ) } else { PasswordEncodingDialogFragment().apply { positiveButtonClickListener = DialogInterface.OnClickListener { _, _ -> - progressDialogThread.start() + progressDialogThread?.startDatabaseAssignPassword( + masterPasswordChecked, + masterPassword, + keyFileChecked, + keyFile + ) } show(supportFragmentManager, "passwordEncodingTag") } diff --git a/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/DatabaseSavePreferenceDialogFragmentCompat.kt b/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/DatabaseSavePreferenceDialogFragmentCompat.kt index 913b4d018..c5646200a 100644 --- a/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/DatabaseSavePreferenceDialogFragmentCompat.kt +++ b/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/DatabaseSavePreferenceDialogFragmentCompat.kt @@ -19,21 +19,25 @@ */ package com.kunzisoft.keepass.settings.preferencedialogfragment +import android.content.BroadcastReceiver +import android.content.Context +import android.content.Intent +import android.content.IntentFilter import android.content.res.Resources import android.os.Bundle -import android.util.Log import android.view.View -import android.widget.Toast -import com.kunzisoft.keepass.database.action.ProgressDialogSaveDatabaseThread -import com.kunzisoft.keepass.database.action.SaveDatabaseActionRunnable import com.kunzisoft.keepass.database.element.Database +import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.RESULT_KEY +import com.kunzisoft.keepass.settings.SettingsActivity import com.kunzisoft.keepass.tasks.ActionRunnable +import com.kunzisoft.keepass.utils.DATABASE_STOP_TASK_ACTION abstract class DatabaseSavePreferenceDialogFragmentCompat : InputPreferenceDialogFragmentCompat() { protected var database: Database? = null var actionInUIThreadAfterSaveDatabase: ActionRunnable? = null + private var databaseTaskBroadcastReceiver: BroadcastReceiver? = null protected lateinit var settingsResources: Resources @@ -51,28 +55,31 @@ abstract class DatabaseSavePreferenceDialogFragmentCompat : InputPreferenceDialo override fun onDialogClosed(positiveResult: Boolean) { if (positiveResult) { - activity?.let { notNullActivity -> - database?.let { notNullDatabase -> - ProgressDialogSaveDatabaseThread(notNullActivity) { - SaveDatabaseActionRunnable( - notNullActivity, - notNullDatabase, - true) - }.apply { - actionFinishInUIThread = object:ActionRunnable() { - override fun onFinishRun(result: Result) { - if (!result.isSuccess) { - Log.e(TAG, result.message) - Toast.makeText(notNullActivity, result.message, Toast.LENGTH_SHORT).show() - } - actionInUIThreadAfterSaveDatabase?.onFinishRun(result) - } - } - start() + registerProgressTask() + (activity as SettingsActivity?)?.progressDialogThread?.startDatabaseSave() + } + } + + fun registerProgressTask() { + // TODO remove receiver + // Register a database task receiver to stop loading dialog when service finish the task + databaseTaskBroadcastReceiver = object : BroadcastReceiver() { + override fun onReceive(context: Context?, intent: Intent?) { + when (intent?.action) { + DATABASE_STOP_TASK_ACTION -> { + var result = ActionRunnable.Result(false) + if (intent.hasExtra(RESULT_KEY)) + result = ActionRunnable.Result.fromBundle(intent.getBundleExtra(RESULT_KEY)) + actionInUIThreadAfterSaveDatabase?.onFinishRun(result) } } } } + activity?.registerReceiver(databaseTaskBroadcastReceiver, + IntentFilter().apply { + addAction(DATABASE_STOP_TASK_ACTION) + } + ) } companion object { diff --git a/app/src/main/java/com/kunzisoft/keepass/tasks/ActionRunnable.kt b/app/src/main/java/com/kunzisoft/keepass/tasks/ActionRunnable.kt index ad181fa51..673a30bfc 100644 --- a/app/src/main/java/com/kunzisoft/keepass/tasks/ActionRunnable.kt +++ b/app/src/main/java/com/kunzisoft/keepass/tasks/ActionRunnable.kt @@ -106,5 +106,29 @@ 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) + 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)) + } + } + } } diff --git a/app/src/main/java/com/kunzisoft/keepass/tasks/ProgressTaskDialogFragment.kt b/app/src/main/java/com/kunzisoft/keepass/tasks/ProgressTaskDialogFragment.kt index 32eee39f5..60235a18d 100644 --- a/app/src/main/java/com/kunzisoft/keepass/tasks/ProgressTaskDialogFragment.kt +++ b/app/src/main/java/com/kunzisoft/keepass/tasks/ProgressTaskDialogFragment.kt @@ -21,7 +21,6 @@ package com.kunzisoft.keepass.tasks import android.annotation.SuppressLint import android.app.Dialog -import android.content.DialogInterface import android.os.Bundle import androidx.annotation.StringRes import androidx.fragment.app.DialogFragment @@ -31,8 +30,6 @@ import android.view.View import android.widget.ProgressBar import android.widget.TextView import com.kunzisoft.keepass.R -import com.kunzisoft.keepass.view.lockScreenOrientation -import com.kunzisoft.keepass.view.unlockScreenOrientation open class ProgressTaskDialogFragment : DialogFragment(), ProgressTaskUpdater { @@ -77,11 +74,6 @@ open class ProgressTaskDialogFragment : DialogFragment(), ProgressTaskUpdater { return super.onCreateDialog(savedInstanceState) } - override fun onDismiss(dialog: DialogInterface) { - activity?.unlockScreenOrientation() - super.onDismiss(dialog) - } - fun setTitle(@StringRes titleId: Int) { this.title = titleId } @@ -116,7 +108,7 @@ open class ProgressTaskDialogFragment : DialogFragment(), ProgressTaskUpdater { private const val PROGRESS_TASK_DIALOG_TAG = "progressDialogFragment" - private const val UNDEFINED = -1 + const val UNDEFINED = -1 fun build(@StringRes titleId: Int, @StringRes messageId: Int? = null, @@ -135,7 +127,6 @@ open class ProgressTaskDialogFragment : DialogFragment(), ProgressTaskUpdater { fun start(activity: FragmentActivity, dialog: ProgressTaskDialogFragment) { - activity.lockScreenOrientation() dialog.show(activity.supportFragmentManager, PROGRESS_TASK_DIALOG_TAG) } @@ -144,7 +135,6 @@ open class ProgressTaskDialogFragment : DialogFragment(), ProgressTaskUpdater { if (fragmentTask != null) { val loadingDatabaseDialog = fragmentTask as ProgressTaskDialogFragment loadingDatabaseDialog.dismissAllowingStateLoss() - activity.unlockScreenOrientation() } } } diff --git a/app/src/main/java/com/kunzisoft/keepass/utils/BroadcastAction.kt b/app/src/main/java/com/kunzisoft/keepass/utils/BroadcastAction.kt index f75dd8290..8d6f8e793 100644 --- a/app/src/main/java/com/kunzisoft/keepass/utils/BroadcastAction.kt +++ b/app/src/main/java/com/kunzisoft/keepass/utils/BroadcastAction.kt @@ -1,5 +1,11 @@ package com.kunzisoft.keepass.utils +const val DATABASE_START_TASK_ACTION = "com.kunzisoft.keepass.DATABASE_START_TASK_ACTION" +const val DATABASE_STOP_TASK_ACTION = "com.kunzisoft.keepass.DATABASE_STOP_TASK_ACTION" + +const val DATABASE_CHECK_TASK_ACTION = "com.kunzisoft.keepass.DATABASE_CHECK_TASK_ACTION" + const val LOCK_ACTION = "com.kunzisoft.keepass.LOCK" + const val REMOVE_ENTRY_MAGIKEYBOARD_ACTION = "com.kunzisoft.keepass.REMOVE_ENTRY_MAGIKEYBOARD" diff --git a/app/src/main/java/com/kunzisoft/keepass/view/ViewUtil.kt b/app/src/main/java/com/kunzisoft/keepass/view/ViewUtil.kt index 736696268..d9f48dab2 100644 --- a/app/src/main/java/com/kunzisoft/keepass/view/ViewUtil.kt +++ b/app/src/main/java/com/kunzisoft/keepass/view/ViewUtil.kt @@ -49,19 +49,6 @@ fun Snackbar.asError(): Snackbar { return this } -fun Activity.lockScreenOrientation() { - val currentOrientation = resources.configuration.orientation - requestedOrientation = if (currentOrientation == Configuration.ORIENTATION_PORTRAIT) { - ActivityInfo.SCREEN_ORIENTATION_PORTRAIT - } else { - ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE - } -} - -fun Activity.unlockScreenOrientation() { - requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED -} - fun Toolbar.collapse(animate: Boolean = true) { val recordBarHeight = layoutParams.height val slideAnimator = ValueAnimator.ofInt(height, 0) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 493f2b350..9314c0af3 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -138,6 +138,7 @@ Show the number of entries in a group Size of list items Text size in the element list + Creating database… Loading database… Lower-case Hide passwords From e0e7e431cf33b2fadd7529314875a5d9c9654293 Mon Sep 17 00:00:00 2001 From: J-Jamet Date: Tue, 15 Oct 2019 17:02:59 +0200 Subject: [PATCH 02/16] Best update and nodeId type implementation --- .../kunzisoft/keepass/adapters/NodeAdapter.kt | 1 + .../database/action/node/UpdateEntryRunnable.kt | 11 +++-------- .../database/action/node/UpdateGroupRunnable.kt | 6 ++---- .../keepass/database/cursor/EntryCursor.kt | 16 +++++++--------- .../keepass/database/cursor/EntryCursorUUID.kt | 15 +++++++++++++++ .../keepass/database/cursor/EntryCursorV3.kt | 2 +- .../keepass/database/cursor/EntryCursorV4.kt | 2 +- .../keepass/database/element/PwDatabase.kt | 15 +++++++++------ .../keepass/database/element/PwDatabaseV3.kt | 4 +++- .../keepass/database/element/PwDatabaseV4.kt | 2 +- .../keepass/database/element/PwEntry.kt | 8 +++++--- .../keepass/database/element/PwEntryV3.kt | 2 +- .../keepass/database/element/PwEntryV4.kt | 2 +- .../keepass/database/element/PwGroup.kt | 11 ++++++----- .../keepass/database/element/PwGroupV3.kt | 3 ++- .../keepass/database/element/PwGroupV4.kt | 2 +- .../keepass/database/file/load/Importer.kt | 2 +- 17 files changed, 60 insertions(+), 44 deletions(-) create mode 100644 app/src/main/java/com/kunzisoft/keepass/database/cursor/EntryCursorUUID.kt diff --git a/app/src/main/java/com/kunzisoft/keepass/adapters/NodeAdapter.kt b/app/src/main/java/com/kunzisoft/keepass/adapters/NodeAdapter.kt index 8e0996ae5..f22e4cb88 100644 --- a/app/src/main/java/com/kunzisoft/keepass/adapters/NodeAdapter.kt +++ b/app/src/main/java/com/kunzisoft/keepass/adapters/NodeAdapter.kt @@ -142,6 +142,7 @@ class NodeAdapter Log.e(TAG, "Can't add node elements to the list", e) Toast.makeText(context, "Can't add node elements to the list : " + e.message, Toast.LENGTH_LONG).show() } + notifyDataSetChanged() } fun contains(node: NodeVersioned): Boolean { diff --git a/app/src/main/java/com/kunzisoft/keepass/database/action/node/UpdateEntryRunnable.kt b/app/src/main/java/com/kunzisoft/keepass/database/action/node/UpdateEntryRunnable.kt index 042729e97..0f663149f 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/action/node/UpdateEntryRunnable.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/action/node/UpdateEntryRunnable.kt @@ -33,22 +33,17 @@ class UpdateEntryRunnable constructor( finishRunnable: AfterActionNodeFinishRunnable?) : ActionNodeDatabaseRunnable(context, database, finishRunnable, save) { - // Keep backup of original values in case save fails - private var mBackupEntryHistory: EntryVersioned = EntryVersioned(mOldEntry) - override fun nodeAction() { // Update entry with new values - mOldEntry.updateWith(mNewEntry) mNewEntry.touch(modified = true, touchParents = true) // Create an entry history (an entry history don't have history) - mOldEntry.addEntryToHistory(EntryVersioned(mBackupEntryHistory, copyHistory = false)) + mNewEntry.addEntryToHistory(EntryVersioned(mOldEntry, copyHistory = false)) - database.removeOldestHistory(mOldEntry) + database.removeOldestHistory(mNewEntry) // Only change data un index - // TODO - database.updateEntry(mOldEntry) + database.updateEntry(mNewEntry) } override fun nodeFinish(result: Result): ActionNodeValues { diff --git a/app/src/main/java/com/kunzisoft/keepass/database/action/node/UpdateGroupRunnable.kt b/app/src/main/java/com/kunzisoft/keepass/database/action/node/UpdateGroupRunnable.kt index 1fec741e1..ccc68963c 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/action/node/UpdateGroupRunnable.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/action/node/UpdateGroupRunnable.kt @@ -38,12 +38,10 @@ class UpdateGroupRunnable constructor( override fun nodeAction() { // Update group with new values - mOldGroup.updateWith(mNewGroup) - mOldGroup.touch(modified = true, touchParents = true) + mNewGroup.touch(modified = true, touchParents = true) // Only change data un index - // TODO - database.updateGroup(mOldGroup) + database.updateGroup(mNewGroup) } override fun nodeFinish(result: Result): ActionNodeValues { diff --git a/app/src/main/java/com/kunzisoft/keepass/database/cursor/EntryCursor.kt b/app/src/main/java/com/kunzisoft/keepass/database/cursor/EntryCursor.kt index 67f89fd51..e9f59624b 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/cursor/EntryCursor.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/cursor/EntryCursor.kt @@ -2,12 +2,11 @@ package com.kunzisoft.keepass.database.cursor import android.database.MatrixCursor import android.provider.BaseColumns +import com.kunzisoft.keepass.database.element.PwEntry +import com.kunzisoft.keepass.database.element.PwIconFactory +import com.kunzisoft.keepass.database.element.PwNodeId -import com.kunzisoft.keepass.database.element.* - -import java.util.UUID - -abstract class EntryCursor> : MatrixCursor(arrayOf( +abstract class EntryCursor> : MatrixCursor(arrayOf( _ID, COLUMN_INDEX_UUID_MOST_SIGNIFICANT_BITS, COLUMN_INDEX_UUID_LEAST_SIGNIFICANT_BITS, @@ -25,10 +24,10 @@ abstract class EntryCursor> : MatrixCursor(arrayOf( abstract fun addEntry(entry: PwEntryV) + abstract fun getPwNodeId(): PwNodeId + open fun populateEntry(pwEntry: PwEntryV, iconFactory: PwIconFactory) { - pwEntry.nodeId = PwNodeIdUUID( - UUID(getLong(getColumnIndex(COLUMN_INDEX_UUID_MOST_SIGNIFICANT_BITS)), - getLong(getColumnIndex(COLUMN_INDEX_UUID_LEAST_SIGNIFICANT_BITS)))) + pwEntry.nodeId = getPwNodeId() pwEntry.title = getString(getColumnIndex(COLUMN_INDEX_TITLE)) val iconStandard = iconFactory.getIcon(getInt(getColumnIndex(COLUMN_INDEX_ICON_STANDARD))) @@ -53,5 +52,4 @@ abstract class EntryCursor> : MatrixCursor(arrayOf( const val COLUMN_INDEX_URL = "URL" const val COLUMN_INDEX_NOTES = "notes" } - } diff --git a/app/src/main/java/com/kunzisoft/keepass/database/cursor/EntryCursorUUID.kt b/app/src/main/java/com/kunzisoft/keepass/database/cursor/EntryCursorUUID.kt new file mode 100644 index 000000000..95be574a9 --- /dev/null +++ b/app/src/main/java/com/kunzisoft/keepass/database/cursor/EntryCursorUUID.kt @@ -0,0 +1,15 @@ +package com.kunzisoft.keepass.database.cursor + +import com.kunzisoft.keepass.database.element.PwEntry +import com.kunzisoft.keepass.database.element.PwNodeId +import com.kunzisoft.keepass.database.element.PwNodeIdUUID +import java.util.* + +abstract class EntryCursorUUID>: EntryCursor() { + + override fun getPwNodeId(): PwNodeId { + return PwNodeIdUUID( + UUID(getLong(getColumnIndex(COLUMN_INDEX_UUID_MOST_SIGNIFICANT_BITS)), + getLong(getColumnIndex(COLUMN_INDEX_UUID_LEAST_SIGNIFICANT_BITS)))) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/kunzisoft/keepass/database/cursor/EntryCursorV3.kt b/app/src/main/java/com/kunzisoft/keepass/database/cursor/EntryCursorV3.kt index 9ef52fbe5..f50b65388 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/cursor/EntryCursorV3.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/cursor/EntryCursorV3.kt @@ -3,7 +3,7 @@ package com.kunzisoft.keepass.database.cursor import com.kunzisoft.keepass.database.element.PwDatabase import com.kunzisoft.keepass.database.element.PwEntryV3 -class EntryCursorV3 : EntryCursor() { +class EntryCursorV3 : EntryCursorUUID() { override fun addEntry(entry: PwEntryV3) { addRow(arrayOf( diff --git a/app/src/main/java/com/kunzisoft/keepass/database/cursor/EntryCursorV4.kt b/app/src/main/java/com/kunzisoft/keepass/database/cursor/EntryCursorV4.kt index d4b1c02dd..f4fcbb3a1 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/cursor/EntryCursorV4.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/cursor/EntryCursorV4.kt @@ -5,7 +5,7 @@ import com.kunzisoft.keepass.database.element.PwIconFactory import java.util.UUID -class EntryCursorV4 : EntryCursor() { +class EntryCursorV4 : EntryCursorUUID() { private val extraFieldCursor: ExtraFieldCursor = ExtraFieldCursor() diff --git a/app/src/main/java/com/kunzisoft/keepass/database/element/PwDatabase.kt b/app/src/main/java/com/kunzisoft/keepass/database/element/PwDatabase.kt index 78e64fd0c..6a3e7eab9 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/element/PwDatabase.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/element/PwDatabase.kt @@ -30,8 +30,9 @@ import java.util.* abstract class PwDatabase< GroupId, - Group : PwGroup, - Entry : PwEntry + EntryId, + Group : PwGroup, + Entry : PwEntry > { // Algorithm used to encrypt the database @@ -51,7 +52,7 @@ abstract class PwDatabase< var changeDuplicateId = false private var groupIndexes = LinkedHashMap, Group>() - private var entryIndexes = LinkedHashMap, Entry>() + private var entryIndexes = LinkedHashMap, Entry>() abstract val version: String @@ -193,7 +194,7 @@ abstract class PwDatabase< abstract fun newGroupId(): PwNodeId - abstract fun newEntryId(): PwNodeId + abstract fun newEntryId(): PwNodeId abstract fun createGroup(): Group @@ -274,7 +275,7 @@ abstract class PwDatabase< } } - fun isEntryIdUsed(id: PwNodeId): Boolean { + fun isEntryIdUsed(id: PwNodeId): Boolean { return entryIndexes.containsKey(id) } @@ -282,7 +283,7 @@ abstract class PwDatabase< return entryIndexes.values } - fun getEntryById(id: PwNodeId): Entry? { + fun getEntryById(id: PwNodeId): Entry? { return this.entryIndexes[id] } @@ -340,6 +341,7 @@ abstract class PwDatabase< } fun updateGroup(group: Group) { + getGroupById(group.nodeId)?.parent?.updateChildGroup(group) updateGroupIndex(group) } @@ -357,6 +359,7 @@ abstract class PwDatabase< } fun updateEntry(entry: Entry) { + getEntryById(entry.nodeId)?.parent?.updateChildEntry(entry) updateEntryIndex(entry) } diff --git a/app/src/main/java/com/kunzisoft/keepass/database/element/PwDatabaseV3.kt b/app/src/main/java/com/kunzisoft/keepass/database/element/PwDatabaseV3.kt index 58e8b0027..2af4ff0f3 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/element/PwDatabaseV3.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/element/PwDatabaseV3.kt @@ -28,8 +28,10 @@ import java.io.InputStream import java.security.DigestOutputStream import java.security.MessageDigest import java.security.NoSuchAlgorithmException +import java.util.* +import kotlin.collections.ArrayList -class PwDatabaseV3 : PwDatabase() { +class PwDatabaseV3 : PwDatabase() { private var numKeyEncRounds: Int = 0 diff --git a/app/src/main/java/com/kunzisoft/keepass/database/element/PwDatabaseV4.kt b/app/src/main/java/com/kunzisoft/keepass/database/element/PwDatabaseV4.kt index ce0d56591..31b11f8e1 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/element/PwDatabaseV4.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/element/PwDatabaseV4.kt @@ -41,7 +41,7 @@ import javax.xml.parsers.DocumentBuilderFactory import javax.xml.parsers.ParserConfigurationException -class PwDatabaseV4 : PwDatabase { +class PwDatabaseV4 : PwDatabase { var hmacKey: ByteArray? = null private set diff --git a/app/src/main/java/com/kunzisoft/keepass/database/element/PwEntry.kt b/app/src/main/java/com/kunzisoft/keepass/database/element/PwEntry.kt index 1b27ce15d..e5a1067ae 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/element/PwEntry.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/element/PwEntry.kt @@ -5,10 +5,12 @@ import java.util.* abstract class PwEntry < - ParentGroup: PwGroupInterface, - Entry: PwEntryInterface + GroupId, + EntryId, + ParentGroup: PwGroup, + Entry: PwEntry > - : PwNode, PwEntryInterface { + : PwNode, PwEntryInterface { constructor() : super() diff --git a/app/src/main/java/com/kunzisoft/keepass/database/element/PwEntryV3.kt b/app/src/main/java/com/kunzisoft/keepass/database/element/PwEntryV3.kt index 589c62778..9c69dfd6c 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/element/PwEntryV3.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/element/PwEntryV3.kt @@ -48,7 +48,7 @@ import java.util.UUID * @author Dominik Reichl @t-online.de> * @author Jeremy Jamet @kunzisoft.com> */ -class PwEntryV3 : PwEntry, PwNodeV3Interface { +class PwEntryV3 : PwEntry, PwNodeV3Interface { /** A string describing what is in pBinaryData */ var binaryDesc = "" diff --git a/app/src/main/java/com/kunzisoft/keepass/database/element/PwEntryV4.kt b/app/src/main/java/com/kunzisoft/keepass/database/element/PwEntryV4.kt index 42aef5204..b07d9b867 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/element/PwEntryV4.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/element/PwEntryV4.kt @@ -26,7 +26,7 @@ import com.kunzisoft.keepass.database.element.security.ProtectedString import com.kunzisoft.keepass.utils.MemoryUtil import java.util.* -class PwEntryV4 : PwEntry, PwNodeV4Interface { +class PwEntryV4 : PwEntry, PwNodeV4Interface { // To decode each field not parcelable @Transient diff --git a/app/src/main/java/com/kunzisoft/keepass/database/element/PwGroup.kt b/app/src/main/java/com/kunzisoft/keepass/database/element/PwGroup.kt index 07914a44a..4eed467c1 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/element/PwGroup.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/element/PwGroup.kt @@ -4,11 +4,12 @@ import android.os.Parcel abstract class PwGroup < - Id, - Group: PwGroupInterface, - Entry: PwEntryInterface + GroupId, + EntryId, + Group: PwGroup, + Entry: PwEntry > - : PwNode, PwGroupInterface { + : PwNode, PwGroupInterface { private var titleGroup = "" @Transient @@ -27,7 +28,7 @@ abstract class PwGroup dest.writeString(titleGroup) } - protected fun updateWith(source: PwGroup) { + protected fun updateWith(source: PwGroup) { super.updateWith(source) titleGroup = source.titleGroup childGroups.clear() diff --git a/app/src/main/java/com/kunzisoft/keepass/database/element/PwGroupV3.kt b/app/src/main/java/com/kunzisoft/keepass/database/element/PwGroupV3.kt index 1c66ad913..ed2aaec3d 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/element/PwGroupV3.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/element/PwGroupV3.kt @@ -22,8 +22,9 @@ package com.kunzisoft.keepass.database.element import android.os.Parcel import android.os.Parcelable +import java.util.* -class PwGroupV3 : PwGroup, PwNodeV3Interface { +class PwGroupV3 : PwGroup, PwNodeV3Interface { var level = 0 // short /** Used by KeePass internally, don't use */ diff --git a/app/src/main/java/com/kunzisoft/keepass/database/element/PwGroupV4.kt b/app/src/main/java/com/kunzisoft/keepass/database/element/PwGroupV4.kt index c8980f9f2..e7eee8abc 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/element/PwGroupV4.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/element/PwGroupV4.kt @@ -25,7 +25,7 @@ import android.os.Parcelable import java.util.HashMap import java.util.UUID -class PwGroupV4 : PwGroup, PwNodeV4Interface { +class PwGroupV4 : PwGroup, PwNodeV4Interface { // TODO Encapsulate override var icon: PwIcon diff --git a/app/src/main/java/com/kunzisoft/keepass/database/file/load/Importer.kt b/app/src/main/java/com/kunzisoft/keepass/database/file/load/Importer.kt index d10d234cb..8743eb855 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/file/load/Importer.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/file/load/Importer.kt @@ -24,7 +24,7 @@ import com.kunzisoft.keepass.database.exception.LoadDatabaseException import com.kunzisoft.keepass.tasks.ProgressTaskUpdater import java.io.InputStream -abstract class Importer> { +abstract class Importer> { /** * Load a versioned database file, return contents in a new PwDatabase. From 721d61dda78d4eb9d9bda1b6291bc145ef491942 Mon Sep 17 00:00:00 2001 From: J-Jamet Date: Tue, 15 Oct 2019 18:05:33 +0200 Subject: [PATCH 03/16] Fix update nodes --- .../database/action/ProgressDialogThread.kt | 4 +- .../action/node/UpdateEntryRunnable.kt | 15 +++++--- .../action/node/UpdateGroupRunnable.kt | 10 +++-- .../keepass/database/element/PwGroup.kt | 36 ++++++------------ .../DatabaseTaskNotificationService.kt | 38 +++++++++++-------- 5 files changed, 52 insertions(+), 51 deletions(-) diff --git a/app/src/main/java/com/kunzisoft/keepass/database/action/ProgressDialogThread.kt b/app/src/main/java/com/kunzisoft/keepass/database/action/ProgressDialogThread.kt index ce559bc0d..e3ade1b6b 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/action/ProgressDialogThread.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/action/ProgressDialogThread.kt @@ -183,7 +183,7 @@ class ProgressDialogThread(private val activity: FragmentActivity, groupToUpdate: GroupVersioned, save: Boolean) { start(Bundle().apply { - putParcelable(DatabaseTaskNotificationService.OLD_GROUP_KEY, oldGroup) + putParcelable(DatabaseTaskNotificationService.GROUP_ID_KEY, oldGroup.nodeId) putParcelable(DatabaseTaskNotificationService.GROUP_KEY, groupToUpdate) putBoolean(DatabaseTaskNotificationService.SAVE_DATABASE_KEY, save) } @@ -205,7 +205,7 @@ class ProgressDialogThread(private val activity: FragmentActivity, entryToUpdate: EntryVersioned, save: Boolean) { start(Bundle().apply { - putParcelable(DatabaseTaskNotificationService.OLD_ENTRY_KEY, oldEntry) + putParcelable(DatabaseTaskNotificationService.ENTRY_ID_KEY, oldEntry.nodeId) putParcelable(DatabaseTaskNotificationService.ENTRY_KEY, entryToUpdate) putBoolean(DatabaseTaskNotificationService.SAVE_DATABASE_KEY, save) } diff --git a/app/src/main/java/com/kunzisoft/keepass/database/action/node/UpdateEntryRunnable.kt b/app/src/main/java/com/kunzisoft/keepass/database/action/node/UpdateEntryRunnable.kt index 0f663149f..a67dbc9f8 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/action/node/UpdateEntryRunnable.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/action/node/UpdateEntryRunnable.kt @@ -33,29 +33,34 @@ class UpdateEntryRunnable constructor( finishRunnable: AfterActionNodeFinishRunnable?) : ActionNodeDatabaseRunnable(context, database, finishRunnable, save) { + // Keep backup of original values in case save fails + private var mBackupEntryHistory: EntryVersioned = EntryVersioned(mOldEntry) + override fun nodeAction() { // Update entry with new values + mOldEntry.updateWith(mNewEntry) mNewEntry.touch(modified = true, touchParents = true) // Create an entry history (an entry history don't have history) - mNewEntry.addEntryToHistory(EntryVersioned(mOldEntry, copyHistory = false)) + mOldEntry.addEntryToHistory(EntryVersioned(mBackupEntryHistory, copyHistory = false)) - database.removeOldestHistory(mNewEntry) + database.removeOldestHistory(mOldEntry) // Only change data un index - database.updateEntry(mNewEntry) + database.updateEntry(mOldEntry) } override fun nodeFinish(result: Result): ActionNodeValues { if (!result.isSuccess) { + mOldEntry.updateWith(mBackupEntryHistory) // If we fail to save, back out changes to global structure database.updateEntry(mOldEntry) } val oldNodesReturn = ArrayList() - oldNodesReturn.add(mOldEntry) + oldNodesReturn.add(mBackupEntryHistory) val newNodesReturn = ArrayList() - newNodesReturn.add(mNewEntry) + newNodesReturn.add(mOldEntry) return ActionNodeValues(result, oldNodesReturn, newNodesReturn) } } diff --git a/app/src/main/java/com/kunzisoft/keepass/database/action/node/UpdateGroupRunnable.kt b/app/src/main/java/com/kunzisoft/keepass/database/action/node/UpdateGroupRunnable.kt index ccc68963c..60cab4804 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/action/node/UpdateGroupRunnable.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/action/node/UpdateGroupRunnable.kt @@ -38,22 +38,24 @@ class UpdateGroupRunnable constructor( override fun nodeAction() { // Update group with new values - mNewGroup.touch(modified = true, touchParents = true) + mOldGroup.updateWith(mNewGroup) + mOldGroup.touch(modified = true, touchParents = true) // Only change data un index - database.updateGroup(mNewGroup) + database.updateGroup(mOldGroup) } override fun nodeFinish(result: Result): ActionNodeValues { if (!result.isSuccess) { // If we fail to save, back out changes to global structure mOldGroup.updateWith(mBackupGroup) + database.updateGroup(mOldGroup) } val oldNodesReturn = ArrayList() - oldNodesReturn.add(mOldGroup) + oldNodesReturn.add(mBackupGroup) val newNodesReturn = ArrayList() - newNodesReturn.add(mNewGroup) + newNodesReturn.add(mOldGroup) return ActionNodeValues(result, oldNodesReturn, newNodesReturn) } } diff --git a/app/src/main/java/com/kunzisoft/keepass/database/element/PwGroup.kt b/app/src/main/java/com/kunzisoft/keepass/database/element/PwGroup.kt index 4eed467c1..616ec211a 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/element/PwGroup.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/element/PwGroup.kt @@ -13,9 +13,9 @@ abstract class PwGroup private var titleGroup = "" @Transient - private val childGroups = ArrayList() + private val childGroups = LinkedHashMap, Group>() @Transient - private val childEntries = ArrayList() + private val childEntries = LinkedHashMap, Entry>() constructor() : super() @@ -32,9 +32,9 @@ abstract class PwGroup super.updateWith(source) titleGroup = source.titleGroup childGroups.clear() - childGroups.addAll(source.childGroups) + childGroups.putAll(source.childGroups) childEntries.clear() - childEntries.addAll(source.childEntries) + childEntries.putAll(source.childEntries) } override var title: String @@ -42,47 +42,35 @@ abstract class PwGroup set(value) { titleGroup = value } override fun getChildGroups(): MutableList { - return childGroups + return childGroups.values.toMutableList() } override fun getChildEntries(): MutableList { - return childEntries + return childEntries.values.toMutableList() } override fun addChildGroup(group: Group) { - if (childGroups.contains(group)) - removeChildGroup(group) - this.childGroups.add(group) + this.childGroups[group.nodeId] = group } override fun addChildEntry(entry: Entry) { - if (childEntries.contains(entry)) - removeChildEntry(entry) - this.childEntries.add(entry) + this.childEntries[entry.nodeId] = entry } override fun updateChildEntry(entry: Entry) { - if (childEntries.contains(entry)) { - val index = this.childEntries.indexOf(entry) - childEntries.remove(entry) - childEntries.add(index, entry) - } + this.childEntries[entry.nodeId] = entry } override fun updateChildGroup(group: Group) { - if (childGroups.contains(group)) { - val index = this.childGroups.indexOf(group) - childGroups.remove(group) - childGroups.add(index, group) - } + this.childGroups[group.nodeId] = group } override fun removeChildGroup(group: Group) { - this.childGroups.remove(group) + this.childGroups.remove(group.nodeId) } override fun removeChildEntry(entry: Entry) { - this.childEntries.remove(entry) + this.childEntries.remove(entry.nodeId) } override fun toString(): String { diff --git a/app/src/main/java/com/kunzisoft/keepass/notifications/DatabaseTaskNotificationService.kt b/app/src/main/java/com/kunzisoft/keepass/notifications/DatabaseTaskNotificationService.kt index 3d5e34d6c..a8f371d87 100644 --- a/app/src/main/java/com/kunzisoft/keepass/notifications/DatabaseTaskNotificationService.kt +++ b/app/src/main/java/com/kunzisoft/keepass/notifications/DatabaseTaskNotificationService.kt @@ -254,16 +254,19 @@ class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdat } private fun buildDatabaseUpdateGroupActionTask(intent: Intent): ActionRunnable? { - return if (intent.hasExtra(OLD_GROUP_KEY) + return if (intent.hasExtra(GROUP_ID_KEY) && intent.hasExtra(GROUP_KEY) && intent.hasExtra(SAVE_DATABASE_KEY) ) { - UpdateGroupRunnable(this, - Database.getInstance(), - intent.getParcelableExtra(OLD_GROUP_KEY), - intent.getParcelableExtra(GROUP_KEY), - intent.getBooleanExtra(SAVE_DATABASE_KEY, false), - AfterActionNodeRunnable()) + val database = Database.getInstance() + database.getGroupById(intent.getParcelableExtra(GROUP_ID_KEY))?.let { oldGroup -> + UpdateGroupRunnable(this, + database, + oldGroup, + intent.getParcelableExtra(GROUP_KEY), + intent.getBooleanExtra(SAVE_DATABASE_KEY, false), + AfterActionNodeRunnable()) + } } else { null } @@ -289,16 +292,19 @@ class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdat } private fun buildDatabaseUpdateEntryActionTask(intent: Intent): ActionRunnable? { - return if (intent.hasExtra(OLD_ENTRY_KEY) + return if (intent.hasExtra(ENTRY_ID_KEY) && intent.hasExtra(ENTRY_KEY) && intent.hasExtra(SAVE_DATABASE_KEY) ) { - UpdateEntryRunnable(this, - Database.getInstance(), - intent.getParcelableExtra(OLD_ENTRY_KEY), - intent.getParcelableExtra(ENTRY_KEY), - intent.getBooleanExtra(SAVE_DATABASE_KEY, false), - AfterActionNodeRunnable()) + val database = Database.getInstance() + database.getEntryById(intent.getParcelableExtra(ENTRY_ID_KEY))?.let { oldEntry -> + UpdateEntryRunnable(this, + database, + oldEntry, + intent.getParcelableExtra(ENTRY_KEY), + intent.getBooleanExtra(SAVE_DATABASE_KEY, false), + AfterActionNodeRunnable()) + } } else { null } @@ -430,8 +436,8 @@ class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdat const val FIX_DUPLICATE_UUID_KEY = "FIX_DUPLICATE_UUID_KEY" const val GROUP_KEY = "GROUP_KEY" const val ENTRY_KEY = "ENTRY_KEY" - const val OLD_GROUP_KEY = "OLD_GROUP_KEY" - const val OLD_ENTRY_KEY = "OLD_ENTRY_KEY" + const val GROUP_ID_KEY = "GROUP_ID_KEY" + const val ENTRY_ID_KEY = "ENTRY_ID_KEY" const val GROUPS_ID_KEY = "GROUPS_ID_KEY" const val ENTRIES_ID_KEY = "ENTRIES_ID_KEY" const val PARENT_ID_KEY = "PARENT_ID_KEY" From e087e191204ad674fc3f1ffb5465f750693e3c04 Mon Sep 17 00:00:00 2001 From: J-Jamet Date: Wed, 16 Oct 2019 10:46:56 +0200 Subject: [PATCH 04/16] Fix update entry --- .../action/node/UpdateEntryRunnable.kt | 3 +++ .../database/element/EntryVersioned.kt | 2 +- .../database/element/GroupVersioned.kt | 20 +------------------ .../keepass/database/element/NodeVersioned.kt | 4 +++- .../keepass/database/element/PwDatabase.kt | 2 -- .../keepass/database/element/PwGroup.kt | 8 -------- .../database/element/PwGroupInterface.kt | 4 ---- .../keepass/database/element/PwNodeId.kt | 13 ++++++++++++ .../DatabaseTaskNotificationService.kt | 6 ++++-- 9 files changed, 25 insertions(+), 37 deletions(-) diff --git a/app/src/main/java/com/kunzisoft/keepass/database/action/node/UpdateEntryRunnable.kt b/app/src/main/java/com/kunzisoft/keepass/database/action/node/UpdateEntryRunnable.kt index a67dbc9f8..a6529a969 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/action/node/UpdateEntryRunnable.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/action/node/UpdateEntryRunnable.kt @@ -37,6 +37,9 @@ class UpdateEntryRunnable constructor( private var mBackupEntryHistory: EntryVersioned = EntryVersioned(mOldEntry) override fun nodeAction() { + // WARNING : Re attribute parent removed in entry edit activity to save memory + mNewEntry.parent = mOldEntry.parent + // Update entry with new values mOldEntry.updateWith(mNewEntry) mNewEntry.touch(modified = true, touchParents = true) diff --git a/app/src/main/java/com/kunzisoft/keepass/database/element/EntryVersioned.kt b/app/src/main/java/com/kunzisoft/keepass/database/element/EntryVersioned.kt index e86177dc2..544ab91ca 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/element/EntryVersioned.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/element/EntryVersioned.kt @@ -61,7 +61,7 @@ class EntryVersioned : NodeVersioned, PwEntryInterface { dest.writeParcelable(pwEntryV4, flags) } - var nodeId: PwNodeId + override var nodeId: PwNodeId get() = pwEntryV4?.nodeId ?: pwEntryV3?.nodeId ?: PwNodeIdUUID() set(value) { pwEntryV3?.nodeId = value diff --git a/app/src/main/java/com/kunzisoft/keepass/database/element/GroupVersioned.kt b/app/src/main/java/com/kunzisoft/keepass/database/element/GroupVersioned.kt index 995491394..acefc0bfc 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/element/GroupVersioned.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/element/GroupVersioned.kt @@ -70,7 +70,7 @@ class GroupVersioned : NodeVersioned, PwGroupInterface? + override val nodeId: PwNodeId<*>? get() = pwGroupV4?.nodeId ?: pwGroupV3?.nodeId override var title: String @@ -237,24 +237,6 @@ class GroupVersioned : NodeVersioned, PwGroupInterface { + val nodeId: PwNodeId<*>? + val nodePositionInParent: Int get() { parent?.getChildren(true)?.let { children -> children.forEachIndexed { index, nodeVersioned -> - if (nodeVersioned == this) + if (nodeVersioned.nodeId == this.nodeId) return index } } diff --git a/app/src/main/java/com/kunzisoft/keepass/database/element/PwDatabase.kt b/app/src/main/java/com/kunzisoft/keepass/database/element/PwDatabase.kt index 6a3e7eab9..d15b1fe41 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/element/PwDatabase.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/element/PwDatabase.kt @@ -341,7 +341,6 @@ abstract class PwDatabase< } fun updateGroup(group: Group) { - getGroupById(group.nodeId)?.parent?.updateChildGroup(group) updateGroupIndex(group) } @@ -359,7 +358,6 @@ abstract class PwDatabase< } fun updateEntry(entry: Entry) { - getEntryById(entry.nodeId)?.parent?.updateChildEntry(entry) updateEntryIndex(entry) } diff --git a/app/src/main/java/com/kunzisoft/keepass/database/element/PwGroup.kt b/app/src/main/java/com/kunzisoft/keepass/database/element/PwGroup.kt index 616ec211a..dbbbca61a 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/element/PwGroup.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/element/PwGroup.kt @@ -57,14 +57,6 @@ abstract class PwGroup this.childEntries[entry.nodeId] = entry } - override fun updateChildEntry(entry: Entry) { - this.childEntries[entry.nodeId] = entry - } - - override fun updateChildGroup(group: Group) { - this.childGroups[group.nodeId] = group - } - override fun removeChildGroup(group: Group) { this.childGroups.remove(group.nodeId) } diff --git a/app/src/main/java/com/kunzisoft/keepass/database/element/PwGroupInterface.kt b/app/src/main/java/com/kunzisoft/keepass/database/element/PwGroupInterface.kt index 8d17a34c0..35d42bb31 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/element/PwGroupInterface.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/element/PwGroupInterface.kt @@ -12,10 +12,6 @@ interface PwGroupInterface, Entry> : PwNod fun addChildEntry(entry: Entry) - fun updateChildEntry(entry: Entry) - - fun updateChildGroup(group: Group) - fun removeChildGroup(group: Group) fun removeChildEntry(entry: Entry) diff --git a/app/src/main/java/com/kunzisoft/keepass/database/element/PwNodeId.kt b/app/src/main/java/com/kunzisoft/keepass/database/element/PwNodeId.kt index 9cfa914ec..38bc119b5 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/element/PwNodeId.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/element/PwNodeId.kt @@ -31,4 +31,17 @@ abstract class PwNodeId : Parcelable { override fun describeContents(): Int { return 0 } + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other !is PwNodeId<*>) return false + + if (id != other.id) return false + + return true + } + + override fun hashCode(): Int { + return id?.hashCode() ?: 0 + } } diff --git a/app/src/main/java/com/kunzisoft/keepass/notifications/DatabaseTaskNotificationService.kt b/app/src/main/java/com/kunzisoft/keepass/notifications/DatabaseTaskNotificationService.kt index a8f371d87..18a9f8935 100644 --- a/app/src/main/java/com/kunzisoft/keepass/notifications/DatabaseTaskNotificationService.kt +++ b/app/src/main/java/com/kunzisoft/keepass/notifications/DatabaseTaskNotificationService.kt @@ -260,10 +260,11 @@ class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdat ) { val database = Database.getInstance() database.getGroupById(intent.getParcelableExtra(GROUP_ID_KEY))?.let { oldGroup -> + val newGroup: GroupVersioned = intent.getParcelableExtra(GROUP_KEY) UpdateGroupRunnable(this, database, oldGroup, - intent.getParcelableExtra(GROUP_KEY), + newGroup, intent.getBooleanExtra(SAVE_DATABASE_KEY, false), AfterActionNodeRunnable()) } @@ -298,10 +299,11 @@ class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdat ) { val database = Database.getInstance() database.getEntryById(intent.getParcelableExtra(ENTRY_ID_KEY))?.let { oldEntry -> + val newEntry: EntryVersioned = intent.getParcelableExtra(ENTRY_KEY) UpdateEntryRunnable(this, database, oldEntry, - intent.getParcelableExtra(ENTRY_KEY), + newEntry, intent.getBooleanExtra(SAVE_DATABASE_KEY, false), AfterActionNodeRunnable()) } From a21de3b8923a2d0c701d463e0dcfa44aacd9d2ce Mon Sep 17 00:00:00 2001 From: J-Jamet Date: Wed, 16 Oct 2019 11:48:35 +0200 Subject: [PATCH 05/16] Fix update group --- .../keepass/activities/EntryEditActivity.kt | 2 +- .../keepass/activities/GroupActivity.kt | 12 ++++--- .../action/node/UpdateEntryRunnable.kt | 5 ++- .../action/node/UpdateGroupRunnable.kt | 6 +++- .../database/element/GroupVersioned.kt | 32 +++++++++++++++++++ .../keepass/database/element/NodeVersioned.kt | 8 +++++ 6 files changed, 56 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/com/kunzisoft/keepass/activities/EntryEditActivity.kt b/app/src/main/java/com/kunzisoft/keepass/activities/EntryEditActivity.kt index 28124050d..d0da88770 100644 --- a/app/src/main/java/com/kunzisoft/keepass/activities/EntryEditActivity.kt +++ b/app/src/main/java/com/kunzisoft/keepass/activities/EntryEditActivity.kt @@ -111,7 +111,7 @@ class EntryEditActivity : LockingHideActivity(), // Create a copy to modify mNewEntry = EntryVersioned(entry).also { newEntry -> // WARNING Remove the parent to keep memory with parcelable - newEntry.parent = null + newEntry.removeParent() } } } diff --git a/app/src/main/java/com/kunzisoft/keepass/activities/GroupActivity.kt b/app/src/main/java/com/kunzisoft/keepass/activities/GroupActivity.kt index 54836e296..0e345e0bb 100644 --- a/app/src/main/java/com/kunzisoft/keepass/activities/GroupActivity.kt +++ b/app/src/main/java/com/kunzisoft/keepass/activities/GroupActivity.kt @@ -749,11 +749,15 @@ class GroupActivity : LockingActivity(), // If update add new elements mOldGroupToUpdate?.let { oldGroupToUpdate -> GroupVersioned(oldGroupToUpdate).let { updateGroup -> - updateGroup.title = name - // TODO custom icon - updateGroup.icon = icon + updateGroup.apply { + // WARNING remove parent and children to keep memory + removeParent() + removeChildren() + + title = name + this.icon = icon // TODO custom icon + } - mListNodesFragment?.removeNode(oldGroupToUpdate) // If group updated save it in the database progressDialogThread?.startDatabaseUpdateGroup( oldGroupToUpdate, updateGroup, !mReadOnly) diff --git a/app/src/main/java/com/kunzisoft/keepass/database/action/node/UpdateEntryRunnable.kt b/app/src/main/java/com/kunzisoft/keepass/database/action/node/UpdateEntryRunnable.kt index a6529a969..b96ccfdfc 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/action/node/UpdateEntryRunnable.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/action/node/UpdateEntryRunnable.kt @@ -38,7 +38,7 @@ class UpdateEntryRunnable constructor( override fun nodeAction() { // WARNING : Re attribute parent removed in entry edit activity to save memory - mNewEntry.parent = mOldEntry.parent + mNewEntry.addParentFrom(mOldEntry) // Update entry with new values mOldEntry.updateWith(mNewEntry) @@ -46,10 +46,9 @@ class UpdateEntryRunnable constructor( // Create an entry history (an entry history don't have history) mOldEntry.addEntryToHistory(EntryVersioned(mBackupEntryHistory, copyHistory = false)) - database.removeOldestHistory(mOldEntry) - // Only change data un index + // Only change data in index database.updateEntry(mOldEntry) } diff --git a/app/src/main/java/com/kunzisoft/keepass/database/action/node/UpdateGroupRunnable.kt b/app/src/main/java/com/kunzisoft/keepass/database/action/node/UpdateGroupRunnable.kt index 60cab4804..ed270b7cd 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/action/node/UpdateGroupRunnable.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/action/node/UpdateGroupRunnable.kt @@ -37,11 +37,15 @@ class UpdateGroupRunnable constructor( private val mBackupGroup: GroupVersioned = GroupVersioned(mOldGroup) override fun nodeAction() { + // WARNING : Re attribute parent and children removed in group activity to save memory + mNewGroup.addParentFrom(mOldGroup) + mNewGroup.addChildrenFrom(mOldGroup) + // Update group with new values mOldGroup.updateWith(mNewGroup) mOldGroup.touch(modified = true, touchParents = true) - // Only change data un index + // Only change data in index database.updateGroup(mOldGroup) } diff --git a/app/src/main/java/com/kunzisoft/keepass/database/element/GroupVersioned.kt b/app/src/main/java/com/kunzisoft/keepass/database/element/GroupVersioned.kt index acefc0bfc..5737738a4 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/element/GroupVersioned.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/element/GroupVersioned.kt @@ -114,6 +114,38 @@ class GroupVersioned : NodeVersioned, PwGroupInterface + pwGroupV3?.addChildEntry(entryToAdd) + } + group.pwGroupV3?.getChildGroups()?.forEach { groupToAdd -> + pwGroupV3?.addChildGroup(groupToAdd) + } + + group.pwGroupV4?.getChildEntries()?.forEach { entryToAdd -> + pwGroupV4?.addChildEntry(entryToAdd) + } + group.pwGroupV4?.getChildGroups()?.forEach { groupToAdd -> + pwGroupV4?.addChildGroup(groupToAdd) + } + } + + fun removeChildren() { + pwGroupV3?.getChildEntries()?.forEach { entryToRemove -> + pwGroupV3?.removeChildEntry(entryToRemove) + } + pwGroupV3?.getChildGroups()?.forEach { groupToRemove -> + pwGroupV3?.removeChildGroup(groupToRemove) + } + + pwGroupV4?.getChildEntries()?.forEach { entryToRemove -> + pwGroupV4?.removeChildEntry(entryToRemove) + } + pwGroupV4?.getChildGroups()?.forEach { groupToRemove -> + pwGroupV4?.removeChildGroup(groupToRemove) + } + } + override fun touch(modified: Boolean, touchParents: Boolean) { pwGroupV3?.touch(modified, touchParents) pwGroupV4?.touch(modified, touchParents) diff --git a/app/src/main/java/com/kunzisoft/keepass/database/element/NodeVersioned.kt b/app/src/main/java/com/kunzisoft/keepass/database/element/NodeVersioned.kt index ad9ef6d74..f231245f8 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/element/NodeVersioned.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/element/NodeVersioned.kt @@ -14,6 +14,14 @@ interface NodeVersioned: PwNodeInterface { } return -1 } + + fun addParentFrom(node: NodeVersioned) { + parent = node.parent + } + + fun removeParent() { + parent = null + } } /** From 2637788429dbc984c176c50ac368a967e6f84607 Mon Sep 17 00:00:00 2001 From: J-Jamet Date: Wed, 16 Oct 2019 15:31:07 +0200 Subject: [PATCH 06/16] Fix dialog update --- .../database/action/ProgressDialogThread.kt | 99 +++++++++++++++---- .../DatabaseTaskNotificationService.kt | 77 ++++++++++----- .../tasks/ProgressTaskDialogFragment.kt | 38 +++++-- .../keepass/utils/BroadcastAction.kt | 2 - 4 files changed, 162 insertions(+), 54 deletions(-) diff --git a/app/src/main/java/com/kunzisoft/keepass/database/action/ProgressDialogThread.kt b/app/src/main/java/com/kunzisoft/keepass/database/action/ProgressDialogThread.kt index e3ade1b6b..0aeea41c3 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/action/ProgressDialogThread.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/action/ProgressDialogThread.kt @@ -1,12 +1,10 @@ package com.kunzisoft.keepass.database.action -import android.content.BroadcastReceiver -import android.content.Context -import android.content.Intent -import android.content.IntentFilter +import android.content.* +import android.content.Context.BIND_ABOVE_CLIENT +import android.content.Context.BIND_NOT_FOREGROUND import android.net.Uri -import android.os.Build -import android.os.Bundle +import android.os.* import androidx.fragment.app.FragmentActivity import com.kunzisoft.keepass.R import com.kunzisoft.keepass.database.element.* @@ -23,38 +21,102 @@ import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Compa import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_UPDATE_ENTRY_TASK import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_UPDATE_GROUP_TASK import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_TASK_KEY +import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.CHECK_ACTION import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.DATABASE_TASK_MESSAGE_KEY -import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.DATABASE_TASK_SUBTITLE_KEY +import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.DATABASE_TASK_WARNING_KEY import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.DATABASE_TASK_TITLE_KEY import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.RESULT_KEY +import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.START_ACTION +import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.STOP_ACTION +import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.UPDATE_ACTION_ELEMENTS import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.getBundleFromListNodes import com.kunzisoft.keepass.tasks.ActionRunnable import com.kunzisoft.keepass.tasks.ProgressTaskDialogFragment +import com.kunzisoft.keepass.tasks.ProgressTaskDialogFragment.Companion.UNDEFINED import com.kunzisoft.keepass.timeout.TimeoutHelper -import com.kunzisoft.keepass.utils.DATABASE_CHECK_TASK_ACTION 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 + class ProgressDialogThread(private val activity: FragmentActivity, var onActionFinish: (actionTask: String, - result: ActionRunnable.Result) -> Unit) { + result: ActionRunnable.Result) -> Unit) { private var progressTaskDialogFragment: ProgressTaskDialogFragment? = null - private var databaseTaskBroadcastReceiver: BroadcastReceiver? = null - private var intentDatabaseTask = Intent(activity, DatabaseTaskNotificationService::class.java) - private fun startDialog(intent: Intent) { + private var databaseTaskBroadcastReceiver: BroadcastReceiver? = null + + private var actionMessenger: Messenger? = null + private var serviceConnection = object: ServiceConnection { + override fun onServiceDisconnected(name: ComponentName?) { + actionMessenger = null + } + + override fun onServiceConnected(name: ComponentName?, serviceBinder: IBinder?) { + actionMessenger = Messenger(serviceBinder) + try { + val message = Message.obtain(null, CHECK_ACTION) + message.replyTo = Messenger(ResponseHandler(activity, onActionFinish)) + actionMessenger?.send(message) + } catch (e: RemoteException) { + e.printStackTrace() + } + } + } + + private class ResponseHandler(private val activity: FragmentActivity, + var onActionFinish: (actionTask: String, + result: ActionRunnable.Result) -> Unit) : Handler() { + override fun handleMessage(message: Message) { + when (message.what) { + START_ACTION -> { + TimeoutHelper.temporarilyDisableTimeout() + ProgressTaskDialogFragment.start(activity, + ProgressTaskDialogFragment.build()) + } + STOP_ACTION -> { + ProgressTaskDialogFragment.stop(activity) + TimeoutHelper.releaseTemporarilyDisableTimeoutAndLockIfTimeout(activity) + val dataBundle = message.data + if (dataBundle != null + && dataBundle.containsKey(ACTION_TASK_KEY) + && dataBundle.containsKey(RESULT_KEY)) + onActionFinish.invoke( + dataBundle.getString(ACTION_TASK_KEY)!!, + ActionRunnable.Result.fromBundle(dataBundle.getBundle(RESULT_KEY)!!)) + } + UPDATE_ACTION_ELEMENTS -> { + // TODO better implementation + val dataBundle = message.data + if (dataBundle != null) { + if (dataBundle.containsKey(DATABASE_TASK_TITLE_KEY)) + ProgressTaskDialogFragment.updateTitle(activity, + message.data.getInt(DATABASE_TASK_TITLE_KEY)) + if (dataBundle.containsKey(DATABASE_TASK_MESSAGE_KEY)) + ProgressTaskDialogFragment.updateMessage(activity, + message.data.getInt(DATABASE_TASK_MESSAGE_KEY)) + if (dataBundle.containsKey(DATABASE_TASK_WARNING_KEY)) + ProgressTaskDialogFragment.updateWarning(activity, + message.data.getInt(DATABASE_TASK_WARNING_KEY)) + } + } + } + } + } + + private fun startDialog(intent: Intent? = null) { TimeoutHelper.temporarilyDisableTimeout() + // Show the dialog - progressTaskDialogFragment = ProgressTaskDialogFragment.build( - intent.getIntExtra(DATABASE_TASK_TITLE_KEY, R.string.loading_database), - intent.getIntExtra(DATABASE_TASK_SUBTITLE_KEY, ProgressTaskDialogFragment.UNDEFINED), - intent.getIntExtra(DATABASE_TASK_MESSAGE_KEY, ProgressTaskDialogFragment.UNDEFINED)) + val title = intent?.getIntExtra(DATABASE_TASK_TITLE_KEY, R.string.loading_database) ?: UNDEFINED + val subTitle = intent?.getIntExtra(DATABASE_TASK_WARNING_KEY, UNDEFINED) ?: UNDEFINED + val message = intent?.getIntExtra(DATABASE_TASK_MESSAGE_KEY, UNDEFINED) ?: UNDEFINED + progressTaskDialogFragment = ProgressTaskDialogFragment.build(title, subTitle, message) ProgressTaskDialogFragment.start(activity, progressTaskDialogFragment!!) } @@ -62,7 +124,6 @@ class ProgressDialogThread(private val activity: FragmentActivity, // Remove the progress task ProgressTaskDialogFragment.stop(activity) TimeoutHelper.releaseTemporarilyDisableTimeoutAndLockIfTimeout(activity) - activity.stopService(intentDatabaseTask) if (intent != null && intent.hasExtra(ACTION_TASK_KEY) && intent.hasExtra(RESULT_KEY)) @@ -97,10 +158,12 @@ class ProgressDialogThread(private val activity: FragmentActivity, ) // Check if a service is currently running - activity.sendBroadcast(Intent(DATABASE_CHECK_TASK_ACTION)) + activity.bindService(intentDatabaseTask, serviceConnection, BIND_NOT_FOREGROUND or BIND_ABOVE_CLIENT) } fun unregisterProgressTask() { + activity.unbindService(serviceConnection) + activity.unregisterReceiver(databaseTaskBroadcastReceiver) } diff --git a/app/src/main/java/com/kunzisoft/keepass/notifications/DatabaseTaskNotificationService.kt b/app/src/main/java/com/kunzisoft/keepass/notifications/DatabaseTaskNotificationService.kt index 18a9f8935..77ccc2696 100644 --- a/app/src/main/java/com/kunzisoft/keepass/notifications/DatabaseTaskNotificationService.kt +++ b/app/src/main/java/com/kunzisoft/keepass/notifications/DatabaseTaskNotificationService.kt @@ -1,12 +1,8 @@ package com.kunzisoft.keepass.notifications -import android.content.BroadcastReceiver -import android.content.Context import android.content.Intent -import android.content.IntentFilter import android.net.Uri -import android.os.AsyncTask -import android.os.Bundle +import android.os.* import android.util.Log import com.kunzisoft.keepass.R import com.kunzisoft.keepass.app.database.FileDatabaseHistoryAction @@ -18,12 +14,12 @@ import com.kunzisoft.keepass.database.action.node.* import com.kunzisoft.keepass.database.element.* import com.kunzisoft.keepass.tasks.ActionRunnable import com.kunzisoft.keepass.tasks.ProgressTaskUpdater -import com.kunzisoft.keepass.utils.DATABASE_CHECK_TASK_ACTION 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 +import android.os.Bundle class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdater { @@ -31,27 +27,44 @@ class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdat private var actionRunnableAsyncTask: ActionRunnableAsyncTask? = null - private var checkBroadcastReceiver: BroadcastReceiver? = null + private var actionStatusHandler = ActionStatusHandler() + private var actionMessenger = Messenger(actionStatusHandler) - override fun onCreate() { - super.onCreate() + private class ActionStatusHandler: Handler() { + var titleId: Int? = null + var messageId: Int? = null + var warningId: Int? = null - checkBroadcastReceiver = object: BroadcastReceiver() { - override fun onReceive(context: Context?, intent: Intent?) { - sendBroadcast(Intent(DATABASE_START_TASK_ACTION)) + override fun handleMessage(message: Message?) { + when (message?.what) { + CHECK_ACTION -> { + try { + // Incoming data + val response = Message.obtain(null, UPDATE_ACTION_ELEMENTS) + response.data = Bundle().apply { + titleId?.let { + putInt(DATABASE_TASK_TITLE_KEY, it) + } + messageId?.let { + putInt(DATABASE_TASK_MESSAGE_KEY, it) + } + warningId?.let { + putInt(DATABASE_TASK_WARNING_KEY, it) + } + } + message.replyTo?.send(response) + } catch (e: RemoteException) { + e.printStackTrace() + } + + } + else -> super.handleMessage(message) } } - - registerReceiver(checkBroadcastReceiver, IntentFilter().apply { - addAction(DATABASE_CHECK_TASK_ACTION) - } - ) } - override fun onDestroy() { - unregisterReceiver(checkBroadcastReceiver) - - super.onDestroy() + override fun onBind(intent: Intent): IBinder? { + return actionMessenger.binder } override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { @@ -72,13 +85,15 @@ class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdat ACTION_DATABASE_LOAD_TASK -> R.string.loading_database else -> R.string.loading_database } - val subtitleId: Int? = when (intent.action) { - else -> null - } val messageId: Int? = when (intent.action) { ACTION_DATABASE_LOAD_TASK -> null - else -> R.string.do_not_kill_app + else -> null } + val warningId: Int? = + if (intent.action == ACTION_DATABASE_LOAD_TASK) + null + else + R.string.do_not_kill_app val actionRunnable: ActionRunnable? = when (intent.action) { ACTION_DATABASE_CREATE_TASK -> buildDatabaseCreateActionTask(intent) @@ -107,13 +122,16 @@ class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdat ACTION_DATABASE_COPY_NODES_TASK, ACTION_DATABASE_MOVE_NODES_TASK, ACTION_DATABASE_DELETE_NODES_TASK -> { + actionStatusHandler.titleId = titleId + actionStatusHandler.messageId = messageId + actionStatusHandler.warningId = warningId newNotification(intent.getIntExtra(DATABASE_TASK_TITLE_KEY, titleId)) actionRunnableAsyncTask = ActionRunnableAsyncTask(this, { sendBroadcast(Intent(DATABASE_START_TASK_ACTION).apply { putExtra(DATABASE_TASK_TITLE_KEY, titleId) - putExtra(DATABASE_TASK_SUBTITLE_KEY, subtitleId) putExtra(DATABASE_TASK_MESSAGE_KEY, messageId) + putExtra(DATABASE_TASK_WARNING_KEY, warningId) }) }, { result -> @@ -121,6 +139,7 @@ class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdat putExtra(ACTION_TASK_KEY, intent.action) putExtra(RESULT_KEY, result.toBundle()) }) + stopSelf() } ) actionRunnable?.let { actionRunnableNotNull -> @@ -412,9 +431,13 @@ class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdat private val TAG = DatabaseTaskNotificationService::class.java.name + const val START_ACTION = 42 + const val STOP_ACTION = 43 + const val CHECK_ACTION = 44 + const val UPDATE_ACTION_ELEMENTS = 45 const val DATABASE_TASK_TITLE_KEY = "DATABASE_TASK_TITLE_KEY" - const val DATABASE_TASK_SUBTITLE_KEY = "DATABASE_TASK_SUBTITLE_KEY" const val DATABASE_TASK_MESSAGE_KEY = "DATABASE_TASK_MESSAGE_KEY" + const val DATABASE_TASK_WARNING_KEY = "DATABASE_TASK_WARNING_KEY" const val ACTION_DATABASE_CREATE_TASK = "ACTION_DATABASE_CREATE_TASK" const val ACTION_DATABASE_SAVE_TASK = "ACTION_DATABASE_SAVE_TASK" diff --git a/app/src/main/java/com/kunzisoft/keepass/tasks/ProgressTaskDialogFragment.kt b/app/src/main/java/com/kunzisoft/keepass/tasks/ProgressTaskDialogFragment.kt index 60235a18d..deb41e426 100644 --- a/app/src/main/java/com/kunzisoft/keepass/tasks/ProgressTaskDialogFragment.kt +++ b/app/src/main/java/com/kunzisoft/keepass/tasks/ProgressTaskDialogFragment.kt @@ -110,12 +110,14 @@ open class ProgressTaskDialogFragment : DialogFragment(), ProgressTaskUpdater { const val UNDEFINED = -1 - fun build(@StringRes titleId: Int, + fun build(@StringRes titleId: Int? = null, @StringRes messageId: Int? = null, @StringRes warningId: Int? = null): ProgressTaskDialogFragment { // Create an instance of the dialog fragment and show it val dialog = ProgressTaskDialogFragment() - dialog.updateTitle(titleId) + titleId?.let { + dialog.updateTitle(it) + } messageId?.let { dialog.updateMessage(it) } @@ -130,12 +132,34 @@ open class ProgressTaskDialogFragment : DialogFragment(), ProgressTaskUpdater { dialog.show(activity.supportFragmentManager, PROGRESS_TASK_DIALOG_TAG) } - fun stop(activity: FragmentActivity) { - val fragmentTask = activity.supportFragmentManager.findFragmentByTag(PROGRESS_TASK_DIALOG_TAG) - if (fragmentTask != null) { - val loadingDatabaseDialog = fragmentTask as ProgressTaskDialogFragment - loadingDatabaseDialog.dismissAllowingStateLoss() + private fun retrieveProgressDialog(activity: FragmentActivity): ProgressTaskDialogFragment? { + return activity.supportFragmentManager + .findFragmentByTag(PROGRESS_TASK_DIALOG_TAG) as ProgressTaskDialogFragment? + } + + private fun retrieveAndShowProgressDialog(activity: FragmentActivity): ProgressTaskDialogFragment { + var dialog = retrieveProgressDialog(activity) + if (dialog == null) { + dialog = build() + start(activity, build()) } + return dialog + } + + fun stop(activity: FragmentActivity) { + retrieveProgressDialog(activity)?.dismissAllowingStateLoss() + } + + fun updateTitle(activity: FragmentActivity, titleId: Int) { + retrieveAndShowProgressDialog(activity).updateTitle(titleId) + } + + fun updateMessage(activity: FragmentActivity, messageId: Int) { + retrieveAndShowProgressDialog(activity).updateMessage(messageId) + } + + fun updateWarning(activity: FragmentActivity, warningId: Int) { + retrieveAndShowProgressDialog(activity).updateWarning(warningId) } } } diff --git a/app/src/main/java/com/kunzisoft/keepass/utils/BroadcastAction.kt b/app/src/main/java/com/kunzisoft/keepass/utils/BroadcastAction.kt index 8d6f8e793..8b8f9d8b2 100644 --- a/app/src/main/java/com/kunzisoft/keepass/utils/BroadcastAction.kt +++ b/app/src/main/java/com/kunzisoft/keepass/utils/BroadcastAction.kt @@ -3,8 +3,6 @@ package com.kunzisoft.keepass.utils const val DATABASE_START_TASK_ACTION = "com.kunzisoft.keepass.DATABASE_START_TASK_ACTION" const val DATABASE_STOP_TASK_ACTION = "com.kunzisoft.keepass.DATABASE_STOP_TASK_ACTION" -const val DATABASE_CHECK_TASK_ACTION = "com.kunzisoft.keepass.DATABASE_CHECK_TASK_ACTION" - const val LOCK_ACTION = "com.kunzisoft.keepass.LOCK" const val REMOVE_ENTRY_MAGIKEYBOARD_ACTION = "com.kunzisoft.keepass.REMOVE_ENTRY_MAGIKEYBOARD" From 891d3142d2668cc1d1166b858607404f9a50af22 Mon Sep 17 00:00:00 2001 From: J-Jamet Date: Wed, 16 Oct 2019 18:49:15 +0200 Subject: [PATCH 07/16] Better code for bind callback --- .../database/action/ProgressDialogThread.kt | 119 +++++++----------- .../DatabaseTaskNotificationService.kt | 117 +++++++++-------- .../tasks/ProgressTaskDialogFragment.kt | 50 +++----- 3 files changed, 131 insertions(+), 155 deletions(-) diff --git a/app/src/main/java/com/kunzisoft/keepass/database/action/ProgressDialogThread.kt b/app/src/main/java/com/kunzisoft/keepass/database/action/ProgressDialogThread.kt index 0aeea41c3..07b411d9d 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/action/ProgressDialogThread.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/action/ProgressDialogThread.kt @@ -4,7 +4,9 @@ import android.content.* import android.content.Context.BIND_ABOVE_CLIENT import android.content.Context.BIND_NOT_FOREGROUND import android.net.Uri -import android.os.* +import android.os.Build +import android.os.Bundle +import android.os.IBinder import androidx.fragment.app.FragmentActivity import com.kunzisoft.keepass.R import com.kunzisoft.keepass.database.element.* @@ -21,18 +23,15 @@ import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Compa import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_UPDATE_ENTRY_TASK import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_UPDATE_GROUP_TASK import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_TASK_KEY -import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.CHECK_ACTION import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.DATABASE_TASK_MESSAGE_KEY -import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.DATABASE_TASK_WARNING_KEY import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.DATABASE_TASK_TITLE_KEY +import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.DATABASE_TASK_WARNING_KEY import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.RESULT_KEY -import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.START_ACTION -import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.STOP_ACTION -import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.UPDATE_ACTION_ELEMENTS import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.getBundleFromListNodes import com.kunzisoft.keepass.tasks.ActionRunnable import com.kunzisoft.keepass.tasks.ProgressTaskDialogFragment import com.kunzisoft.keepass.tasks.ProgressTaskDialogFragment.Companion.UNDEFINED +import com.kunzisoft.keepass.tasks.ProgressTaskDialogFragment.Companion.retrieveProgressDialog import com.kunzisoft.keepass.timeout.TimeoutHelper import com.kunzisoft.keepass.utils.DATABASE_START_TASK_ACTION import com.kunzisoft.keepass.utils.DATABASE_STOP_TASK_ACTION @@ -45,91 +44,64 @@ class ProgressDialogThread(private val activity: FragmentActivity, var onActionFinish: (actionTask: String, result: ActionRunnable.Result) -> Unit) { - private var progressTaskDialogFragment: ProgressTaskDialogFragment? = null - private var intentDatabaseTask = Intent(activity, DatabaseTaskNotificationService::class.java) - private var databaseTaskBroadcastReceiver: BroadcastReceiver? = null + private var mProgressTaskDialogFragment: ProgressTaskDialogFragment? = null + + private var databaseTaskBroadcastReceiver: BroadcastReceiver? = null + private var mBinder: DatabaseTaskNotificationService.ActionTaskBinder? = null - private var actionMessenger: Messenger? = null private var serviceConnection = object: ServiceConnection { - override fun onServiceDisconnected(name: ComponentName?) { - actionMessenger = null - } override fun onServiceConnected(name: ComponentName?, serviceBinder: IBinder?) { - actionMessenger = Messenger(serviceBinder) - try { - val message = Message.obtain(null, CHECK_ACTION) - message.replyTo = Messenger(ResponseHandler(activity, onActionFinish)) - actionMessenger?.send(message) - } catch (e: RemoteException) { - e.printStackTrace() + mBinder = (serviceBinder as DatabaseTaskNotificationService.ActionTaskBinder).apply { + addActionTaskListener(actionTaskListener) + getService().checkAction() } } + + override fun onServiceDisconnected(name: ComponentName?) { + mBinder?.removeActionTaskListener(actionTaskListener) + mBinder = null + } } - private class ResponseHandler(private val activity: FragmentActivity, - var onActionFinish: (actionTask: String, - result: ActionRunnable.Result) -> Unit) : Handler() { - override fun handleMessage(message: Message) { - when (message.what) { - START_ACTION -> { - TimeoutHelper.temporarilyDisableTimeout() - ProgressTaskDialogFragment.start(activity, - ProgressTaskDialogFragment.build()) - } - STOP_ACTION -> { - ProgressTaskDialogFragment.stop(activity) - TimeoutHelper.releaseTemporarilyDisableTimeoutAndLockIfTimeout(activity) - val dataBundle = message.data - if (dataBundle != null - && dataBundle.containsKey(ACTION_TASK_KEY) - && dataBundle.containsKey(RESULT_KEY)) - onActionFinish.invoke( - dataBundle.getString(ACTION_TASK_KEY)!!, - ActionRunnable.Result.fromBundle(dataBundle.getBundle(RESULT_KEY)!!)) - } - UPDATE_ACTION_ELEMENTS -> { - // TODO better implementation - val dataBundle = message.data - if (dataBundle != null) { - if (dataBundle.containsKey(DATABASE_TASK_TITLE_KEY)) - ProgressTaskDialogFragment.updateTitle(activity, - message.data.getInt(DATABASE_TASK_TITLE_KEY)) - if (dataBundle.containsKey(DATABASE_TASK_MESSAGE_KEY)) - ProgressTaskDialogFragment.updateMessage(activity, - message.data.getInt(DATABASE_TASK_MESSAGE_KEY)) - if (dataBundle.containsKey(DATABASE_TASK_WARNING_KEY)) - ProgressTaskDialogFragment.updateWarning(activity, - message.data.getInt(DATABASE_TASK_WARNING_KEY)) - } - } + private val actionTaskListener = object: DatabaseTaskNotificationService.ActionTaskListener { + override fun onStartAction(titleId: Int?, messageId: Int?, warningId: Int?) { + // startDialog(titleId, messageId, warningId) + } + + override fun onUpdateAction(titleId: Int?, messageId: Int?, warningId: Int?) { + retrieveProgressDialog(activity)?.let { + ProgressTaskDialogFragment.update(it, titleId, messageId, warningId) } } + + override fun onStopAction(actionTask: String, result: ActionRunnable.Result) { + // stopDialog(actionTask, result) + } } - private fun startDialog(intent: Intent? = null) { + private fun startDialog(titleId: Int?, messageId: Int?, warningId: Int?) { TimeoutHelper.temporarilyDisableTimeout() // Show the dialog - val title = intent?.getIntExtra(DATABASE_TASK_TITLE_KEY, R.string.loading_database) ?: UNDEFINED - val subTitle = intent?.getIntExtra(DATABASE_TASK_WARNING_KEY, UNDEFINED) ?: UNDEFINED - val message = intent?.getIntExtra(DATABASE_TASK_MESSAGE_KEY, UNDEFINED) ?: UNDEFINED - progressTaskDialogFragment = ProgressTaskDialogFragment.build(title, subTitle, message) - ProgressTaskDialogFragment.start(activity, progressTaskDialogFragment!!) + mProgressTaskDialogFragment = retrieveProgressDialog(activity) + if (mProgressTaskDialogFragment == null) + mProgressTaskDialogFragment = ProgressTaskDialogFragment.build(titleId, messageId, warningId) + else { + ProgressTaskDialogFragment.update(mProgressTaskDialogFragment!!, titleId, messageId, warningId) + } + ProgressTaskDialogFragment.start(activity, mProgressTaskDialogFragment!!) } - private fun stopDialog(intent: Intent? = null) { + private fun stopDialog(actionTask: String? = null, result: ActionRunnable.Result? = null) { // Remove the progress task ProgressTaskDialogFragment.stop(activity) TimeoutHelper.releaseTemporarilyDisableTimeoutAndLockIfTimeout(activity) - if (intent != null - && intent.hasExtra(ACTION_TASK_KEY) - && intent.hasExtra(RESULT_KEY)) - onActionFinish.invoke( - intent.getStringExtra(ACTION_TASK_KEY), - ActionRunnable.Result.fromBundle(intent.getBundleExtra(RESULT_KEY))) + + if (actionTask != null && result != null) + onActionFinish.invoke(actionTask, result) } fun registerProgressTask() { @@ -141,10 +113,15 @@ class ProgressDialogThread(private val activity: FragmentActivity, activity.runOnUiThread { when (intent?.action) { DATABASE_START_TASK_ACTION -> { - startDialog(intent) + val title = intent.getIntExtra(DATABASE_TASK_TITLE_KEY, R.string.loading_database) + val message = intent.getIntExtra(DATABASE_TASK_MESSAGE_KEY, UNDEFINED) + val warning = intent.getIntExtra(DATABASE_TASK_WARNING_KEY, UNDEFINED) + startDialog(title, message, warning) } DATABASE_STOP_TASK_ACTION -> { - stopDialog(intent) + val actionTask = intent.getStringExtra(ACTION_TASK_KEY) + val result = ActionRunnable.Result.fromBundle(intent.getBundleExtra(RESULT_KEY)) + stopDialog(actionTask, result) } } } diff --git a/app/src/main/java/com/kunzisoft/keepass/notifications/DatabaseTaskNotificationService.kt b/app/src/main/java/com/kunzisoft/keepass/notifications/DatabaseTaskNotificationService.kt index 77ccc2696..6f5f137b4 100644 --- a/app/src/main/java/com/kunzisoft/keepass/notifications/DatabaseTaskNotificationService.kt +++ b/app/src/main/java/com/kunzisoft/keepass/notifications/DatabaseTaskNotificationService.kt @@ -2,7 +2,10 @@ package com.kunzisoft.keepass.notifications import android.content.Intent import android.net.Uri -import android.os.* +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.FileDatabaseHistoryAction @@ -19,7 +22,6 @@ import com.kunzisoft.keepass.utils.DATABASE_STOP_TASK_ACTION import java.io.File import java.util.* import kotlin.collections.ArrayList -import android.os.Bundle class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdater { @@ -27,44 +29,40 @@ class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdat private var actionRunnableAsyncTask: ActionRunnableAsyncTask? = null - private var actionStatusHandler = ActionStatusHandler() - private var actionMessenger = Messenger(actionStatusHandler) + private var mActionTaskBinder = ActionTaskBinder() + private var mActionTaskListeners = LinkedList() - private class ActionStatusHandler: Handler() { - var titleId: Int? = null - var messageId: Int? = null - var warningId: Int? = null + private var mTitleId: Int? = null + private var mMessageId: Int? = null + private var mWarningId: Int? = null - override fun handleMessage(message: Message?) { - when (message?.what) { - CHECK_ACTION -> { - try { - // Incoming data - val response = Message.obtain(null, UPDATE_ACTION_ELEMENTS) - response.data = Bundle().apply { - titleId?.let { - putInt(DATABASE_TASK_TITLE_KEY, it) - } - messageId?.let { - putInt(DATABASE_TASK_MESSAGE_KEY, it) - } - warningId?.let { - putInt(DATABASE_TASK_WARNING_KEY, it) - } - } - message.replyTo?.send(response) - } catch (e: RemoteException) { - e.printStackTrace() - } + inner class ActionTaskBinder: Binder() { - } - else -> super.handleMessage(message) - } + fun getService(): DatabaseTaskNotificationService = this@DatabaseTaskNotificationService + + fun addActionTaskListener(actionTaskListener: ActionTaskListener) { + mActionTaskListeners.add(actionTaskListener) + } + + fun removeActionTaskListener(actionTaskListener: ActionTaskListener) { + mActionTaskListeners.remove(actionTaskListener) + } + } + + interface ActionTaskListener { + fun onStartAction(titleId: Int?, messageId: Int?, warningId: Int?) + fun onUpdateAction(titleId: Int?, messageId: Int?, warningId: Int?) + fun onStopAction(actionTask: String, result: ActionRunnable.Result) + } + + fun checkAction() { + mActionTaskListeners.forEach { actionTaskListener -> + actionTaskListener.onUpdateAction(mTitleId, mMessageId, mWarningId) } } override fun onBind(intent: Intent): IBinder? { - return actionMessenger.binder + return mActionTaskBinder } override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { @@ -122,25 +120,40 @@ class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdat ACTION_DATABASE_COPY_NODES_TASK, ACTION_DATABASE_MOVE_NODES_TASK, ACTION_DATABASE_DELETE_NODES_TASK -> { - actionStatusHandler.titleId = titleId - actionStatusHandler.messageId = messageId - actionStatusHandler.warningId = warningId - newNotification(intent.getIntExtra(DATABASE_TASK_TITLE_KEY, titleId)) - actionRunnableAsyncTask = ActionRunnableAsyncTask(this, - { - sendBroadcast(Intent(DATABASE_START_TASK_ACTION).apply { - putExtra(DATABASE_TASK_TITLE_KEY, titleId) - putExtra(DATABASE_TASK_MESSAGE_KEY, messageId) - putExtra(DATABASE_TASK_WARNING_KEY, warningId) - }) - }, { result -> - sendBroadcast(Intent(DATABASE_STOP_TASK_ACTION).apply { - putExtra(ACTION_TASK_KEY, intent.action) - putExtra(RESULT_KEY, result.toBundle()) - }) - stopSelf() + // Assign elements for updates + mTitleId = titleId + mMessageId = messageId + mWarningId = warningId + + // Create the notification + newNotification(intent.getIntExtra(DATABASE_TASK_TITLE_KEY, titleId)) + + // Build and launch the action + actionRunnableAsyncTask = ActionRunnableAsyncTask(this, + { + mActionTaskListeners.forEach { actionTaskListener -> + actionTaskListener.onStartAction(titleId, messageId, warningId) } + + sendBroadcast(Intent(DATABASE_START_TASK_ACTION).apply { + putExtra(DATABASE_TASK_TITLE_KEY, titleId) + putExtra(DATABASE_TASK_MESSAGE_KEY, messageId) + putExtra(DATABASE_TASK_WARNING_KEY, warningId) + }) + + }, { result -> + mActionTaskListeners.forEach { actionTaskListener -> + actionTaskListener.onStopAction(intent.action!!, result) + } + + sendBroadcast(Intent(DATABASE_STOP_TASK_ACTION).apply { + putExtra(ACTION_TASK_KEY, intent.action) + putExtra(RESULT_KEY, result.toBundle()) + }) + + stopSelf() + } ) actionRunnable?.let { actionRunnableNotNull -> actionRunnableAsyncTask?.execute({ actionRunnableNotNull }) @@ -431,10 +444,6 @@ class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdat private val TAG = DatabaseTaskNotificationService::class.java.name - const val START_ACTION = 42 - const val STOP_ACTION = 43 - const val CHECK_ACTION = 44 - const val UPDATE_ACTION_ELEMENTS = 45 const val DATABASE_TASK_TITLE_KEY = "DATABASE_TASK_TITLE_KEY" const val DATABASE_TASK_MESSAGE_KEY = "DATABASE_TASK_MESSAGE_KEY" const val DATABASE_TASK_WARNING_KEY = "DATABASE_TASK_WARNING_KEY" diff --git a/app/src/main/java/com/kunzisoft/keepass/tasks/ProgressTaskDialogFragment.kt b/app/src/main/java/com/kunzisoft/keepass/tasks/ProgressTaskDialogFragment.kt index deb41e426..17517a4c8 100644 --- a/app/src/main/java/com/kunzisoft/keepass/tasks/ProgressTaskDialogFragment.kt +++ b/app/src/main/java/com/kunzisoft/keepass/tasks/ProgressTaskDialogFragment.kt @@ -115,51 +115,41 @@ open class ProgressTaskDialogFragment : DialogFragment(), ProgressTaskUpdater { @StringRes warningId: Int? = null): ProgressTaskDialogFragment { // Create an instance of the dialog fragment and show it val dialog = ProgressTaskDialogFragment() - titleId?.let { - dialog.updateTitle(it) - } - messageId?.let { - dialog.updateMessage(it) - } - warningId?.let { - dialog.updateWarning(it) - } + update(dialog, titleId, messageId, warningId) return dialog } fun start(activity: FragmentActivity, dialog: ProgressTaskDialogFragment) { - dialog.show(activity.supportFragmentManager, PROGRESS_TASK_DIALOG_TAG) + activity.runOnUiThread { + dialog.show(activity.supportFragmentManager, PROGRESS_TASK_DIALOG_TAG) + } } - private fun retrieveProgressDialog(activity: FragmentActivity): ProgressTaskDialogFragment? { + fun retrieveProgressDialog(activity: FragmentActivity): ProgressTaskDialogFragment? { return activity.supportFragmentManager .findFragmentByTag(PROGRESS_TASK_DIALOG_TAG) as ProgressTaskDialogFragment? } - private fun retrieveAndShowProgressDialog(activity: FragmentActivity): ProgressTaskDialogFragment { - var dialog = retrieveProgressDialog(activity) - if (dialog == null) { - dialog = build() - start(activity, build()) - } - return dialog - } - fun stop(activity: FragmentActivity) { retrieveProgressDialog(activity)?.dismissAllowingStateLoss() } - fun updateTitle(activity: FragmentActivity, titleId: Int) { - retrieveAndShowProgressDialog(activity).updateTitle(titleId) - } - - fun updateMessage(activity: FragmentActivity, messageId: Int) { - retrieveAndShowProgressDialog(activity).updateMessage(messageId) - } - - fun updateWarning(activity: FragmentActivity, warningId: Int) { - retrieveAndShowProgressDialog(activity).updateWarning(warningId) + fun update(dialog: ProgressTaskDialogFragment, + titleId: Int?, + messageId: Int?, + warningId: Int?) { + dialog.apply { + titleId?.let { + updateTitle(it) + } + messageId?.let { + updateMessage(it) + } + warningId?.let { + updateWarning(it) + } + } } } } From b559670dff6de660066fcc433ee03889d21ef192 Mon Sep 17 00:00:00 2001 From: J-Jamet Date: Thu, 17 Oct 2019 09:53:00 +0200 Subject: [PATCH 08/16] Fix result security by binder --- .../keepass/activities/PasswordActivity.kt | 161 +++++++++--------- .../database/action/LoadDatabaseRunnable.kt | 5 +- .../database/action/ProgressDialogThread.kt | 25 +-- .../DatabaseTaskNotificationService.kt | 53 +++--- ...abaseSavePreferenceDialogFragmentCompat.kt | 31 +--- 5 files changed, 140 insertions(+), 135 deletions(-) diff --git a/app/src/main/java/com/kunzisoft/keepass/activities/PasswordActivity.kt b/app/src/main/java/com/kunzisoft/keepass/activities/PasswordActivity.kt index b95d558d8..def11479d 100644 --- a/app/src/main/java/com/kunzisoft/keepass/activities/PasswordActivity.kt +++ b/app/src/main/java/com/kunzisoft/keepass/activities/PasswordActivity.kt @@ -30,9 +30,6 @@ import android.os.Build import android.os.Bundle import android.os.Handler import android.preference.PreferenceManager -import androidx.annotation.RequiresApi -import com.google.android.material.snackbar.Snackbar -import androidx.appcompat.widget.Toolbar import android.text.Editable import android.text.TextWatcher import android.util.Log @@ -41,8 +38,14 @@ import android.view.Menu import android.view.MenuItem import android.view.View import android.view.inputmethod.EditorInfo.IME_ACTION_DONE -import android.widget.* +import android.widget.Button +import android.widget.CompoundButton +import android.widget.EditText +import android.widget.TextView +import androidx.annotation.RequiresApi +import androidx.appcompat.widget.Toolbar import androidx.biometric.BiometricManager +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 @@ -52,19 +55,18 @@ 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.utils.FileDatabaseInfo import com.kunzisoft.keepass.app.database.FileDatabaseHistoryAction import com.kunzisoft.keepass.autofill.AutofillHelper -import com.kunzisoft.keepass.database.element.Database -import com.kunzisoft.keepass.education.PasswordActivityEducation import com.kunzisoft.keepass.biometric.AdvancedUnlockedManager 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.settings.PreferencesUtil -import com.kunzisoft.keepass.tasks.ActionRunnable +import com.kunzisoft.keepass.utils.FileDatabaseInfo import com.kunzisoft.keepass.utils.MenuUtil import com.kunzisoft.keepass.utils.UriUtil import com.kunzisoft.keepass.view.AdvancedUnlockInfoView @@ -164,7 +166,78 @@ class PasswordActivity : StylishActivity() { when (actionTask) { ACTION_DATABASE_LOAD_TASK -> { // TODO - onFinishLoadDatabase?.onFinishRun(result) + // Recheck fingerprint if error + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + if (PreferencesUtil.isBiometricUnlockEnable(this@PasswordActivity)) { + // Stay with the same mode and init it + advancedUnlockedManager?.initBiometricMode() + } + } + + var databaseUri: Uri? = null + var masterPassword: String? = null + var keyFileUri: Uri? = 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) + } + + databaseUri?.let { databaseFileUri -> + 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 + // TODO Cipher + /* + if (cipherDatabaseEntity != null) { + CipherDatabaseAction.getInstance(this@PasswordActivity) + .addOrUpdateCipherDatabase(cipherDatabaseEntity) { + checkAndLaunchGroupActivity(Database.getInstance(), + masterPassword, + keyFileUri) + } + } else { + + */ + checkAndLaunchGroupActivity(Database.getInstance(), + masterPassword, + keyFileUri) + //} + + } 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, + keyFileUri, + true) + } + } + + 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() + } + } } } } @@ -426,17 +499,13 @@ class PasswordActivity : StylishActivity() { checkboxPasswordView?.isChecked = false } - private var onFinishLoadDatabase: ActionRunnable? = null - private fun loadDatabase(databaseFileUri: Uri?, password: String?, keyFileUri: Uri?, cipherDatabaseEntity: CipherDatabaseEntity? = null) { - runOnUiThread { - if (PreferencesUtil.deletePasswordAfterConnexionAttempt(this)) { - removePassword() - } + if (PreferencesUtil.deletePasswordAfterConnexionAttempt(this)) { + removePassword() } // Clear before we load @@ -444,66 +513,6 @@ class PasswordActivity : StylishActivity() { database.closeAndClear(applicationContext.filesDir) databaseFileUri?.let { databaseUri -> - - onFinishLoadDatabase = object: ActionRunnable() { - override fun onFinishRun(result: Result) { - runOnUiThread { - // Recheck fingerprint if error - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - if (PreferencesUtil.isBiometricUnlockEnable(this@PasswordActivity)) { - // Stay with the same mode and init it - advancedUnlockedManager?.initBiometricMode() - } - } - - 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 - if (cipherDatabaseEntity != null) { - CipherDatabaseAction.getInstance(this@PasswordActivity) - .addOrUpdateCipherDatabase(cipherDatabaseEntity) { - checkAndLaunchGroupActivity(database, password, keyFileUri) - } - } else { - checkAndLaunchGroupActivity(database, password, keyFileUri) - } - - } else { - var resultError = "" - val resultException = result.exception - val resultMessage = result.message - - if (resultException != null) { - resultError = resultException.getLocalizedMessage(resources) - if (resultException is LoadDatabaseDuplicateUuidException) - showLoadDatabaseDuplicateUuidMessage { - showProgressDialogAndLoadDatabase( - databaseUri, - password, - keyFileUri, - true) - } - } - - 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() - } - } - } - } - // Show the progress dialog and load the database showProgressDialogAndLoadDatabase( databaseUri, diff --git a/app/src/main/java/com/kunzisoft/keepass/database/action/LoadDatabaseRunnable.kt b/app/src/main/java/com/kunzisoft/keepass/database/action/LoadDatabaseRunnable.kt index c63ed3aa6..805921b4f 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/action/LoadDatabaseRunnable.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/action/LoadDatabaseRunnable.kt @@ -35,8 +35,9 @@ class LoadDatabaseRunnable(private val mDatabase: Database, private val cacheDirectory: File, private val mOmitBackup: Boolean, private val mFixDuplicateUUID: Boolean, - private val progressTaskUpdater: ProgressTaskUpdater?) - : ActionRunnable(null, executeNestedActionIfResultFalse = true) { + private val progressTaskUpdater: ProgressTaskUpdater?, + actionFinishRunnable: ActionRunnable?) + : ActionRunnable(actionFinishRunnable, executeNestedActionIfResultFalse = true) { override fun run() { try { diff --git a/app/src/main/java/com/kunzisoft/keepass/database/action/ProgressDialogThread.kt b/app/src/main/java/com/kunzisoft/keepass/database/action/ProgressDialogThread.kt index 07b411d9d..147ce8c43 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/action/ProgressDialogThread.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/action/ProgressDialogThread.kt @@ -22,11 +22,9 @@ import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Compa import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_SAVE_TASK import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_UPDATE_ENTRY_TASK import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_UPDATE_GROUP_TASK -import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_TASK_KEY import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.DATABASE_TASK_MESSAGE_KEY import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.DATABASE_TASK_TITLE_KEY import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.DATABASE_TASK_WARNING_KEY -import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.RESULT_KEY import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.getBundleFromListNodes import com.kunzisoft.keepass.tasks.ActionRunnable import com.kunzisoft.keepass.tasks.ProgressTaskDialogFragment @@ -78,7 +76,8 @@ class ProgressDialogThread(private val activity: FragmentActivity, } override fun onStopAction(actionTask: String, result: ActionRunnable.Result) { - // stopDialog(actionTask, result) + onActionFinish.invoke(actionTask, result) + stopDialog() } } @@ -95,13 +94,11 @@ class ProgressDialogThread(private val activity: FragmentActivity, ProgressTaskDialogFragment.start(activity, mProgressTaskDialogFragment!!) } - private fun stopDialog(actionTask: String? = null, result: ActionRunnable.Result? = null) { + private fun stopDialog() { // Remove the progress task ProgressTaskDialogFragment.stop(activity) - TimeoutHelper.releaseTemporarilyDisableTimeoutAndLockIfTimeout(activity) - if (actionTask != null && result != null) - onActionFinish.invoke(actionTask, result) + TimeoutHelper.releaseTemporarilyDisableTimeoutAndLockIfTimeout(activity) } fun registerProgressTask() { @@ -117,11 +114,14 @@ class ProgressDialogThread(private val activity: FragmentActivity, val message = intent.getIntExtra(DATABASE_TASK_MESSAGE_KEY, UNDEFINED) val warning = intent.getIntExtra(DATABASE_TASK_WARNING_KEY, UNDEFINED) startDialog(title, message, warning) + + // Bind to the service when is starting + activity.bindService(intentDatabaseTask, serviceConnection, BIND_NOT_FOREGROUND or BIND_ABOVE_CLIENT) } DATABASE_STOP_TASK_ACTION -> { - val actionTask = intent.getStringExtra(ACTION_TASK_KEY) - val result = ActionRunnable.Result.fromBundle(intent.getBundleExtra(RESULT_KEY)) - stopDialog(actionTask, result) + activity.unbindService(serviceConnection) + + stopDialog() } } } @@ -134,11 +134,14 @@ class ProgressDialogThread(private val activity: FragmentActivity, } ) - // Check if a service is currently running + // Check if a service is currently running else do nothing activity.bindService(intentDatabaseTask, serviceConnection, BIND_NOT_FOREGROUND or BIND_ABOVE_CLIENT) } fun unregisterProgressTask() { + mBinder?.removeActionTaskListener(actionTaskListener) + mBinder = null + activity.unbindService(serviceConnection) activity.unregisterReceiver(databaseTaskBroadcastReceiver) diff --git a/app/src/main/java/com/kunzisoft/keepass/notifications/DatabaseTaskNotificationService.kt b/app/src/main/java/com/kunzisoft/keepass/notifications/DatabaseTaskNotificationService.kt index 6f5f137b4..d0da59e1f 100644 --- a/app/src/main/java/com/kunzisoft/keepass/notifications/DatabaseTaskNotificationService.kt +++ b/app/src/main/java/com/kunzisoft/keepass/notifications/DatabaseTaskNotificationService.kt @@ -69,7 +69,9 @@ class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdat if (intent == null) return START_REDELIVER_INTENT - val titleId: Int = when (intent.action) { + val intentAction = intent.action + + val titleId: Int = when (intentAction) { ACTION_DATABASE_CREATE_TASK -> R.string.creating_database ACTION_DATABASE_SAVE_TASK, ACTION_DATABASE_ASSIGN_PASSWORD_TASK, @@ -83,17 +85,17 @@ class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdat ACTION_DATABASE_LOAD_TASK -> R.string.loading_database else -> R.string.loading_database } - val messageId: Int? = when (intent.action) { + val messageId: Int? = when (intentAction) { ACTION_DATABASE_LOAD_TASK -> null else -> null } val warningId: Int? = - if (intent.action == ACTION_DATABASE_LOAD_TASK) + if (intentAction == ACTION_DATABASE_LOAD_TASK) null else R.string.do_not_kill_app - val actionRunnable: ActionRunnable? = when (intent.action) { + val actionRunnable: ActionRunnable? = when (intentAction) { ACTION_DATABASE_CREATE_TASK -> buildDatabaseCreateActionTask(intent) ACTION_DATABASE_SAVE_TASK -> buildDatabaseSaveActionTask() ACTION_DATABASE_LOAD_TASK -> buildDatabaseLoadActionTask(intent) @@ -108,7 +110,7 @@ class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdat else -> null } - when (intent.action ) { + when (intentAction) { ACTION_DATABASE_CREATE_TASK, ACTION_DATABASE_SAVE_TASK, ACTION_DATABASE_LOAD_TASK, @@ -132,25 +134,22 @@ class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdat // Build and launch the action actionRunnableAsyncTask = ActionRunnableAsyncTask(this, { - mActionTaskListeners.forEach { actionTaskListener -> - actionTaskListener.onStartAction(titleId, messageId, warningId) - } - sendBroadcast(Intent(DATABASE_START_TASK_ACTION).apply { putExtra(DATABASE_TASK_TITLE_KEY, titleId) putExtra(DATABASE_TASK_MESSAGE_KEY, messageId) putExtra(DATABASE_TASK_WARNING_KEY, warningId) }) - }, { result -> mActionTaskListeners.forEach { actionTaskListener -> - actionTaskListener.onStopAction(intent.action!!, result) + actionTaskListener.onStartAction(titleId, messageId, warningId) } - sendBroadcast(Intent(DATABASE_STOP_TASK_ACTION).apply { - putExtra(ACTION_TASK_KEY, intent.action) - putExtra(RESULT_KEY, result.toBundle()) - }) + }, { result -> + mActionTaskListeners.forEach { actionTaskListener -> + actionTaskListener.onStopAction(intentAction, result) + } + + sendBroadcast(Intent(DATABASE_STOP_TASK_ACTION)) stopSelf() } @@ -233,16 +232,29 @@ class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdat && intent.hasExtra(OMIT_BACKUP_KEY) && intent.hasExtra(FIX_DUPLICATE_UUID_KEY) ) { + val databaseUri: Uri = intent.getParcelableExtra(DATABASE_URI_KEY) + val masterPassword: String? = intent.getStringExtra(MASTER_PASSWORD_KEY) + val keyFileUri: Uri? = intent.getParcelableExtra(KEY_FILE_KEY) + return LoadDatabaseRunnable( Database.getInstance(), - intent.getParcelableExtra(DATABASE_URI_KEY), - intent.getStringExtra(MASTER_PASSWORD_KEY), - intent.getParcelableExtra(KEY_FILE_KEY), + databaseUri, + masterPassword, + keyFileUri, contentResolver, intent.getSerializableExtra(CACHE_DIR_KEY) as File, intent.getBooleanExtra(OMIT_BACKUP_KEY, false), intent.getBooleanExtra(FIX_DUPLICATE_UUID_KEY, false), - this) + this, + object: ActionRunnable() { + override fun onFinishRun(result: Result) { + result.data = Bundle().apply { + putParcelable(DATABASE_URI_KEY, databaseUri) + putString(MASTER_PASSWORD_KEY, masterPassword) + putParcelable(KEY_FILE_KEY, keyFileUri) + } + } + }) } else { return null } @@ -479,9 +491,6 @@ class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdat const val OLD_NODES_KEY = "OLD_NODES_KEY" const val NEW_NODES_KEY = "NEW_NODES_KEY" - const val ACTION_TASK_KEY = "ACTION_TASK_KEY" - const val RESULT_KEY = "RESULT_KEY" - fun getListNodesFromBundle(database: Database, bundle: Bundle): List { val nodesAction = ArrayList() bundle.getParcelableArrayList>(GROUPS_ID_KEY)?.forEach { diff --git a/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/DatabaseSavePreferenceDialogFragmentCompat.kt b/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/DatabaseSavePreferenceDialogFragmentCompat.kt index c5646200a..9b0ee00b1 100644 --- a/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/DatabaseSavePreferenceDialogFragmentCompat.kt +++ b/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/DatabaseSavePreferenceDialogFragmentCompat.kt @@ -19,25 +19,18 @@ */ package com.kunzisoft.keepass.settings.preferencedialogfragment -import android.content.BroadcastReceiver -import android.content.Context -import android.content.Intent -import android.content.IntentFilter import android.content.res.Resources import android.os.Bundle import android.view.View import com.kunzisoft.keepass.database.element.Database -import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.RESULT_KEY import com.kunzisoft.keepass.settings.SettingsActivity import com.kunzisoft.keepass.tasks.ActionRunnable -import com.kunzisoft.keepass.utils.DATABASE_STOP_TASK_ACTION abstract class DatabaseSavePreferenceDialogFragmentCompat : InputPreferenceDialogFragmentCompat() { protected var database: Database? = null var actionInUIThreadAfterSaveDatabase: ActionRunnable? = null - private var databaseTaskBroadcastReceiver: BroadcastReceiver? = null protected lateinit var settingsResources: Resources @@ -55,31 +48,21 @@ abstract class DatabaseSavePreferenceDialogFragmentCompat : InputPreferenceDialo override fun onDialogClosed(positiveResult: Boolean) { if (positiveResult) { - registerProgressTask() + registerActionFinish() (activity as SettingsActivity?)?.progressDialogThread?.startDatabaseSave() } } - fun registerProgressTask() { + fun registerActionFinish() { // TODO remove receiver // Register a database task receiver to stop loading dialog when service finish the task - databaseTaskBroadcastReceiver = object : BroadcastReceiver() { - override fun onReceive(context: Context?, intent: Intent?) { - when (intent?.action) { - DATABASE_STOP_TASK_ACTION -> { - var result = ActionRunnable.Result(false) - if (intent.hasExtra(RESULT_KEY)) - result = ActionRunnable.Result.fromBundle(intent.getBundleExtra(RESULT_KEY)) - actionInUIThreadAfterSaveDatabase?.onFinishRun(result) - } - } + /* + when (intent?.action) { + DATABASE_STOP_TASK_ACTION -> { + actionInUIThreadAfterSaveDatabase?.onFinishRun(result) } } - activity?.registerReceiver(databaseTaskBroadcastReceiver, - IntentFilter().apply { - addAction(DATABASE_STOP_TASK_ACTION) - } - ) + */ } companion object { From 2982f67717d1b13dbe10df4a50bc17743b3983f1 Mon Sep 17 00:00:00 2001 From: J-Jamet Date: Thu, 17 Oct 2019 10:24:12 +0200 Subject: [PATCH 09/16] Fix biometric recognition with new loading process --- .../keepass/activities/PasswordActivity.kt | 28 +++++---- .../app/database/CipherDatabaseEntity.kt | 30 +++++++++- .../biometric/AdvancedUnlockedManager.kt | 34 ++++++----- .../database/action/ProgressDialogThread.kt | 57 +++++++++++++------ .../DatabaseTaskNotificationService.kt | 5 ++ 5 files changed, 109 insertions(+), 45 deletions(-) diff --git a/app/src/main/java/com/kunzisoft/keepass/activities/PasswordActivity.kt b/app/src/main/java/com/kunzisoft/keepass/activities/PasswordActivity.kt index def11479d..ce3a32baa 100644 --- a/app/src/main/java/com/kunzisoft/keepass/activities/PasswordActivity.kt +++ b/app/src/main/java/com/kunzisoft/keepass/activities/PasswordActivity.kt @@ -55,6 +55,7 @@ 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 @@ -165,7 +166,6 @@ class PasswordActivity : StylishActivity() { progressDialogThread = ProgressDialogThread(this) { actionTask, result -> when (actionTask) { ACTION_DATABASE_LOAD_TASK -> { - // TODO // Recheck fingerprint if error if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if (PreferencesUtil.isBiometricUnlockEnable(this@PasswordActivity)) { @@ -177,11 +177,13 @@ class PasswordActivity : StylishActivity() { var databaseUri: Uri? = null var masterPassword: String? = null var keyFileUri: Uri? = null + 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?.let { databaseFileUri -> @@ -195,22 +197,18 @@ class PasswordActivity : StylishActivity() { removePassword() // Register the biometric - // TODO Cipher - /* - if (cipherDatabaseEntity != null) { + cipherEntity?.let { cipherDatabaseEntity -> CipherDatabaseAction.getInstance(this@PasswordActivity) .addOrUpdateCipherDatabase(cipherDatabaseEntity) { checkAndLaunchGroupActivity(Database.getInstance(), masterPassword, keyFileUri) } - } else { - - */ - checkAndLaunchGroupActivity(Database.getInstance(), - masterPassword, - keyFileUri) - //} + } ?: run { + checkAndLaunchGroupActivity(Database.getInstance(), + masterPassword, + keyFileUri) + } } else { var resultError = "" @@ -225,6 +223,7 @@ class PasswordActivity : StylishActivity() { databaseFileUri, masterPassword, keyFileUri, + cipherEntity, true) } } @@ -235,7 +234,9 @@ class PasswordActivity : StylishActivity() { Log.e(TAG, resultError, resultException) - Snackbar.make(activity_password_coordinator_layout, resultError, Snackbar.LENGTH_LONG).asError().show() + Snackbar.make(activity_password_coordinator_layout, + resultError, + Snackbar.LENGTH_LONG).asError().show() } } } @@ -518,6 +519,7 @@ class PasswordActivity : StylishActivity() { databaseUri, password, keyFileUri, + cipherDatabaseEntity, false) } } @@ -525,11 +527,13 @@ class PasswordActivity : StylishActivity() { private fun showProgressDialogAndLoadDatabase(databaseUri: Uri, password: String?, keyFile: Uri?, + cipherDatabaseEntity: CipherDatabaseEntity?, fixDuplicateUUID: Boolean) { progressDialogThread?.startDatabaseLoad( databaseUri, password, keyFile, + cipherDatabaseEntity, filesDir, PreferencesUtil.omitBackup(this@PasswordActivity), fixDuplicateUUID diff --git a/app/src/main/java/com/kunzisoft/keepass/app/database/CipherDatabaseEntity.kt b/app/src/main/java/com/kunzisoft/keepass/app/database/CipherDatabaseEntity.kt index 140b2bf2c..304517552 100644 --- a/app/src/main/java/com/kunzisoft/keepass/app/database/CipherDatabaseEntity.kt +++ b/app/src/main/java/com/kunzisoft/keepass/app/database/CipherDatabaseEntity.kt @@ -1,5 +1,7 @@ package com.kunzisoft.keepass.app.database +import android.os.Parcel +import android.os.Parcelable import androidx.room.ColumnInfo import androidx.room.Entity import androidx.room.PrimaryKey @@ -15,7 +17,33 @@ data class CipherDatabaseEntity( @ColumnInfo(name = "specs_parameters") var specParameters: String -) { +): Parcelable { + + constructor(parcel: Parcel) : this( + parcel.readString()!!, + parcel.readString()!!, + parcel.readString()!!) + + override fun writeToParcel(parcel: Parcel, flags: Int) { + parcel.writeString(databaseUri) + parcel.writeString(encryptedValue) + parcel.writeString(specParameters) + } + + override fun describeContents(): Int { + return 0 + } + + companion object CREATOR : Parcelable.Creator { + override fun createFromParcel(parcel: Parcel): CipherDatabaseEntity { + return CipherDatabaseEntity(parcel) + } + + override fun newArray(size: Int): Array { + return arrayOfNulls(size) + } + } + override fun equals(other: Any?): Boolean { if (this === other) return true if (javaClass != other?.javaClass) return false diff --git a/app/src/main/java/com/kunzisoft/keepass/biometric/AdvancedUnlockedManager.kt b/app/src/main/java/com/kunzisoft/keepass/biometric/AdvancedUnlockedManager.kt index 7e03b7ad7..784a7d7b1 100644 --- a/app/src/main/java/com/kunzisoft/keepass/biometric/AdvancedUnlockedManager.kt +++ b/app/src/main/java/com/kunzisoft/keepass/biometric/AdvancedUnlockedManager.kt @@ -121,20 +121,26 @@ class AdvancedUnlockedManager(var context: FragmentActivity, } override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) { - when (biometricMode) { - Mode.UNAVAILABLE -> {} - Mode.PAUSE -> {} - Mode.NOT_CONFIGURED -> {} - Mode.WAIT_CREDENTIAL -> {} - Mode.STORE -> { - // newly store the entered password in encrypted way - biometricUnlockDatabaseHelper?.encryptData(passwordView?.text.toString()) - } - Mode.OPEN -> { - // retrieve the encrypted value from preferences - cipherDatabaseAction.getCipherDatabase(databaseFileUri) { - it?.encryptedValue?.let { value -> - biometricUnlockDatabaseHelper?.decryptData(value) + context.runOnUiThread { + when (biometricMode) { + Mode.UNAVAILABLE -> { + } + Mode.PAUSE -> { + } + Mode.NOT_CONFIGURED -> { + } + Mode.WAIT_CREDENTIAL -> { + } + Mode.STORE -> { + // newly store the entered password in encrypted way + biometricUnlockDatabaseHelper?.encryptData(passwordView?.text.toString()) + } + Mode.OPEN -> { + // retrieve the encrypted value from preferences + cipherDatabaseAction.getCipherDatabase(databaseFileUri) { + it?.encryptedValue?.let { value -> + biometricUnlockDatabaseHelper?.decryptData(value) + } } } } diff --git a/app/src/main/java/com/kunzisoft/keepass/database/action/ProgressDialogThread.kt b/app/src/main/java/com/kunzisoft/keepass/database/action/ProgressDialogThread.kt index 147ce8c43..72139ee96 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/action/ProgressDialogThread.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/action/ProgressDialogThread.kt @@ -9,6 +9,7 @@ import android.os.Bundle import android.os.IBinder import androidx.fragment.app.FragmentActivity import com.kunzisoft.keepass.R +import com.kunzisoft.keepass.app.database.CipherDatabaseEntity import com.kunzisoft.keepass.database.element.* import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_ASSIGN_PASSWORD_TASK @@ -49,20 +50,7 @@ class ProgressDialogThread(private val activity: FragmentActivity, private var databaseTaskBroadcastReceiver: BroadcastReceiver? = null private var mBinder: DatabaseTaskNotificationService.ActionTaskBinder? = null - private var serviceConnection = object: ServiceConnection { - - override fun onServiceConnected(name: ComponentName?, serviceBinder: IBinder?) { - mBinder = (serviceBinder as DatabaseTaskNotificationService.ActionTaskBinder).apply { - addActionTaskListener(actionTaskListener) - getService().checkAction() - } - } - - override fun onServiceDisconnected(name: ComponentName?) { - mBinder?.removeActionTaskListener(actionTaskListener) - mBinder = null - } - } + private var serviceConnection: ServiceConnection? = null private val actionTaskListener = object: DatabaseTaskNotificationService.ActionTaskListener { override fun onStartAction(titleId: Int?, messageId: Int?, warningId: Int?) { @@ -101,7 +89,38 @@ class ProgressDialogThread(private val activity: FragmentActivity, TimeoutHelper.releaseTemporarilyDisableTimeoutAndLockIfTimeout(activity) } + private fun bindService() { + serviceConnection?.let { + activity.bindService(intentDatabaseTask, it, BIND_NOT_FOREGROUND or BIND_ABOVE_CLIENT) + } + } + + /** + * Unbind the service and assign null to the service connection to check if already unbind or not + */ + private fun unBindService() { + serviceConnection?.let { + activity.unbindService(it) + } + serviceConnection = null + } + fun registerProgressTask() { + + serviceConnection = object: ServiceConnection { + override fun onServiceConnected(name: ComponentName?, serviceBinder: IBinder?) { + mBinder = (serviceBinder as DatabaseTaskNotificationService.ActionTaskBinder).apply { + addActionTaskListener(actionTaskListener) + getService().checkAction() + } + } + + override fun onServiceDisconnected(name: ComponentName?) { + mBinder?.removeActionTaskListener(actionTaskListener) + mBinder = null + } + } + // Register a database task receiver to stop loading dialog when service finish the task databaseTaskBroadcastReceiver = object : BroadcastReceiver() { override fun onReceive(context: Context?, intent: Intent?) { @@ -116,10 +135,10 @@ class ProgressDialogThread(private val activity: FragmentActivity, startDialog(title, message, warning) // Bind to the service when is starting - activity.bindService(intentDatabaseTask, serviceConnection, BIND_NOT_FOREGROUND or BIND_ABOVE_CLIENT) + bindService() } DATABASE_STOP_TASK_ACTION -> { - activity.unbindService(serviceConnection) + unBindService() stopDialog() } @@ -135,14 +154,14 @@ class ProgressDialogThread(private val activity: FragmentActivity, ) // Check if a service is currently running else do nothing - activity.bindService(intentDatabaseTask, serviceConnection, BIND_NOT_FOREGROUND or BIND_ABOVE_CLIENT) + bindService() } fun unregisterProgressTask() { mBinder?.removeActionTaskListener(actionTaskListener) mBinder = null - activity.unbindService(serviceConnection) + unBindService() activity.unregisterReceiver(databaseTaskBroadcastReceiver) } @@ -183,6 +202,7 @@ class ProgressDialogThread(private val activity: FragmentActivity, fun startDatabaseLoad(databaseUri: Uri, masterPassword: String?, keyFile: Uri?, + cipherEntity: CipherDatabaseEntity?, filesDir: File, omitBackup: Boolean, fixDuplicateUuid: Boolean) { @@ -190,6 +210,7 @@ class ProgressDialogThread(private val activity: FragmentActivity, 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) diff --git a/app/src/main/java/com/kunzisoft/keepass/notifications/DatabaseTaskNotificationService.kt b/app/src/main/java/com/kunzisoft/keepass/notifications/DatabaseTaskNotificationService.kt index d0da59e1f..604f9068a 100644 --- a/app/src/main/java/com/kunzisoft/keepass/notifications/DatabaseTaskNotificationService.kt +++ b/app/src/main/java/com/kunzisoft/keepass/notifications/DatabaseTaskNotificationService.kt @@ -8,6 +8,7 @@ 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 @@ -228,6 +229,7 @@ class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdat if (intent.hasExtra(DATABASE_URI_KEY) && 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) @@ -235,6 +237,7 @@ class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdat 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(), @@ -252,6 +255,7 @@ class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdat putParcelable(DATABASE_URI_KEY, databaseUri) putString(MASTER_PASSWORD_KEY, masterPassword) putParcelable(KEY_FILE_KEY, keyFileUri) + putParcelable(CIPHER_ENTITY_KEY, cipherEntity) } } }) @@ -477,6 +481,7 @@ class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdat const val MASTER_PASSWORD_KEY = "MASTER_PASSWORD_KEY" 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" From 6a5263df771a83d0da70b60958694678bb86043b Mon Sep 17 00:00:00 2001 From: J-Jamet Date: Thu, 17 Oct 2019 10:28:24 +0200 Subject: [PATCH 10/16] Fix biometric recognition error with new loading process --- .../keepass/biometric/AdvancedUnlockedManager.kt | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/kunzisoft/keepass/biometric/AdvancedUnlockedManager.kt b/app/src/main/java/com/kunzisoft/keepass/biometric/AdvancedUnlockedManager.kt index 784a7d7b1..ba97ab845 100644 --- a/app/src/main/java/com/kunzisoft/keepass/biometric/AdvancedUnlockedManager.kt +++ b/app/src/main/java/com/kunzisoft/keepass/biometric/AdvancedUnlockedManager.kt @@ -111,13 +111,17 @@ class AdvancedUnlockedManager(var context: FragmentActivity, override fun onAuthenticationError( errorCode: Int, errString: CharSequence) { - Log.e(TAG, "Biometric authentication error. Code : $errorCode Error : $errString") - setAdvancedUnlockedMessageView(errString.toString()) + context.runOnUiThread { + Log.e(TAG, "Biometric authentication error. Code : $errorCode Error : $errString") + setAdvancedUnlockedMessageView(errString.toString()) + } } override fun onAuthenticationFailed() { - Log.e(TAG, "Biometric authentication failed, biometric not recognized") - setAdvancedUnlockedMessageView(R.string.biometric_not_recognized) + context.runOnUiThread { + Log.e(TAG, "Biometric authentication failed, biometric not recognized") + setAdvancedUnlockedMessageView(R.string.biometric_not_recognized) + } } override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) { From b25180c6170d6e7fda7e94ec6cfa9118b7c0be3b Mon Sep 17 00:00:00 2001 From: J-Jamet Date: Thu, 17 Oct 2019 11:29:30 +0200 Subject: [PATCH 11/16] Show update message and fix dialog retrievment --- .../database/action/ProgressDialogThread.kt | 88 ++++++++----------- .../DatabaseTaskNotificationService.kt | 5 +- .../tasks/ProgressTaskDialogFragment.kt | 27 +----- 3 files changed, 46 insertions(+), 74 deletions(-) diff --git a/app/src/main/java/com/kunzisoft/keepass/database/action/ProgressDialogThread.kt b/app/src/main/java/com/kunzisoft/keepass/database/action/ProgressDialogThread.kt index 72139ee96..adcc20305 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/action/ProgressDialogThread.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/action/ProgressDialogThread.kt @@ -8,7 +8,6 @@ import android.os.Build import android.os.Bundle import android.os.IBinder import androidx.fragment.app.FragmentActivity -import com.kunzisoft.keepass.R import com.kunzisoft.keepass.app.database.CipherDatabaseEntity import com.kunzisoft.keepass.database.element.* import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService @@ -23,13 +22,9 @@ import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Compa import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_SAVE_TASK import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_UPDATE_ENTRY_TASK import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_UPDATE_GROUP_TASK -import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.DATABASE_TASK_MESSAGE_KEY -import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.DATABASE_TASK_TITLE_KEY -import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.DATABASE_TASK_WARNING_KEY import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.getBundleFromListNodes import com.kunzisoft.keepass.tasks.ActionRunnable import com.kunzisoft.keepass.tasks.ProgressTaskDialogFragment -import com.kunzisoft.keepass.tasks.ProgressTaskDialogFragment.Companion.UNDEFINED import com.kunzisoft.keepass.tasks.ProgressTaskDialogFragment.Companion.retrieveProgressDialog import com.kunzisoft.keepass.timeout.TimeoutHelper import com.kunzisoft.keepass.utils.DATABASE_START_TASK_ACTION @@ -45,8 +40,6 @@ class ProgressDialogThread(private val activity: FragmentActivity, private var intentDatabaseTask = Intent(activity, DatabaseTaskNotificationService::class.java) - private var mProgressTaskDialogFragment: ProgressTaskDialogFragment? = null - private var databaseTaskBroadcastReceiver: BroadcastReceiver? = null private var mBinder: DatabaseTaskNotificationService.ActionTaskBinder? = null @@ -54,42 +47,62 @@ class ProgressDialogThread(private val activity: FragmentActivity, private val actionTaskListener = object: DatabaseTaskNotificationService.ActionTaskListener { override fun onStartAction(titleId: Int?, messageId: Int?, warningId: Int?) { - // startDialog(titleId, messageId, warningId) + TimeoutHelper.temporarilyDisableTimeout() + startOrUpdateDialog(titleId, messageId, warningId) } override fun onUpdateAction(titleId: Int?, messageId: Int?, warningId: Int?) { - retrieveProgressDialog(activity)?.let { - ProgressTaskDialogFragment.update(it, titleId, messageId, warningId) - } + TimeoutHelper.temporarilyDisableTimeout() + startOrUpdateDialog(titleId, messageId, warningId) } override fun onStopAction(actionTask: String, result: ActionRunnable.Result) { onActionFinish.invoke(actionTask, result) - stopDialog() + // Remove the progress task + ProgressTaskDialogFragment.stop(activity) + TimeoutHelper.releaseTemporarilyDisableTimeoutAndLockIfTimeout(activity) } } - private fun startDialog(titleId: Int?, messageId: Int?, warningId: Int?) { - TimeoutHelper.temporarilyDisableTimeout() - - // Show the dialog - mProgressTaskDialogFragment = retrieveProgressDialog(activity) - if (mProgressTaskDialogFragment == null) - mProgressTaskDialogFragment = ProgressTaskDialogFragment.build(titleId, messageId, warningId) - else { - ProgressTaskDialogFragment.update(mProgressTaskDialogFragment!!, titleId, messageId, warningId) + private fun startOrUpdateDialog(titleId: Int?, messageId: Int?, warningId: Int?) { + var progressTaskDialogFragment = retrieveProgressDialog(activity) + if (progressTaskDialogFragment == null) { + progressTaskDialogFragment = ProgressTaskDialogFragment.build() + ProgressTaskDialogFragment.start(activity, progressTaskDialogFragment) + } + progressTaskDialogFragment.apply { + titleId?.let { + updateTitle(it) + } + messageId?.let { + updateMessage(it) + } + warningId?.let { + updateWarning(it) + } } - ProgressTaskDialogFragment.start(activity, mProgressTaskDialogFragment!!) } - private fun stopDialog() { - // Remove the progress task - ProgressTaskDialogFragment.stop(activity) + private fun initServiceConnection() { + if (serviceConnection == null) { + serviceConnection = object : ServiceConnection { + override fun onServiceConnected(name: ComponentName?, serviceBinder: IBinder?) { + mBinder = (serviceBinder as DatabaseTaskNotificationService.ActionTaskBinder).apply { + addActionTaskListener(actionTaskListener) + getService().checkAction() + } + } - TimeoutHelper.releaseTemporarilyDisableTimeoutAndLockIfTimeout(activity) + override fun onServiceDisconnected(name: ComponentName?) { + mBinder?.removeActionTaskListener(actionTaskListener) + mBinder = null + } + } + } } private fun bindService() { + initServiceConnection() serviceConnection?.let { activity.bindService(intentDatabaseTask, it, BIND_NOT_FOREGROUND or BIND_ABOVE_CLIENT) } @@ -107,40 +120,17 @@ class ProgressDialogThread(private val activity: FragmentActivity, fun registerProgressTask() { - serviceConnection = object: ServiceConnection { - override fun onServiceConnected(name: ComponentName?, serviceBinder: IBinder?) { - mBinder = (serviceBinder as DatabaseTaskNotificationService.ActionTaskBinder).apply { - addActionTaskListener(actionTaskListener) - getService().checkAction() - } - } - - override fun onServiceDisconnected(name: ComponentName?) { - mBinder?.removeActionTaskListener(actionTaskListener) - mBinder = null - } - } - // Register a database task receiver to stop loading dialog when service finish the task databaseTaskBroadcastReceiver = object : BroadcastReceiver() { override fun onReceive(context: Context?, intent: Intent?) { - if (intent == null) - stopDialog() activity.runOnUiThread { when (intent?.action) { DATABASE_START_TASK_ACTION -> { - val title = intent.getIntExtra(DATABASE_TASK_TITLE_KEY, R.string.loading_database) - val message = intent.getIntExtra(DATABASE_TASK_MESSAGE_KEY, UNDEFINED) - val warning = intent.getIntExtra(DATABASE_TASK_WARNING_KEY, UNDEFINED) - startDialog(title, message, warning) - // Bind to the service when is starting bindService() } DATABASE_STOP_TASK_ACTION -> { unBindService() - - stopDialog() } } } diff --git a/app/src/main/java/com/kunzisoft/keepass/notifications/DatabaseTaskNotificationService.kt b/app/src/main/java/com/kunzisoft/keepass/notifications/DatabaseTaskNotificationService.kt index 604f9068a..fc6d20304 100644 --- a/app/src/main/java/com/kunzisoft/keepass/notifications/DatabaseTaskNotificationService.kt +++ b/app/src/main/java/com/kunzisoft/keepass/notifications/DatabaseTaskNotificationService.kt @@ -176,7 +176,10 @@ class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdat } override fun updateMessage(resId: Int) { - // TODO + mMessageId = resId + mActionTaskListeners.forEach { actionTaskListener -> + actionTaskListener.onUpdateAction(mTitleId, mMessageId, mWarningId) + } } private fun buildDatabaseCreateActionTask(intent: Intent): ActionRunnable? { diff --git a/app/src/main/java/com/kunzisoft/keepass/tasks/ProgressTaskDialogFragment.kt b/app/src/main/java/com/kunzisoft/keepass/tasks/ProgressTaskDialogFragment.kt index 17517a4c8..583ff7f71 100644 --- a/app/src/main/java/com/kunzisoft/keepass/tasks/ProgressTaskDialogFragment.kt +++ b/app/src/main/java/com/kunzisoft/keepass/tasks/ProgressTaskDialogFragment.kt @@ -110,13 +110,9 @@ open class ProgressTaskDialogFragment : DialogFragment(), ProgressTaskUpdater { const val UNDEFINED = -1 - fun build(@StringRes titleId: Int? = null, - @StringRes messageId: Int? = null, - @StringRes warningId: Int? = null): ProgressTaskDialogFragment { - // Create an instance of the dialog fragment and show it - val dialog = ProgressTaskDialogFragment() - update(dialog, titleId, messageId, warningId) - return dialog + fun build(): ProgressTaskDialogFragment { + // Create an instance of the dialog fragment + return ProgressTaskDialogFragment() } fun start(activity: FragmentActivity, @@ -134,22 +130,5 @@ open class ProgressTaskDialogFragment : DialogFragment(), ProgressTaskUpdater { fun stop(activity: FragmentActivity) { retrieveProgressDialog(activity)?.dismissAllowingStateLoss() } - - fun update(dialog: ProgressTaskDialogFragment, - titleId: Int?, - messageId: Int?, - warningId: Int?) { - dialog.apply { - titleId?.let { - updateTitle(it) - } - messageId?.let { - updateMessage(it) - } - warningId?.let { - updateWarning(it) - } - } - } } } From 214e2cf109585dbcf19300c39f506d43c9c87577 Mon Sep 17 00:00:00 2001 From: J-Jamet Date: Thu, 17 Oct 2019 14:07:39 +0200 Subject: [PATCH 12/16] Better database loading code --- .../keepass/activities/GroupActivity.kt | 27 +++--- .../keepass/activities/PasswordActivity.kt | 97 +++++-------------- .../helpers/EntrySelectionHelper.kt | 6 +- .../database/action/LoadDatabaseRunnable.kt | 42 ++++++-- .../database/action/ProgressDialogThread.kt | 6 +- .../magikeyboard/KeyboardLauncherActivity.kt | 2 +- .../DatabaseTaskNotificationService.kt | 15 ++- 7 files changed, 86 insertions(+), 109 deletions(-) diff --git a/app/src/main/java/com/kunzisoft/keepass/activities/GroupActivity.kt b/app/src/main/java/com/kunzisoft/keepass/activities/GroupActivity.kt index 0e345e0bb..c949cfdb1 100644 --- a/app/src/main/java/com/kunzisoft/keepass/activities/GroupActivity.kt +++ b/app/src/main/java/com/kunzisoft/keepass/activities/GroupActivity.kt @@ -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) } } diff --git a/app/src/main/java/com/kunzisoft/keepass/activities/PasswordActivity.kt b/app/src/main/java/com/kunzisoft/keepass/activities/PasswordActivity.kt index ce3a32baa..1811edb06 100644 --- a/app/src/main/java/com/kunzisoft/keepass/activities/PasswordActivity.kt +++ b/app/src/main/java/com/kunzisoft/keepass/activities/PasswordActivity.kt @@ -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 diff --git a/app/src/main/java/com/kunzisoft/keepass/activities/helpers/EntrySelectionHelper.kt b/app/src/main/java/com/kunzisoft/keepass/activities/helpers/EntrySelectionHelper.kt index e046223f6..dc04e3291 100644 --- a/app/src/main/java/com/kunzisoft/keepass/activities/helpers/EntrySelectionHelper.kt +++ b/app/src/main/java/com/kunzisoft/keepass/activities/helpers/EntrySelectionHelper.kt @@ -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) { diff --git a/app/src/main/java/com/kunzisoft/keepass/database/action/LoadDatabaseRunnable.kt b/app/src/main/java/com/kunzisoft/keepass/database/action/LoadDatabaseRunnable.kt index 805921b4f..3744e69f4 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/action/LoadDatabaseRunnable.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/action/LoadDatabaseRunnable.kt @@ -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) diff --git a/app/src/main/java/com/kunzisoft/keepass/database/action/ProgressDialogThread.kt b/app/src/main/java/com/kunzisoft/keepass/database/action/ProgressDialogThread.kt index adcc20305..396ff8dcf 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/action/ProgressDialogThread.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/action/ProgressDialogThread.kt @@ -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) diff --git a/app/src/main/java/com/kunzisoft/keepass/magikeyboard/KeyboardLauncherActivity.kt b/app/src/main/java/com/kunzisoft/keepass/magikeyboard/KeyboardLauncherActivity.kt index efe0269ee..2828960a2 100644 --- a/app/src/main/java/com/kunzisoft/keepass/magikeyboard/KeyboardLauncherActivity.kt +++ b/app/src/main/java/com/kunzisoft/keepass/magikeyboard/KeyboardLauncherActivity.kt @@ -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) diff --git a/app/src/main/java/com/kunzisoft/keepass/notifications/DatabaseTaskNotificationService.kt b/app/src/main/java/com/kunzisoft/keepass/notifications/DatabaseTaskNotificationService.kt index fc6d20304..bae368b05 100644 --- a/app/src/main/java/com/kunzisoft/keepass/notifications/DatabaseTaskNotificationService.kt +++ b/app/src/main/java/com/kunzisoft/keepass/notifications/DatabaseTaskNotificationService.kt @@ -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" From def9744f75539deefaa741c0debdcfcef4265743 Mon Sep 17 00:00:00 2001 From: J-Jamet Date: Thu, 17 Oct 2019 14:54:34 +0200 Subject: [PATCH 13/16] Fix launch group activity when database loaded --- .../activities/FileDatabaseSelectActivity.kt | 23 ++++++++++ .../keepass/activities/PasswordActivity.kt | 42 ++++++++++++------- .../database/action/LoadDatabaseRunnable.kt | 2 + .../database/action/ProgressDialogThread.kt | 6 ++- .../keepass/database/element/Database.kt | 3 +- .../DatabaseTaskNotificationService.kt | 5 +++ 6 files changed, 64 insertions(+), 17 deletions(-) diff --git a/app/src/main/java/com/kunzisoft/keepass/activities/FileDatabaseSelectActivity.kt b/app/src/main/java/com/kunzisoft/keepass/activities/FileDatabaseSelectActivity.kt index 9f7ee13f3..80ab902e2 100644 --- a/app/src/main/java/com/kunzisoft/keepass/activities/FileDatabaseSelectActivity.kt +++ b/app/src/main/java/com/kunzisoft/keepass/activities/FileDatabaseSelectActivity.kt @@ -50,6 +50,7 @@ import com.kunzisoft.keepass.adapters.FileDatabaseHistoryAdapter import com.kunzisoft.keepass.app.database.FileDatabaseHistoryAction import com.kunzisoft.keepass.autofill.AutofillHelper import com.kunzisoft.keepass.database.action.ProgressDialogThread +import com.kunzisoft.keepass.database.element.Database import com.kunzisoft.keepass.education.FileDatabaseSelectActivityEducation import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_CREATE_TASK import com.kunzisoft.keepass.utils.MenuUtil @@ -232,6 +233,23 @@ class FileDatabaseSelectActivity : StylishActivity(), }) } + private fun launchGroupActivity(readOnly: Boolean) { + EntrySelectionHelper.doEntrySelectionAction(intent, + { + GroupActivity.launch(this@FileDatabaseSelectActivity, readOnly) + }, + { + GroupActivity.launchForKeyboardSelection(this@FileDatabaseSelectActivity, readOnly) + // Do not keep history + finish() + }, + { assistStructure -> + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + GroupActivity.launchForAutofillResult(this@FileDatabaseSelectActivity, assistStructure, readOnly) + } + }) + } + private fun launchPasswordActivityWithPath(databaseUri: Uri) { launchPasswordActivity(databaseUri, null) // Delete flickering for kitkat <= @@ -259,6 +277,11 @@ class FileDatabaseSelectActivity : StylishActivity(), } override fun onResume() { + val database = Database.getInstance() + if (database.loaded) { + launchGroupActivity(database.isReadOnly) + } + super.onResume() updateExternalStorageWarning() diff --git a/app/src/main/java/com/kunzisoft/keepass/activities/PasswordActivity.kt b/app/src/main/java/com/kunzisoft/keepass/activities/PasswordActivity.kt index 1811edb06..9fddf4d24 100644 --- a/app/src/main/java/com/kunzisoft/keepass/activities/PasswordActivity.kt +++ b/app/src/main/java/com/kunzisoft/keepass/activities/PasswordActivity.kt @@ -66,6 +66,7 @@ import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Compa 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.notifications.DatabaseTaskNotificationService.Companion.READ_ONLY_KEY import com.kunzisoft.keepass.settings.PreferencesUtil import com.kunzisoft.keepass.utils.FileDatabaseInfo import com.kunzisoft.keepass.utils.MenuUtil @@ -177,12 +178,14 @@ class PasswordActivity : StylishActivity() { var databaseUri: Uri? = null var masterPassword: String? = null var keyFileUri: Uri? = null + var readOnly = true var cipherEntity: CipherDatabaseEntity? = null result.data?.let { resultData -> databaseUri = resultData.getParcelable(DATABASE_URI_KEY) masterPassword = resultData.getString(MASTER_PASSWORD_KEY) keyFileUri = resultData.getParcelable(KEY_FILE_KEY) + readOnly = resultData.getBoolean(READ_ONLY_KEY) cipherEntity = resultData.getParcelable(CIPHER_ENTITY_KEY) } @@ -191,20 +194,7 @@ class PasswordActivity : StylishActivity() { removePassword() if (result.isSuccess) { - 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) - } - }) + launchGroupActivity() } else { var resultError = "" val resultException = result.exception @@ -218,6 +208,7 @@ class PasswordActivity : StylishActivity() { databaseFileUri, masterPassword, keyFileUri, + readOnly, cipherEntity, true) } @@ -239,6 +230,23 @@ class PasswordActivity : StylishActivity() { } } + private fun launchGroupActivity() { + 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) + } + }) + } + private val onEditorActionListener = object : TextView.OnEditorActionListener { override fun onEditorAction(v: TextView?, actionId: Int, event: KeyEvent?): Boolean { if (actionId == IME_ACTION_DONE) { @@ -250,6 +258,9 @@ class PasswordActivity : StylishActivity() { } override fun onResume() { + if (Database.getInstance().loaded) + launchGroupActivity() + // If the database isn't accessible make sure to clear the password field, if it // was saved in the instance state if (Database.getInstance().loaded) { @@ -510,6 +521,7 @@ class PasswordActivity : StylishActivity() { databaseUri, password, keyFileUri, + readOnly, cipherDatabaseEntity, false) } @@ -518,12 +530,14 @@ class PasswordActivity : StylishActivity() { private fun showProgressDialogAndLoadDatabase(databaseUri: Uri, password: String?, keyFile: Uri?, + readOnly: Boolean, cipherDatabaseEntity: CipherDatabaseEntity?, fixDuplicateUUID: Boolean) { progressDialogThread?.startDatabaseLoad( databaseUri, password, keyFile, + readOnly, cipherDatabaseEntity, fixDuplicateUUID ) diff --git a/app/src/main/java/com/kunzisoft/keepass/database/action/LoadDatabaseRunnable.kt b/app/src/main/java/com/kunzisoft/keepass/database/action/LoadDatabaseRunnable.kt index 3744e69f4..2b77d73cd 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/action/LoadDatabaseRunnable.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/action/LoadDatabaseRunnable.kt @@ -35,6 +35,7 @@ class LoadDatabaseRunnable(private val context: Context, private val mUri: Uri, private val mPass: String?, private val mKey: Uri?, + private val mReadonly: Boolean, private val mCipherEntity: CipherDatabaseEntity?, private val mOmitBackup: Boolean, private val mFixDuplicateUUID: Boolean, @@ -50,6 +51,7 @@ class LoadDatabaseRunnable(private val context: Context, mDatabase.closeAndClear(cacheDirectory) mDatabase.loadData(mUri, mPass, mKey, + mReadonly, context.contentResolver, cacheDirectory, mOmitBackup, diff --git a/app/src/main/java/com/kunzisoft/keepass/database/action/ProgressDialogThread.kt b/app/src/main/java/com/kunzisoft/keepass/database/action/ProgressDialogThread.kt index 396ff8dcf..89d8d7cb6 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/action/ProgressDialogThread.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/action/ProgressDialogThread.kt @@ -118,8 +118,6 @@ 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() { override fun onReceive(context: Context?, intent: Intent?) { @@ -148,6 +146,8 @@ class ProgressDialogThread(private val activity: FragmentActivity, } fun unregisterProgressTask() { + ProgressTaskDialogFragment.stop(activity) + mBinder?.removeActionTaskListener(actionTaskListener) mBinder = null @@ -192,12 +192,14 @@ class ProgressDialogThread(private val activity: FragmentActivity, fun startDatabaseLoad(databaseUri: Uri, masterPassword: String?, keyFile: Uri?, + readOnly: Boolean, cipherEntity: CipherDatabaseEntity?, fixDuplicateUuid: Boolean) { start(Bundle().apply { putParcelable(DatabaseTaskNotificationService.DATABASE_URI_KEY, databaseUri) putString(DatabaseTaskNotificationService.MASTER_PASSWORD_KEY, masterPassword) putParcelable(DatabaseTaskNotificationService.KEY_FILE_KEY, keyFile) + putBoolean(DatabaseTaskNotificationService.READ_ONLY_KEY, readOnly) putParcelable(DatabaseTaskNotificationService.CIPHER_ENTITY_KEY, cipherEntity) putBoolean(DatabaseTaskNotificationService.FIX_DUPLICATE_UUID_KEY, fixDuplicateUuid) } diff --git a/app/src/main/java/com/kunzisoft/keepass/database/element/Database.kt b/app/src/main/java/com/kunzisoft/keepass/database/element/Database.kt index 7645b7f14..eb483a2be 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/element/Database.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/element/Database.kt @@ -288,6 +288,7 @@ class Database { @Throws(LoadDatabaseException::class) fun loadData(uri: Uri, password: String?, keyfile: Uri?, + readOnly: Boolean, contentResolver: ContentResolver, cacheDirectory: File, omitBackup: Boolean, @@ -295,7 +296,7 @@ class Database { progressTaskUpdater: ProgressTaskUpdater?) { mUri = uri - isReadOnly = false + isReadOnly = readOnly if (uri.scheme == "file") { val file = File(uri.path!!) isReadOnly = !file.canWrite() diff --git a/app/src/main/java/com/kunzisoft/keepass/notifications/DatabaseTaskNotificationService.kt b/app/src/main/java/com/kunzisoft/keepass/notifications/DatabaseTaskNotificationService.kt index bae368b05..c3ac2cdbd 100644 --- a/app/src/main/java/com/kunzisoft/keepass/notifications/DatabaseTaskNotificationService.kt +++ b/app/src/main/java/com/kunzisoft/keepass/notifications/DatabaseTaskNotificationService.kt @@ -232,6 +232,7 @@ class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdat if (intent.hasExtra(DATABASE_URI_KEY) && intent.hasExtra(MASTER_PASSWORD_KEY) && intent.hasExtra(KEY_FILE_KEY) + && intent.hasExtra(READ_ONLY_KEY) && intent.hasExtra(CIPHER_ENTITY_KEY) && intent.hasExtra(FIX_DUPLICATE_UUID_KEY) ) { @@ -239,6 +240,7 @@ class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdat 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 readOnly: Boolean = intent.getBooleanExtra(READ_ONLY_KEY, true) val cipherEntity: CipherDatabaseEntity? = intent.getParcelableExtra(CIPHER_ENTITY_KEY) return LoadDatabaseRunnable( @@ -247,6 +249,7 @@ class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdat databaseUri, masterPassword, keyFileUri, + readOnly, cipherEntity, PreferencesUtil.omitBackup(this), intent.getBooleanExtra(FIX_DUPLICATE_UUID_KEY, false), @@ -257,6 +260,7 @@ class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdat putParcelable(DATABASE_URI_KEY, databaseUri) putString(MASTER_PASSWORD_KEY, masterPassword) putParcelable(KEY_FILE_KEY, keyFileUri) + putBoolean(READ_ONLY_KEY, readOnly) putParcelable(CIPHER_ENTITY_KEY, cipherEntity) } } @@ -483,6 +487,7 @@ class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdat const val MASTER_PASSWORD_KEY = "MASTER_PASSWORD_KEY" const val KEY_FILE_CHECKED_KEY = "KEY_FILE_CHECKED_KEY" const val KEY_FILE_KEY = "KEY_FILE_KEY" + const val READ_ONLY_KEY = "READ_ONLY_KEY" const val CIPHER_ENTITY_KEY = "CIPHER_ENTITY_KEY" const val FIX_DUPLICATE_UUID_KEY = "FIX_DUPLICATE_UUID_KEY" const val GROUP_KEY = "GROUP_KEY" From d1d2b99e0959d4b1ad2f299bfdf654ec6a711ed9 Mon Sep 17 00:00:00 2001 From: J-Jamet Date: Thu, 17 Oct 2019 15:17:18 +0200 Subject: [PATCH 14/16] Fix autofill selection --- .../main/java/com/kunzisoft/keepass/activities/GroupActivity.kt | 1 - .../kunzisoft/keepass/database/action/ProgressDialogThread.kt | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/kunzisoft/keepass/activities/GroupActivity.kt b/app/src/main/java/com/kunzisoft/keepass/activities/GroupActivity.kt index c949cfdb1..033cc6a0e 100644 --- a/app/src/main/java/com/kunzisoft/keepass/activities/GroupActivity.kt +++ b/app/src/main/java/com/kunzisoft/keepass/activities/GroupActivity.kt @@ -889,7 +889,6 @@ class GroupActivity : LockingActivity(), if (group != null) { intent.putExtra(GROUP_ID_KEY, group.nodeId) } - intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK ReadOnlyHelper.putReadOnlyInIntent(intent, readOnly) intentBuildLauncher.invoke(intent) } diff --git a/app/src/main/java/com/kunzisoft/keepass/database/action/ProgressDialogThread.kt b/app/src/main/java/com/kunzisoft/keepass/database/action/ProgressDialogThread.kt index 89d8d7cb6..4c5ed8cf6 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/action/ProgressDialogThread.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/action/ProgressDialogThread.kt @@ -118,6 +118,8 @@ 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() { override fun onReceive(context: Context?, intent: Intent?) { From 2e58c2f1b34fbcd2a36e3592c46353022eb06320 Mon Sep 17 00:00:00 2001 From: J-Jamet Date: Thu, 17 Oct 2019 20:02:49 +0200 Subject: [PATCH 15/16] Fix duplication during deletion --- .../keepass/database/element/PwGroup.kt | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/app/src/main/java/com/kunzisoft/keepass/database/element/PwGroup.kt b/app/src/main/java/com/kunzisoft/keepass/database/element/PwGroup.kt index dbbbca61a..50d94dca0 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/element/PwGroup.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/element/PwGroup.kt @@ -13,9 +13,9 @@ abstract class PwGroup private var titleGroup = "" @Transient - private val childGroups = LinkedHashMap, Group>() + private val childGroups = ArrayList() @Transient - private val childEntries = LinkedHashMap, Entry>() + private val childEntries = ArrayList() constructor() : super() @@ -32,9 +32,9 @@ abstract class PwGroup super.updateWith(source) titleGroup = source.titleGroup childGroups.clear() - childGroups.putAll(source.childGroups) + childGroups.addAll(source.childGroups) childEntries.clear() - childEntries.putAll(source.childEntries) + childEntries.addAll(source.childEntries) } override var title: String @@ -42,27 +42,31 @@ abstract class PwGroup set(value) { titleGroup = value } override fun getChildGroups(): MutableList { - return childGroups.values.toMutableList() + return childGroups } override fun getChildEntries(): MutableList { - return childEntries.values.toMutableList() + return childEntries } override fun addChildGroup(group: Group) { - this.childGroups[group.nodeId] = group + if (childGroups.contains(group)) + removeChildGroup(group) + this.childGroups.add(group) } override fun addChildEntry(entry: Entry) { - this.childEntries[entry.nodeId] = entry + if (childEntries.contains(entry)) + removeChildEntry(entry) + this.childEntries.add(entry) } override fun removeChildGroup(group: Group) { - this.childGroups.remove(group.nodeId) + this.childGroups.remove(group) } override fun removeChildEntry(entry: Entry) { - this.childEntries.remove(entry.nodeId) + this.childEntries.remove(entry) } override fun toString(): String { From 9d160db281ff9a22ab1e381d6780a7460f737a04 Mon Sep 17 00:00:00 2001 From: J-Jamet Date: Fri, 18 Oct 2019 13:44:28 +0200 Subject: [PATCH 16/16] Add setting updates for dialog thread --- .../keepass/crypto/keyDerivation/KdfEngine.kt | 4 +- .../database/action/ProgressDialogThread.kt | 150 ++++++++++- .../DatabaseTaskNotificationService.kt | 148 ++++++----- .../settings/NestedSettingsFragment.kt | 245 ++++++++++++++++-- .../keepass/settings/SettingsActivity.kt | 29 +-- ...baseColorPreferenceDialogFragmentCompat.kt | 28 +- ...mpressionPreferenceDialogFragmentCompat.kt | 29 +-- ...tUsernamePreferenceDialogFragmentCompat.kt | 21 +- ...scriptionPreferenceDialogFragmentCompat.kt | 21 +- ...AlgorithmPreferenceDialogFragmentCompat.kt | 21 +- ...erivationPreferenceDialogFragmentCompat.kt | 26 +- ...abaseNamePreferenceDialogFragmentCompat.kt | 21 +- ...abaseSavePreferenceDialogFragmentCompat.kt | 37 +-- ...toryItemsPreferenceDialogFragmentCompat.kt | 21 +- ...storySizePreferenceDialogFragmentCompat.kt | 21 +- ...moryUsagePreferenceDialogFragmentCompat.kt | 21 +- ...rallelismPreferenceDialogFragmentCompat.kt | 21 +- .../RoundsPreferenceDialogFragmentCompat.kt | 20 +- 18 files changed, 492 insertions(+), 392 deletions(-) diff --git a/app/src/main/java/com/kunzisoft/keepass/crypto/keyDerivation/KdfEngine.kt b/app/src/main/java/com/kunzisoft/keepass/crypto/keyDerivation/KdfEngine.kt index b2ec56f42..29e7124f5 100644 --- a/app/src/main/java/com/kunzisoft/keepass/crypto/keyDerivation/KdfEngine.kt +++ b/app/src/main/java/com/kunzisoft/keepass/crypto/keyDerivation/KdfEngine.kt @@ -22,9 +22,11 @@ package com.kunzisoft.keepass.crypto.keyDerivation import com.kunzisoft.keepass.database.ObjectNameResource import java.io.IOException +import java.io.Serializable import java.util.UUID -abstract class KdfEngine : ObjectNameResource { +// TODO Parcelable +abstract class KdfEngine : ObjectNameResource, Serializable { var uuid: UUID? = null diff --git a/app/src/main/java/com/kunzisoft/keepass/database/action/ProgressDialogThread.kt b/app/src/main/java/com/kunzisoft/keepass/database/action/ProgressDialogThread.kt index 4c5ed8cf6..7bac595c2 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/action/ProgressDialogThread.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/action/ProgressDialogThread.kt @@ -9,6 +9,7 @@ import android.os.Bundle import android.os.IBinder import androidx.fragment.app.FragmentActivity import com.kunzisoft.keepass.app.database.CipherDatabaseEntity +import com.kunzisoft.keepass.crypto.keyDerivation.KdfEngine import com.kunzisoft.keepass.database.element.* import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_ASSIGN_PASSWORD_TASK @@ -19,7 +20,18 @@ import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Compa import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_DELETE_NODES_TASK import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_LOAD_TASK import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_MOVE_NODES_TASK -import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_SAVE_TASK +import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_SAVE_COLOR_TASK +import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_SAVE_COMPRESSION_TASK +import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_SAVE_DEFAULT_USERNAME_TASK +import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_SAVE_DESCRIPTION_TASK +import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_SAVE_ENCRYPTION_TASK +import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_SAVE_ITERATIONS_TASK +import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_SAVE_KEY_DERIVATION_TASK +import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_SAVE_MAX_HISTORY_ITEMS_TASK +import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_SAVE_MAX_HISTORY_SIZE_TASK +import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_SAVE_MEMORY_USAGE_TASK +import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_SAVE_NAME_TASK +import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_SAVE_PARALLELISM_TASK import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_UPDATE_ENTRY_TASK import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_UPDATE_GROUP_TASK import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.getBundleFromListNodes @@ -172,6 +184,12 @@ class ProgressDialogThread(private val activity: FragmentActivity, } } + /* + ---- + Main methods + ---- + */ + fun startDatabaseCreate(databaseUri: Uri, masterPasswordChecked: Boolean, masterPassword: String?, @@ -187,10 +205,6 @@ class ProgressDialogThread(private val activity: FragmentActivity, , ACTION_DATABASE_CREATE_TASK) } - fun startDatabaseSave() { - start(null, ACTION_DATABASE_SAVE_TASK) - } - fun startDatabaseLoad(databaseUri: Uri, masterPassword: String?, keyFile: Uri?, @@ -222,6 +236,12 @@ class ProgressDialogThread(private val activity: FragmentActivity, , ACTION_DATABASE_ASSIGN_PASSWORD_TASK) } + /* + ---- + Nodes Actions + ---- + */ + fun startDatabaseCreateGroup(newGroup: GroupVersioned, parent: GroupVersioned, save: Boolean) { @@ -313,4 +333,124 @@ class ProgressDialogThread(private val activity: FragmentActivity, save: Boolean) { startDatabaseActionListNodes(ACTION_DATABASE_DELETE_NODES_TASK, nodesToDelete, null, save) } + + /* + ----------------- + Main Settings + ----------------- + */ + + fun startDatabaseSaveName(oldName: String, + newName: String) { + start(Bundle().apply { + putString(DatabaseTaskNotificationService.OLD_ELEMENT_KEY, oldName) + putString(DatabaseTaskNotificationService.NEW_ELEMENT_KEY, newName) + } + , ACTION_DATABASE_SAVE_NAME_TASK) + } + + fun startDatabaseSaveDescription(oldDescription: String, + newDescription: String) { + start(Bundle().apply { + putString(DatabaseTaskNotificationService.OLD_ELEMENT_KEY, oldDescription) + putString(DatabaseTaskNotificationService.NEW_ELEMENT_KEY, newDescription) + } + , ACTION_DATABASE_SAVE_DESCRIPTION_TASK) + } + + fun startDatabaseSaveDefaultUsername(oldDefaultUsername: String, + newDefaultUsername: String) { + start(Bundle().apply { + putString(DatabaseTaskNotificationService.OLD_ELEMENT_KEY, oldDefaultUsername) + putString(DatabaseTaskNotificationService.NEW_ELEMENT_KEY, newDefaultUsername) + } + , ACTION_DATABASE_SAVE_DEFAULT_USERNAME_TASK) + } + + fun startDatabaseSaveColor(oldColor: String, + newColor: String) { + start(Bundle().apply { + putString(DatabaseTaskNotificationService.OLD_ELEMENT_KEY, oldColor) + putString(DatabaseTaskNotificationService.NEW_ELEMENT_KEY, newColor) + } + , ACTION_DATABASE_SAVE_COLOR_TASK) + } + + fun startDatabaseSaveCompression(oldCompression: PwCompressionAlgorithm, + newCompression: PwCompressionAlgorithm) { + start(Bundle().apply { + putSerializable(DatabaseTaskNotificationService.OLD_ELEMENT_KEY, oldCompression) + putSerializable(DatabaseTaskNotificationService.NEW_ELEMENT_KEY, newCompression) + } + , ACTION_DATABASE_SAVE_COMPRESSION_TASK) + } + + fun startDatabaseSaveMaxHistoryItems(oldMaxHistoryItems: Int, + newMaxHistoryItems: Int) { + start(Bundle().apply { + putInt(DatabaseTaskNotificationService.OLD_ELEMENT_KEY, oldMaxHistoryItems) + putInt(DatabaseTaskNotificationService.NEW_ELEMENT_KEY, newMaxHistoryItems) + } + , ACTION_DATABASE_SAVE_MAX_HISTORY_ITEMS_TASK) + } + + fun startDatabaseSaveMaxHistorySize(oldMaxHistorySize: Long, + newMaxHistorySize: Long) { + start(Bundle().apply { + putLong(DatabaseTaskNotificationService.OLD_ELEMENT_KEY, oldMaxHistorySize) + putLong(DatabaseTaskNotificationService.NEW_ELEMENT_KEY, newMaxHistorySize) + } + , ACTION_DATABASE_SAVE_MAX_HISTORY_SIZE_TASK) + } + + /* + ------------------- + Security Settings + ------------------- + */ + + fun startDatabaseSaveEncryption(oldEncryption: PwEncryptionAlgorithm, + newEncryption: PwEncryptionAlgorithm) { + start(Bundle().apply { + putSerializable(DatabaseTaskNotificationService.OLD_ELEMENT_KEY, oldEncryption) + putSerializable(DatabaseTaskNotificationService.NEW_ELEMENT_KEY, newEncryption) + } + , ACTION_DATABASE_SAVE_ENCRYPTION_TASK) + } + + fun startDatabaseSaveKeyDerivation(oldKeyDerivation: KdfEngine, + newKeyDerivation: KdfEngine) { + start(Bundle().apply { + putSerializable(DatabaseTaskNotificationService.OLD_ELEMENT_KEY, oldKeyDerivation) + putSerializable(DatabaseTaskNotificationService.NEW_ELEMENT_KEY, newKeyDerivation) + } + , ACTION_DATABASE_SAVE_KEY_DERIVATION_TASK) + } + + fun startDatabaseSaveIterations(oldIterations: Long, + newIterations: Long) { + start(Bundle().apply { + putLong(DatabaseTaskNotificationService.OLD_ELEMENT_KEY, oldIterations) + putLong(DatabaseTaskNotificationService.NEW_ELEMENT_KEY, newIterations) + } + , ACTION_DATABASE_SAVE_ITERATIONS_TASK) + } + + fun startDatabaseSaveMemoryUsage(oldMemoryUsage: Long, + newMemoryUsage: Long) { + start(Bundle().apply { + putLong(DatabaseTaskNotificationService.OLD_ELEMENT_KEY, oldMemoryUsage) + putLong(DatabaseTaskNotificationService.NEW_ELEMENT_KEY, newMemoryUsage) + } + , ACTION_DATABASE_SAVE_MEMORY_USAGE_TASK) + } + + fun startDatabaseSaveParallelism(oldParallelism: Int, + newParallelism: Int) { + start(Bundle().apply { + putInt(DatabaseTaskNotificationService.OLD_ELEMENT_KEY, oldParallelism) + putInt(DatabaseTaskNotificationService.NEW_ELEMENT_KEY, newParallelism) + } + , ACTION_DATABASE_SAVE_PARALLELISM_TASK) + } } \ No newline at end of file diff --git a/app/src/main/java/com/kunzisoft/keepass/notifications/DatabaseTaskNotificationService.kt b/app/src/main/java/com/kunzisoft/keepass/notifications/DatabaseTaskNotificationService.kt index c3ac2cdbd..e5f6efe51 100644 --- a/app/src/main/java/com/kunzisoft/keepass/notifications/DatabaseTaskNotificationService.kt +++ b/app/src/main/java/com/kunzisoft/keepass/notifications/DatabaseTaskNotificationService.kt @@ -74,17 +74,8 @@ class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdat val titleId: Int = when (intentAction) { ACTION_DATABASE_CREATE_TASK -> R.string.creating_database - ACTION_DATABASE_SAVE_TASK, - ACTION_DATABASE_ASSIGN_PASSWORD_TASK, - ACTION_DATABASE_CREATE_GROUP_TASK, - ACTION_DATABASE_UPDATE_GROUP_TASK, - ACTION_DATABASE_CREATE_ENTRY_TASK, - ACTION_DATABASE_UPDATE_ENTRY_TASK, - ACTION_DATABASE_COPY_NODES_TASK, - ACTION_DATABASE_MOVE_NODES_TASK, - ACTION_DATABASE_DELETE_NODES_TASK -> R.string.saving_database ACTION_DATABASE_LOAD_TASK -> R.string.loading_database - else -> R.string.loading_database + else -> R.string.saving_database } val messageId: Int? = when (intentAction) { ACTION_DATABASE_LOAD_TASK -> null @@ -98,7 +89,6 @@ class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdat val actionRunnable: ActionRunnable? = when (intentAction) { ACTION_DATABASE_CREATE_TASK -> buildDatabaseCreateActionTask(intent) - ACTION_DATABASE_SAVE_TASK -> buildDatabaseSaveActionTask() ACTION_DATABASE_LOAD_TASK -> buildDatabaseLoadActionTask(intent) ACTION_DATABASE_ASSIGN_PASSWORD_TASK -> buildDatabaseAssignPasswordActionTask(intent) ACTION_DATABASE_CREATE_GROUP_TASK -> buildDatabaseCreateGroupActionTask(intent) @@ -108,58 +98,54 @@ class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdat ACTION_DATABASE_COPY_NODES_TASK -> buildDatabaseCopyNodesActionTask(intent) ACTION_DATABASE_MOVE_NODES_TASK -> buildDatabaseMoveNodesActionTask(intent) ACTION_DATABASE_DELETE_NODES_TASK -> buildDatabaseDeleteNodesActionTask(intent) + ACTION_DATABASE_SAVE_NAME_TASK, + ACTION_DATABASE_SAVE_DESCRIPTION_TASK, + ACTION_DATABASE_SAVE_DEFAULT_USERNAME_TASK, + ACTION_DATABASE_SAVE_COLOR_TASK, + ACTION_DATABASE_SAVE_COMPRESSION_TASK, + ACTION_DATABASE_SAVE_MAX_HISTORY_ITEMS_TASK, + ACTION_DATABASE_SAVE_MAX_HISTORY_SIZE_TASK, + ACTION_DATABASE_SAVE_ENCRYPTION_TASK, + ACTION_DATABASE_SAVE_KEY_DERIVATION_TASK, + ACTION_DATABASE_SAVE_MEMORY_USAGE_TASK, + ACTION_DATABASE_SAVE_PARALLELISM_TASK, + ACTION_DATABASE_SAVE_ITERATIONS_TASK -> buildDatabaseSaveElementActionTask(intent) else -> null } - when (intentAction) { - ACTION_DATABASE_CREATE_TASK, - ACTION_DATABASE_SAVE_TASK, - ACTION_DATABASE_LOAD_TASK, - ACTION_DATABASE_ASSIGN_PASSWORD_TASK, - ACTION_DATABASE_CREATE_GROUP_TASK, - ACTION_DATABASE_UPDATE_GROUP_TASK, - ACTION_DATABASE_CREATE_ENTRY_TASK, - ACTION_DATABASE_UPDATE_ENTRY_TASK, - ACTION_DATABASE_COPY_NODES_TASK, - ACTION_DATABASE_MOVE_NODES_TASK, - ACTION_DATABASE_DELETE_NODES_TASK -> { + actionRunnable?.let { actionRunnableNotNull -> + // Assign elements for updates + mTitleId = titleId + mMessageId = messageId + mWarningId = warningId - // Assign elements for updates - mTitleId = titleId - mMessageId = messageId - mWarningId = warningId + // Create the notification + newNotification(intent.getIntExtra(DATABASE_TASK_TITLE_KEY, titleId)) - // Create the notification - newNotification(intent.getIntExtra(DATABASE_TASK_TITLE_KEY, titleId)) + // Build and launch the action + actionRunnableAsyncTask = ActionRunnableAsyncTask(this, + { + sendBroadcast(Intent(DATABASE_START_TASK_ACTION).apply { + putExtra(DATABASE_TASK_TITLE_KEY, titleId) + putExtra(DATABASE_TASK_MESSAGE_KEY, messageId) + putExtra(DATABASE_TASK_WARNING_KEY, warningId) + }) - // Build and launch the action - actionRunnableAsyncTask = ActionRunnableAsyncTask(this, - { - sendBroadcast(Intent(DATABASE_START_TASK_ACTION).apply { - putExtra(DATABASE_TASK_TITLE_KEY, titleId) - putExtra(DATABASE_TASK_MESSAGE_KEY, messageId) - putExtra(DATABASE_TASK_WARNING_KEY, warningId) - }) - - mActionTaskListeners.forEach { actionTaskListener -> - actionTaskListener.onStartAction(titleId, messageId, warningId) - } - - }, { result -> - mActionTaskListeners.forEach { actionTaskListener -> - actionTaskListener.onStopAction(intentAction, result) - } - - sendBroadcast(Intent(DATABASE_STOP_TASK_ACTION)) - - stopSelf() + mActionTaskListeners.forEach { actionTaskListener -> + actionTaskListener.onStartAction(titleId, messageId, warningId) } - ) - actionRunnable?.let { actionRunnableNotNull -> - actionRunnableAsyncTask?.execute({ actionRunnableNotNull }) + + }, { result -> + mActionTaskListeners.forEach { actionTaskListener -> + actionTaskListener.onStopAction(intentAction!!, result) + } + + sendBroadcast(Intent(DATABASE_STOP_TASK_ACTION)) + + stopSelf() } - } - else -> {} + ) + actionRunnableAsyncTask?.execute({ actionRunnableNotNull }) } return START_REDELIVER_INTENT @@ -221,12 +207,6 @@ class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdat } } - private fun buildDatabaseSaveActionTask(): ActionRunnable? { - return SaveDatabaseActionRunnable(this, - Database.getInstance(), - true) - } - private fun buildDatabaseLoadActionTask(intent: Intent): ActionRunnable? { if (intent.hasExtra(DATABASE_URI_KEY) @@ -288,6 +268,16 @@ 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 fun buildDatabaseCreateGroupActionTask(intent: Intent): ActionRunnable? { return if (intent.hasExtra(GROUP_KEY) && intent.hasExtra(PARENT_ID_KEY) @@ -366,16 +356,6 @@ 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 fun buildDatabaseCopyNodesActionTask(intent: Intent): ActionRunnable? { return if (intent.hasExtra(GROUPS_ID_KEY) && intent.hasExtra(ENTRIES_ID_KEY) @@ -435,6 +415,17 @@ class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdat } } + private fun buildDatabaseSaveElementActionTask(intent: Intent): ActionRunnable? { + return SaveDatabaseActionRunnable(this, + Database.getInstance(), + true, + object: ActionRunnable() { + override fun onFinishRun(result: Result) { + result.data = intent.extras + } + }) + } + private class ActionRunnableAsyncTask(private val progressTaskUpdater: ProgressTaskUpdater, private val onPreExecute: () -> Unit, private val onPostExecute: (result: ActionRunnable.Result) -> Unit) @@ -471,7 +462,6 @@ class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdat const val DATABASE_TASK_WARNING_KEY = "DATABASE_TASK_WARNING_KEY" const val ACTION_DATABASE_CREATE_TASK = "ACTION_DATABASE_CREATE_TASK" - const val ACTION_DATABASE_SAVE_TASK = "ACTION_DATABASE_SAVE_TASK" const val ACTION_DATABASE_LOAD_TASK = "ACTION_DATABASE_LOAD_TASK" const val ACTION_DATABASE_ASSIGN_PASSWORD_TASK = "ACTION_DATABASE_ASSIGN_PASSWORD_TASK" const val ACTION_DATABASE_CREATE_GROUP_TASK = "ACTION_DATABASE_CREATE_GROUP_TASK" @@ -481,6 +471,18 @@ class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdat const val ACTION_DATABASE_COPY_NODES_TASK = "ACTION_DATABASE_COPY_NODES_TASK" const val ACTION_DATABASE_MOVE_NODES_TASK = "ACTION_DATABASE_MOVE_NODES_TASK" const val ACTION_DATABASE_DELETE_NODES_TASK = "ACTION_DATABASE_DELETE_NODES_TASK" + const val ACTION_DATABASE_SAVE_NAME_TASK = "ACTION_DATABASE_SAVE_NAME_TASK" + const val ACTION_DATABASE_SAVE_DESCRIPTION_TASK = "ACTION_DATABASE_SAVE_DESCRIPTION_TASK" + const val ACTION_DATABASE_SAVE_DEFAULT_USERNAME_TASK = "ACTION_DATABASE_SAVE_DEFAULT_USERNAME_TASK" + const val ACTION_DATABASE_SAVE_COLOR_TASK = "ACTION_DATABASE_SAVE_COLOR_TASK" + const val ACTION_DATABASE_SAVE_COMPRESSION_TASK = "ACTION_DATABASE_SAVE_COMPRESSION_TASK" + const val ACTION_DATABASE_SAVE_MAX_HISTORY_ITEMS_TASK = "ACTION_DATABASE_SAVE_MAX_HISTORY_ITEMS_TASK" + const val ACTION_DATABASE_SAVE_MAX_HISTORY_SIZE_TASK = "ACTION_DATABASE_SAVE_MAX_HISTORY_SIZE_TASK" + const val ACTION_DATABASE_SAVE_ENCRYPTION_TASK = "ACTION_DATABASE_SAVE_ENCRYPTION_TASK" + const val ACTION_DATABASE_SAVE_KEY_DERIVATION_TASK = "ACTION_DATABASE_SAVE_KEY_DERIVATION_TASK" + const val ACTION_DATABASE_SAVE_MEMORY_USAGE_TASK = "ACTION_DATABASE_SAVE_MEMORY_USAGE_TASK" + const val ACTION_DATABASE_SAVE_PARALLELISM_TASK = "ACTION_DATABASE_SAVE_PARALLELISM_TASK" + const val ACTION_DATABASE_SAVE_ITERATIONS_TASK = "ACTION_DATABASE_SAVE_ITERATIONS_TASK" const val DATABASE_URI_KEY = "DATABASE_URI_KEY" const val MASTER_PASSWORD_CHECKED_KEY = "MASTER_PASSWORD_CHECKED_KEY" @@ -500,6 +502,8 @@ class DatabaseTaskNotificationService : NotificationService(), ProgressTaskUpdat const val SAVE_DATABASE_KEY = "SAVE_DATABASE_KEY" const val OLD_NODES_KEY = "OLD_NODES_KEY" const val NEW_NODES_KEY = "NEW_NODES_KEY" + const val OLD_ELEMENT_KEY = "OLD_ELEMENT_KEY" // Warning type of this thing change every time + const val NEW_ELEMENT_KEY = "NEW_ELEMENT_KEY" // Warning type of this thing change every time fun getListNodesFromBundle(database: Database, bundle: Bundle): List { val nodesAction = ArrayList() diff --git a/app/src/main/java/com/kunzisoft/keepass/settings/NestedSettingsFragment.kt b/app/src/main/java/com/kunzisoft/keepass/settings/NestedSettingsFragment.kt index 04390d4e5..ff3197948 100644 --- a/app/src/main/java/com/kunzisoft/keepass/settings/NestedSettingsFragment.kt +++ b/app/src/main/java/com/kunzisoft/keepass/settings/NestedSettingsFragment.kt @@ -47,13 +47,30 @@ import com.kunzisoft.keepass.activities.stylish.Stylish import com.kunzisoft.keepass.app.database.CipherDatabaseAction import com.kunzisoft.keepass.app.database.FileDatabaseHistoryAction import com.kunzisoft.keepass.biometric.BiometricUnlockDatabaseHelper +import com.kunzisoft.keepass.crypto.keyDerivation.KdfEngine import com.kunzisoft.keepass.database.element.Database import com.kunzisoft.keepass.database.element.PwCompressionAlgorithm +import com.kunzisoft.keepass.database.element.PwEncryptionAlgorithm import com.kunzisoft.keepass.education.Education import com.kunzisoft.keepass.icons.IconPackChooser +import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_SAVE_COLOR_TASK +import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_SAVE_COMPRESSION_TASK +import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_SAVE_DEFAULT_USERNAME_TASK +import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_SAVE_DESCRIPTION_TASK +import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_SAVE_ENCRYPTION_TASK +import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_SAVE_ITERATIONS_TASK +import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_SAVE_KEY_DERIVATION_TASK +import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_SAVE_MAX_HISTORY_ITEMS_TASK +import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_SAVE_MAX_HISTORY_SIZE_TASK +import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_SAVE_MEMORY_USAGE_TASK +import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_SAVE_NAME_TASK +import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_SAVE_PARALLELISM_TASK +import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.NEW_ELEMENT_KEY +import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.OLD_ELEMENT_KEY import com.kunzisoft.keepass.settings.preference.* import com.kunzisoft.keepass.settings.preference.DialogColorPreference.Companion.DISABLE_COLOR import com.kunzisoft.keepass.settings.preferencedialogfragment.* +import com.kunzisoft.keepass.tasks.ActionRunnable class NestedSettingsFragment : PreferenceFragmentCompat(), Preference.OnPreferenceClickListener { @@ -62,7 +79,15 @@ class NestedSettingsFragment : PreferenceFragmentCompat(), Preference.OnPreferen private var mCount = 0 + private var dbNamePref: InputTextPreference? = null + private var dbDescriptionPref: InputTextPreference? = null + private var dbDefaultUsername: InputTextPreference? = null private var dbCustomColorPref: DialogColorPreference? = null + private var dbDataCompressionPref: Preference? = null + private var dbMaxHistoryItemsPref: InputNumberPreference? = null + private var dbMaxHistorySizePref: InputNumberPreference? = null + private var mEncryptionAlgorithmPref: DialogListExplanationPreference? = null + private var mKeyDerivationPref: DialogListExplanationPreference? = null private var mRoundPref: InputKdfNumberPreference? = null private var mMemoryPref: InputKdfNumberPreference? = null private var mParallelismPref: InputKdfNumberPreference? = null @@ -349,7 +374,7 @@ class NestedSettingsFragment : PreferenceFragmentCompat(), Preference.OnPreferen val dbGeneralPrefCategory: PreferenceCategory? = findPreference(getString(R.string.database_category_general_key)) // Database name - val dbNamePref: InputTextPreference? = findPreference(getString(R.string.database_name_key)) + dbNamePref = findPreference(getString(R.string.database_name_key)) if (mDatabase.allowName) { dbNamePref?.summary = mDatabase.name } else { @@ -357,7 +382,7 @@ class NestedSettingsFragment : PreferenceFragmentCompat(), Preference.OnPreferen } // Database description - val dbDescriptionPref: InputTextPreference? = findPreference(getString(R.string.database_description_key)) + dbDescriptionPref = findPreference(getString(R.string.database_description_key)) if (mDatabase.allowDescription) { dbDescriptionPref?.summary = mDatabase.description } else { @@ -365,7 +390,7 @@ class NestedSettingsFragment : PreferenceFragmentCompat(), Preference.OnPreferen } // Database default username - val dbDefaultUsername: InputTextPreference? = findPreference(getString(R.string.database_default_username_key)) + dbDefaultUsername = findPreference(getString(R.string.database_default_username_key)) if (mDatabase.allowDefaultUsername) { dbDefaultUsername?.summary = mDatabase.defaultUsername } else { @@ -397,9 +422,9 @@ class NestedSettingsFragment : PreferenceFragmentCompat(), Preference.OnPreferen val dbCompressionPrefCategory: PreferenceCategory? = findPreference(getString(R.string.database_category_compression_key)) // Database compression - val databaseDataCompressionPref = findPreference(getString(R.string.database_data_compression_key)) + dbDataCompressionPref = findPreference(getString(R.string.database_data_compression_key)) if (mDatabase.allowDataCompression) { - databaseDataCompressionPref?.summary = (mDatabase.compressionAlgorithm + dbDataCompressionPref?.summary = (mDatabase.compressionAlgorithm ?: PwCompressionAlgorithm.None).getName(resources) } else { dbCompressionPrefCategory?.isVisible = false @@ -421,12 +446,14 @@ class NestedSettingsFragment : PreferenceFragmentCompat(), Preference.OnPreferen ?.isVisible = mDatabase.manageHistory == true // Max history items - findPreference(getString(R.string.max_history_items_key)) - ?.summary = mDatabase.historyMaxItems.toString() + dbMaxHistoryItemsPref = findPreference(getString(R.string.max_history_items_key))?.apply { + summary = mDatabase.historyMaxItems.toString() + } // Max history size - findPreference(getString(R.string.max_history_size_key)) - ?.summary = mDatabase.historyMaxSize.toString() + dbMaxHistorySizePref = findPreference(getString(R.string.max_history_size_key))?.apply { + summary = mDatabase.historyMaxSize.toString() + } } else { Log.e(javaClass.name, "Database isn't ready") @@ -438,24 +465,29 @@ class NestedSettingsFragment : PreferenceFragmentCompat(), Preference.OnPreferen if (mDatabase.loaded) { // Encryption Algorithm - findPreference(getString(R.string.encryption_algorithm_key)) - ?.summary = mDatabase.getEncryptionAlgorithmName(resources) + mEncryptionAlgorithmPref = findPreference(getString(R.string.encryption_algorithm_key))?.apply { + summary = mDatabase.getEncryptionAlgorithmName(resources) + } // Key derivation function - findPreference(getString(R.string.key_derivation_function_key)) - ?.summary = mDatabase.getKeyDerivationName(resources) + mKeyDerivationPref = findPreference(getString(R.string.key_derivation_function_key))?.apply { + summary = mDatabase.getKeyDerivationName(resources) + } // Round encryption - mRoundPref = findPreference(getString(R.string.transform_rounds_key)) - mRoundPref?.summary = mDatabase.numberKeyEncryptionRounds.toString() + mRoundPref = findPreference(getString(R.string.transform_rounds_key))?.apply { + summary = mDatabase.numberKeyEncryptionRounds.toString() + } // Memory Usage - mMemoryPref = findPreference(getString(R.string.memory_usage_key)) - mMemoryPref?.summary = mDatabase.memoryUsage.toString() + mMemoryPref = findPreference(getString(R.string.memory_usage_key))?.apply { + summary = mDatabase.memoryUsage.toString() + } // Parallelism - mParallelismPref = findPreference(getString(R.string.parallelism_key)) - mParallelismPref?.summary = mDatabase.parallelism.toString() + mParallelismPref = findPreference(getString(R.string.parallelism_key))?.apply { + summary = mDatabase.parallelism.toString() + } } else { Log.e(javaClass.name, "Database isn't ready") } @@ -551,6 +583,178 @@ class NestedSettingsFragment : PreferenceFragmentCompat(), Preference.OnPreferen return view } + fun onProgressDialogThreadResult(actionTask: String, + result: ActionRunnable.Result) { + result.data?.let { data -> + if (data.containsKey(OLD_ELEMENT_KEY) + && data.containsKey(NEW_ELEMENT_KEY)) { + when (actionTask) { + /* + -------- + Main preferences + -------- + */ + ACTION_DATABASE_SAVE_NAME_TASK -> { + val oldName = data.getString(OLD_ELEMENT_KEY)!! + val newName = data.getString(NEW_ELEMENT_KEY)!! + val nameToShow = + if (result.isSuccess) { + newName + } else { + mDatabase.name = oldName + oldName + } + dbNamePref?.summary = nameToShow + } + ACTION_DATABASE_SAVE_DESCRIPTION_TASK -> { + val oldDescription = data.getString(OLD_ELEMENT_KEY)!! + val newDescription = data.getString(NEW_ELEMENT_KEY)!! + val descriptionToShow = + if (result.isSuccess) { + newDescription + } else { + mDatabase.description = oldDescription + oldDescription + } + dbDescriptionPref?.summary = descriptionToShow + } + ACTION_DATABASE_SAVE_DEFAULT_USERNAME_TASK -> { + val oldDefaultUsername = data.getString(OLD_ELEMENT_KEY)!! + val newDefaultUsername = data.getString(NEW_ELEMENT_KEY)!! + val defaultUsernameToShow = + if (result.isSuccess) { + newDefaultUsername + } else { + mDatabase.defaultUsername = oldDefaultUsername + oldDefaultUsername + } + dbDefaultUsername?.summary = defaultUsernameToShow + } + ACTION_DATABASE_SAVE_COLOR_TASK -> { + val oldColor = data.getString(OLD_ELEMENT_KEY)!! + val newColor = data.getString(NEW_ELEMENT_KEY)!! + + val defaultColorToShow = + if (result.isSuccess) { + newColor + } else { + mDatabase.customColor = oldColor + oldColor + } + dbCustomColorPref?.summary = defaultColorToShow + } + ACTION_DATABASE_SAVE_COMPRESSION_TASK -> { + val oldCompression = data.getSerializable(OLD_ELEMENT_KEY) as PwCompressionAlgorithm + val newCompression = data.getSerializable(NEW_ELEMENT_KEY) as PwCompressionAlgorithm + val algorithmToShow = + if (result.isSuccess) { + newCompression + } else { + mDatabase.compressionAlgorithm = oldCompression + oldCompression + } + dbDataCompressionPref?.summary = algorithmToShow.getName(resources) + } + ACTION_DATABASE_SAVE_MAX_HISTORY_ITEMS_TASK -> { + val oldMaxHistoryItems = data.getInt(OLD_ELEMENT_KEY) + val newMaxHistoryItems = data.getInt(NEW_ELEMENT_KEY) + val maxHistoryItemsToShow = + if (result.isSuccess) { + newMaxHistoryItems + } else { + mDatabase.historyMaxItems = oldMaxHistoryItems + oldMaxHistoryItems + } + dbMaxHistoryItemsPref?.summary = maxHistoryItemsToShow.toString() + } + ACTION_DATABASE_SAVE_MAX_HISTORY_SIZE_TASK -> { + val oldMaxHistorySize = data.getLong(OLD_ELEMENT_KEY) + val newMaxHistorySize = data.getLong(NEW_ELEMENT_KEY) + val maxHistorySizeToShow = + if (result.isSuccess) { + newMaxHistorySize + } else { + mDatabase.historyMaxSize = oldMaxHistorySize + oldMaxHistorySize + } + dbMaxHistorySizePref?.summary = maxHistorySizeToShow.toString() + } + + /* + -------- + Security + -------- + */ + ACTION_DATABASE_SAVE_ENCRYPTION_TASK -> { + val oldEncryption = data.getSerializable(OLD_ELEMENT_KEY) as PwEncryptionAlgorithm + val newEncryption = data.getSerializable(NEW_ELEMENT_KEY) as PwEncryptionAlgorithm + val algorithmToShow = + if (result.isSuccess) { + newEncryption + } else { + mDatabase.encryptionAlgorithm = oldEncryption + oldEncryption + } + mEncryptionAlgorithmPref?.summary = algorithmToShow.getName(resources) + } + ACTION_DATABASE_SAVE_KEY_DERIVATION_TASK -> { + val oldKeyDerivationEngine = data.getSerializable(OLD_ELEMENT_KEY) as KdfEngine + val newKeyDerivationEngine = data.getSerializable(NEW_ELEMENT_KEY) as KdfEngine + val kdfEngineToShow = + if (result.isSuccess) { + newKeyDerivationEngine + } else { + mDatabase.kdfEngine = oldKeyDerivationEngine + oldKeyDerivationEngine + } + mKeyDerivationPref?.summary = kdfEngineToShow.getName(resources) + + mRoundPref?.summary = kdfEngineToShow.defaultKeyRounds.toString() + // Disable memory and parallelism if not available + mMemoryPref?.summary = kdfEngineToShow.defaultMemoryUsage.toString() + mParallelismPref?.summary = kdfEngineToShow.defaultParallelism.toString() + } + ACTION_DATABASE_SAVE_ITERATIONS_TASK -> { + val oldIterations = data.getLong(OLD_ELEMENT_KEY) + val newIterations = data.getLong(NEW_ELEMENT_KEY) + val roundsToShow = + if (result.isSuccess) { + newIterations + } else { + mDatabase.numberKeyEncryptionRounds = oldIterations + oldIterations + } + mRoundPref?.summary = roundsToShow.toString() + } + ACTION_DATABASE_SAVE_MEMORY_USAGE_TASK -> { + val oldMemoryUsage = data.getLong(OLD_ELEMENT_KEY) + val newMemoryUsage = data.getLong(NEW_ELEMENT_KEY) + val memoryToShow = + if (result.isSuccess) { + newMemoryUsage + } else { + mDatabase.memoryUsage = oldMemoryUsage + oldMemoryUsage + } + mMemoryPref?.summary = memoryToShow.toString() + } + ACTION_DATABASE_SAVE_PARALLELISM_TASK -> { + val oldParallelism = data.getInt(OLD_ELEMENT_KEY) + val newParallelism = data.getInt(NEW_ELEMENT_KEY) + val parallelismToShow = + if (result.isSuccess) { + newParallelism + } else { + mDatabase.parallelism = oldParallelism + oldParallelism + } + mParallelismPref?.summary = parallelismToShow.toString() + } + } + } + } + } + override fun onDisplayPreferenceDialog(preference: Preference?) { var otherDialogFragment = false @@ -559,6 +763,7 @@ class NestedSettingsFragment : PreferenceFragmentCompat(), Preference.OnPreferen preference?.let { preference -> var dialogFragment: DialogFragment? = null when { + // Main Preferences preference.key == getString(R.string.database_name_key) -> { dialogFragment = DatabaseNamePreferenceDialogFragmentCompat.newInstance(preference.key) } @@ -582,6 +787,8 @@ class NestedSettingsFragment : PreferenceFragmentCompat(), Preference.OnPreferen preference.key == getString(R.string.max_history_size_key) -> { dialogFragment = MaxHistorySizePreferenceDialogFragmentCompat.newInstance(preference.key) } + + // Security preference.key == getString(R.string.encryption_algorithm_key) -> { dialogFragment = DatabaseEncryptionAlgorithmPreferenceDialogFragmentCompat.newInstance(preference.key) } diff --git a/app/src/main/java/com/kunzisoft/keepass/settings/SettingsActivity.kt b/app/src/main/java/com/kunzisoft/keepass/settings/SettingsActivity.kt index ea0067edc..eb29b9312 100644 --- a/app/src/main/java/com/kunzisoft/keepass/settings/SettingsActivity.kt +++ b/app/src/main/java/com/kunzisoft/keepass/settings/SettingsActivity.kt @@ -26,7 +26,6 @@ import android.content.Intent import android.net.Uri import android.os.Bundle import android.view.MenuItem -import android.widget.Toast import androidx.appcompat.widget.Toolbar import androidx.fragment.app.Fragment import com.kunzisoft.keepass.R @@ -36,8 +35,6 @@ import com.kunzisoft.keepass.activities.helpers.ReadOnlyHelper import com.kunzisoft.keepass.activities.lock.LockingActivity import com.kunzisoft.keepass.database.action.ProgressDialogThread import com.kunzisoft.keepass.database.element.Database -import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_ASSIGN_PASSWORD_TASK -import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_SAVE_TASK import com.kunzisoft.keepass.timeout.TimeoutHelper open class SettingsActivity @@ -94,18 +91,10 @@ open class SettingsActivity backupManager = BackupManager(this) progressDialogThread = ProgressDialogThread(this) { actionTask, result -> - when (actionTask) { - ACTION_DATABASE_ASSIGN_PASSWORD_TASK -> { - // Nothing here - } - ACTION_DATABASE_SAVE_TASK -> { - if (!result.isSuccess) { - // TODO Log.e(TAG, result.message) - Toast.makeText(this, result.message, Toast.LENGTH_SHORT).show() - } - // TODO actionAfterSaveDatabase?.onFinishRun(result) - } - } + // Call result in fragment + (supportFragmentManager + .findFragmentByTag(TAG_NESTED) as NestedSettingsFragment?) + ?.onProgressDialogThreadResult(actionTask, result) } } @@ -135,7 +124,10 @@ open class SettingsActivity super.onStop() } - override fun onAssignKeyDialogPositiveClick(masterPasswordChecked: Boolean, masterPassword: String?, keyFileChecked: Boolean, keyFile: Uri?) { + override fun onAssignKeyDialogPositiveClick(masterPasswordChecked: Boolean, + masterPassword: String?, + keyFileChecked: Boolean, + keyFile: Uri?) { Database.getInstance().let { database -> // Show the progress dialog now or after dialog confirmation if (database.validatePasswordEncoding(masterPassword, keyFileChecked)) { @@ -161,7 +153,10 @@ open class SettingsActivity } } - override fun onAssignKeyDialogNegativeClick(masterPasswordChecked: Boolean, masterPassword: String?, keyFileChecked: Boolean, keyFile: Uri?) { + override fun onAssignKeyDialogNegativeClick(masterPasswordChecked: Boolean, + masterPassword: String?, + keyFileChecked: Boolean, + keyFile: Uri?) { } diff --git a/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/DatabaseColorPreferenceDialogFragmentCompat.kt b/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/DatabaseColorPreferenceDialogFragmentCompat.kt index 1c737f114..2cd54591c 100644 --- a/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/DatabaseColorPreferenceDialogFragmentCompat.kt +++ b/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/DatabaseColorPreferenceDialogFragmentCompat.kt @@ -36,7 +36,6 @@ import com.kunzisoft.androidclearchroma.colormode.ColorMode import com.kunzisoft.androidclearchroma.fragment.ChromaColorFragment import com.kunzisoft.androidclearchroma.fragment.ChromaColorFragment.* import com.kunzisoft.keepass.R -import com.kunzisoft.keepass.tasks.ActionRunnable import java.lang.Exception class DatabaseColorPreferenceDialogFragmentCompat : DatabaseSavePreferenceDialogFragmentCompat() { @@ -88,16 +87,15 @@ class DatabaseColorPreferenceDialogFragmentCompat : DatabaseSavePreferenceDialog } val oldColor = database.customColor database.customColor = newColor - - actionInUIThreadAfterSaveDatabase = AfterColorSave(newColor, oldColor) + progressDialogThread?.startDatabaseSaveColor(oldColor, newColor) } - super.onDialogClosed(true) + onDialogClosed(true) dismiss() } alertDialogBuilder.setNegativeButton(android.R.string.cancel) { _, _ -> - super.onDialogClosed(false) + onDialogClosed(false) dismiss() } @@ -112,6 +110,10 @@ class DatabaseColorPreferenceDialogFragmentCompat : DatabaseSavePreferenceDialog return dialog } + override fun onDialogClosed(positiveResult: Boolean) { + // Nothing here + } + /** * Set new dimensions to dialog * @param ad dialog @@ -134,22 +136,6 @@ class DatabaseColorPreferenceDialogFragmentCompat : DatabaseSavePreferenceDialog return rootView } - private inner class AfterColorSave(private val mNewColor: String, - private val mOldColor: String) - : ActionRunnable() { - - override fun onFinishRun(result: Result) { - val defaultColorToShow = - if (result.isSuccess) { - mNewColor - } else { - database?.customColor = mOldColor - mOldColor - } - preference.summary = defaultColorToShow - } - } - companion object { private const val TAG_FRAGMENT_COLORS = "TAG_FRAGMENT_COLORS" diff --git a/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/DatabaseDataCompressionPreferenceDialogFragmentCompat.kt b/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/DatabaseDataCompressionPreferenceDialogFragmentCompat.kt index fbee376de..f20873115 100644 --- a/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/DatabaseDataCompressionPreferenceDialogFragmentCompat.kt +++ b/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/DatabaseDataCompressionPreferenceDialogFragmentCompat.kt @@ -26,7 +26,6 @@ import androidx.recyclerview.widget.RecyclerView import com.kunzisoft.keepass.R import com.kunzisoft.keepass.database.element.PwCompressionAlgorithm import com.kunzisoft.keepass.settings.preferencedialogfragment.adapter.ListRadioItemAdapter -import com.kunzisoft.keepass.tasks.ActionRunnable class DatabaseDataCompressionPreferenceDialogFragmentCompat : DatabaseSavePreferenceDialogFragmentCompat(), @@ -60,39 +59,21 @@ class DatabaseDataCompressionPreferenceDialogFragmentCompat if (positiveResult) { database?.let { database -> if (compressionSelected != null) { - val newAlgorithm = compressionSelected - val oldAlgorithm = database.compressionAlgorithm - database.compressionAlgorithm = newAlgorithm + val newCompression = compressionSelected + val oldCompression = database.compressionAlgorithm + database.compressionAlgorithm = newCompression - if (oldAlgorithm != null && newAlgorithm != null) - actionInUIThreadAfterSaveDatabase = AfterDescriptionSave(newAlgorithm, oldAlgorithm) + if (oldCompression != null && newCompression != null) + progressDialogThread?.startDatabaseSaveCompression(oldCompression, newCompression) } } } - - super.onDialogClosed(positiveResult) } override fun onItemSelected(item: PwCompressionAlgorithm) { this.compressionSelected = item } - private inner class AfterDescriptionSave(private val mNewAlgorithm: PwCompressionAlgorithm, - private val mOldAlgorithm: PwCompressionAlgorithm) - : ActionRunnable() { - - override fun onFinishRun(result: Result) { - val algorithmToShow = - if (result.isSuccess) { - mNewAlgorithm - } else { - database?.compressionAlgorithm = mOldAlgorithm - mOldAlgorithm - } - preference.summary = algorithmToShow.getName(settingsResources) - } - } - companion object { fun newInstance(key: String): DatabaseDataCompressionPreferenceDialogFragmentCompat { diff --git a/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/DatabaseDefaultUsernamePreferenceDialogFragmentCompat.kt b/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/DatabaseDefaultUsernamePreferenceDialogFragmentCompat.kt index 6c7cb52ff..2430616b4 100644 --- a/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/DatabaseDefaultUsernamePreferenceDialogFragmentCompat.kt +++ b/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/DatabaseDefaultUsernamePreferenceDialogFragmentCompat.kt @@ -21,7 +21,6 @@ package com.kunzisoft.keepass.settings.preferencedialogfragment import android.os.Bundle import android.view.View -import com.kunzisoft.keepass.tasks.ActionRunnable class DatabaseDefaultUsernamePreferenceDialogFragmentCompat : DatabaseSavePreferenceDialogFragmentCompat() { @@ -38,27 +37,9 @@ class DatabaseDefaultUsernamePreferenceDialogFragmentCompat : DatabaseSavePrefer val oldDefaultUsername = database.defaultUsername database.defaultUsername = newDefaultUsername - actionInUIThreadAfterSaveDatabase = AfterDefaultUsernameSave(newDefaultUsername, oldDefaultUsername) + progressDialogThread?.startDatabaseSaveDefaultUsername(oldDefaultUsername, newDefaultUsername) } } - - super.onDialogClosed(positiveResult) - } - - private inner class AfterDefaultUsernameSave(private val mNewDefaultUsername: String, - private val mOldDefaultUsername: String) - : ActionRunnable() { - - override fun onFinishRun(result: Result) { - val defaultUsernameToShow = - if (result.isSuccess) { - mNewDefaultUsername - } else { - database?.defaultUsername = mOldDefaultUsername - mOldDefaultUsername - } - preference.summary = defaultUsernameToShow - } } companion object { diff --git a/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/DatabaseDescriptionPreferenceDialogFragmentCompat.kt b/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/DatabaseDescriptionPreferenceDialogFragmentCompat.kt index e08bdb851..199f42373 100644 --- a/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/DatabaseDescriptionPreferenceDialogFragmentCompat.kt +++ b/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/DatabaseDescriptionPreferenceDialogFragmentCompat.kt @@ -21,7 +21,6 @@ package com.kunzisoft.keepass.settings.preferencedialogfragment import android.os.Bundle import android.view.View -import com.kunzisoft.keepass.tasks.ActionRunnable class DatabaseDescriptionPreferenceDialogFragmentCompat : DatabaseSavePreferenceDialogFragmentCompat() { @@ -38,27 +37,9 @@ class DatabaseDescriptionPreferenceDialogFragmentCompat : DatabaseSavePreference val oldDescription = database.description database.description = newDescription - actionInUIThreadAfterSaveDatabase = AfterDescriptionSave(newDescription, oldDescription) + progressDialogThread?.startDatabaseSaveDescription(oldDescription, newDescription) } } - - super.onDialogClosed(positiveResult) - } - - private inner class AfterDescriptionSave(private val mNewDescription: String, - private val mOldDescription: String) - : ActionRunnable() { - - override fun onFinishRun(result: Result) { - val descriptionToShow = - if (result.isSuccess) { - mNewDescription - } else { - database?.description = mOldDescription - mOldDescription - } - preference.summary = descriptionToShow - } } companion object { diff --git a/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/DatabaseEncryptionAlgorithmPreferenceDialogFragmentCompat.kt b/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/DatabaseEncryptionAlgorithmPreferenceDialogFragmentCompat.kt index 38aef811e..61c1f3edb 100644 --- a/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/DatabaseEncryptionAlgorithmPreferenceDialogFragmentCompat.kt +++ b/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/DatabaseEncryptionAlgorithmPreferenceDialogFragmentCompat.kt @@ -26,7 +26,6 @@ import android.view.View import com.kunzisoft.keepass.R import com.kunzisoft.keepass.database.element.PwEncryptionAlgorithm import com.kunzisoft.keepass.settings.preferencedialogfragment.adapter.ListRadioItemAdapter -import com.kunzisoft.keepass.tasks.ActionRunnable class DatabaseEncryptionAlgorithmPreferenceDialogFragmentCompat : DatabaseSavePreferenceDialogFragmentCompat(), @@ -66,35 +65,17 @@ class DatabaseEncryptionAlgorithmPreferenceDialogFragmentCompat database.encryptionAlgorithm = newAlgorithm if (oldAlgorithm != null && newAlgorithm != null) - actionInUIThreadAfterSaveDatabase = AfterDescriptionSave(newAlgorithm, oldAlgorithm) + progressDialogThread?.startDatabaseSaveEncryption(oldAlgorithm, newAlgorithm) } } } } - - super.onDialogClosed(positiveResult) } override fun onItemSelected(item: PwEncryptionAlgorithm) { this.algorithmSelected = item } - private inner class AfterDescriptionSave(private val mNewAlgorithm: PwEncryptionAlgorithm, - private val mOldAlgorithm: PwEncryptionAlgorithm) - : ActionRunnable() { - - override fun onFinishRun(result: Result) { - val algorithmToShow = - if (result.isSuccess) { - mNewAlgorithm - } else { - database?.encryptionAlgorithm = mOldAlgorithm - mOldAlgorithm - } - preference.summary = algorithmToShow.getName(settingsResources) - } - } - companion object { fun newInstance(key: String): DatabaseEncryptionAlgorithmPreferenceDialogFragmentCompat { diff --git a/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/DatabaseKeyDerivationPreferenceDialogFragmentCompat.kt b/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/DatabaseKeyDerivationPreferenceDialogFragmentCompat.kt index 6b05c14a7..dc82d55cb 100644 --- a/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/DatabaseKeyDerivationPreferenceDialogFragmentCompat.kt +++ b/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/DatabaseKeyDerivationPreferenceDialogFragmentCompat.kt @@ -27,7 +27,6 @@ import android.view.View import com.kunzisoft.keepass.R import com.kunzisoft.keepass.crypto.keyDerivation.KdfEngine import com.kunzisoft.keepass.settings.preferencedialogfragment.adapter.ListRadioItemAdapter -import com.kunzisoft.keepass.tasks.ActionRunnable class DatabaseKeyDerivationPreferenceDialogFragmentCompat : DatabaseSavePreferenceDialogFragmentCompat(), @@ -67,13 +66,11 @@ class DatabaseKeyDerivationPreferenceDialogFragmentCompat val oldKdfEngine = database.kdfEngine if (newKdfEngine != null && oldKdfEngine != null) { database.kdfEngine = newKdfEngine - actionInUIThreadAfterSaveDatabase = AfterDescriptionSave(newKdfEngine, oldKdfEngine) + progressDialogThread?.startDatabaseSaveKeyDerivation(oldKdfEngine, newKdfEngine) } } } } - - super.onDialogClosed(positiveResult) } fun setRoundPreference(preference: Preference?) { @@ -92,27 +89,6 @@ class DatabaseKeyDerivationPreferenceDialogFragmentCompat kdfEngineSelected = item } - private inner class AfterDescriptionSave(private val mNewKdfEngine: KdfEngine, - private val mOldKdfEngine: KdfEngine) - : ActionRunnable() { - - override fun onFinishRun(result: Result) { - val kdfEngineToShow = - if (result.isSuccess) { - mNewKdfEngine - } else { - database?.kdfEngine = mOldKdfEngine - mOldKdfEngine - } - preference.summary = kdfEngineToShow.getName(settingsResources) - - roundPreference?.summary = kdfEngineToShow.defaultKeyRounds.toString() - // Disable memory and parallelism if not available - memoryPreference?.summary = kdfEngineToShow.defaultMemoryUsage.toString() - parallelismPreference?.summary = kdfEngineToShow.defaultParallelism.toString() - } - } - companion object { fun newInstance(key: String): DatabaseKeyDerivationPreferenceDialogFragmentCompat { diff --git a/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/DatabaseNamePreferenceDialogFragmentCompat.kt b/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/DatabaseNamePreferenceDialogFragmentCompat.kt index 8b4372037..6eb74e17a 100644 --- a/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/DatabaseNamePreferenceDialogFragmentCompat.kt +++ b/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/DatabaseNamePreferenceDialogFragmentCompat.kt @@ -21,7 +21,6 @@ package com.kunzisoft.keepass.settings.preferencedialogfragment import android.os.Bundle import android.view.View -import com.kunzisoft.keepass.tasks.ActionRunnable class DatabaseNamePreferenceDialogFragmentCompat : DatabaseSavePreferenceDialogFragmentCompat() { @@ -38,27 +37,9 @@ class DatabaseNamePreferenceDialogFragmentCompat : DatabaseSavePreferenceDialogF val oldName = database.name database.name = newName - actionInUIThreadAfterSaveDatabase = AfterNameSave(newName, oldName) + progressDialogThread?.startDatabaseSaveName(oldName, newName) } } - - super.onDialogClosed(positiveResult) - } - - private inner class AfterNameSave(private val mNewName: String, - private val mOldName: String) - : ActionRunnable() { - - override fun onFinishRun(result: Result) { - val nameToShow = - if (result.isSuccess) { - mNewName - } else { - database?.name = mOldName - mOldName - } - preference.summary = nameToShow - } } companion object { diff --git a/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/DatabaseSavePreferenceDialogFragmentCompat.kt b/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/DatabaseSavePreferenceDialogFragmentCompat.kt index 9b0ee00b1..2d4182679 100644 --- a/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/DatabaseSavePreferenceDialogFragmentCompat.kt +++ b/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/DatabaseSavePreferenceDialogFragmentCompat.kt @@ -19,20 +19,17 @@ */ package com.kunzisoft.keepass.settings.preferencedialogfragment -import android.content.res.Resources +import android.content.Context import android.os.Bundle -import android.view.View +import com.kunzisoft.keepass.database.action.ProgressDialogThread import com.kunzisoft.keepass.database.element.Database import com.kunzisoft.keepass.settings.SettingsActivity -import com.kunzisoft.keepass.tasks.ActionRunnable abstract class DatabaseSavePreferenceDialogFragmentCompat : InputPreferenceDialogFragmentCompat() { protected var database: Database? = null - var actionInUIThreadAfterSaveDatabase: ActionRunnable? = null - - protected lateinit var settingsResources: Resources + protected var progressDialogThread: ProgressDialogThread? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -40,33 +37,15 @@ abstract class DatabaseSavePreferenceDialogFragmentCompat : InputPreferenceDialo this.database = Database.getInstance() } - override fun onBindDialogView(view: View) { - super.onBindDialogView(view) - - activity?.resources?.let { settingsResources = it } - } - - override fun onDialogClosed(positiveResult: Boolean) { - if (positiveResult) { - registerActionFinish() - (activity as SettingsActivity?)?.progressDialogThread?.startDatabaseSave() + override fun onAttach(context: Context) { + super.onAttach(context) + // Attach dialog thread to start action + if (context is SettingsActivity) { + progressDialogThread = context.progressDialogThread } } - fun registerActionFinish() { - // TODO remove receiver - // Register a database task receiver to stop loading dialog when service finish the task - /* - when (intent?.action) { - DATABASE_STOP_TASK_ACTION -> { - actionInUIThreadAfterSaveDatabase?.onFinishRun(result) - } - } - */ - } - companion object { - private const val TAG = "DbSavePrefDialog" } } diff --git a/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/MaxHistoryItemsPreferenceDialogFragmentCompat.kt b/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/MaxHistoryItemsPreferenceDialogFragmentCompat.kt index bc3f7e454..f9f45731e 100644 --- a/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/MaxHistoryItemsPreferenceDialogFragmentCompat.kt +++ b/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/MaxHistoryItemsPreferenceDialogFragmentCompat.kt @@ -22,7 +22,6 @@ package com.kunzisoft.keepass.settings.preferencedialogfragment import android.os.Bundle import android.view.View import com.kunzisoft.keepass.R -import com.kunzisoft.keepass.tasks.ActionRunnable class MaxHistoryItemsPreferenceDialogFragmentCompat : DatabaseSavePreferenceDialogFragmentCompat() { @@ -57,27 +56,9 @@ class MaxHistoryItemsPreferenceDialogFragmentCompat : DatabaseSavePreferenceDial val oldMaxHistoryItems = database.historyMaxItems database.historyMaxItems = maxHistoryItems - actionInUIThreadAfterSaveDatabase = AfterMaxHistoryItemsSave(maxHistoryItems, oldMaxHistoryItems) + progressDialogThread?.startDatabaseSaveMaxHistoryItems(oldMaxHistoryItems, maxHistoryItems) } } - - super.onDialogClosed(positiveResult) - } - - private inner class AfterMaxHistoryItemsSave(private val mNewMaxHistoryItems: Int, - private val mOldMaxHistoryItems: Int) - : ActionRunnable() { - - override fun onFinishRun(result: Result) { - val maxHistoryItemsToShow = - if (result.isSuccess) { - mNewMaxHistoryItems - } else { - database?.historyMaxItems = mOldMaxHistoryItems - mOldMaxHistoryItems - } - preference.summary = maxHistoryItemsToShow.toString() - } } companion object { diff --git a/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/MaxHistorySizePreferenceDialogFragmentCompat.kt b/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/MaxHistorySizePreferenceDialogFragmentCompat.kt index da592012b..ca709a2b5 100644 --- a/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/MaxHistorySizePreferenceDialogFragmentCompat.kt +++ b/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/MaxHistorySizePreferenceDialogFragmentCompat.kt @@ -22,7 +22,6 @@ package com.kunzisoft.keepass.settings.preferencedialogfragment import android.os.Bundle import android.view.View import com.kunzisoft.keepass.R -import com.kunzisoft.keepass.tasks.ActionRunnable class MaxHistorySizePreferenceDialogFragmentCompat : DatabaseSavePreferenceDialogFragmentCompat() { @@ -57,27 +56,9 @@ class MaxHistorySizePreferenceDialogFragmentCompat : DatabaseSavePreferenceDialo val oldMaxHistorySize = database.historyMaxSize database.historyMaxSize = maxHistorySize - actionInUIThreadAfterSaveDatabase = AfterMaxHistorySizeSave(maxHistorySize, oldMaxHistorySize) + progressDialogThread?.startDatabaseSaveMaxHistorySize(oldMaxHistorySize, maxHistorySize) } } - - super.onDialogClosed(positiveResult) - } - - private inner class AfterMaxHistorySizeSave(private val mNewMaxHistorySize: Long, - private val mOldMaxHistorySize: Long) - : ActionRunnable() { - - override fun onFinishRun(result: Result) { - val maxHistorySizeToShow = - if (result.isSuccess) { - mNewMaxHistorySize - } else { - database?.historyMaxSize = mOldMaxHistorySize - mOldMaxHistorySize - } - preference.summary = maxHistorySizeToShow.toString() - } } companion object { diff --git a/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/MemoryUsagePreferenceDialogFragmentCompat.kt b/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/MemoryUsagePreferenceDialogFragmentCompat.kt index 25463f269..c2f6e41a0 100644 --- a/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/MemoryUsagePreferenceDialogFragmentCompat.kt +++ b/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/MemoryUsagePreferenceDialogFragmentCompat.kt @@ -22,7 +22,6 @@ package com.kunzisoft.keepass.settings.preferencedialogfragment import android.os.Bundle import android.view.View import com.kunzisoft.keepass.R -import com.kunzisoft.keepass.tasks.ActionRunnable class MemoryUsagePreferenceDialogFragmentCompat : DatabaseSavePreferenceDialogFragmentCompat() { @@ -49,27 +48,9 @@ class MemoryUsagePreferenceDialogFragmentCompat : DatabaseSavePreferenceDialogFr val oldMemoryUsage = database.memoryUsage database.memoryUsage = memoryUsage - actionInUIThreadAfterSaveDatabase = AfterMemorySave(memoryUsage, oldMemoryUsage) + progressDialogThread?.startDatabaseSaveMemoryUsage(oldMemoryUsage, memoryUsage) } } - - super.onDialogClosed(positiveResult) - } - - private inner class AfterMemorySave(private val mNewMemory: Long, - private val mOldMemory: Long) - : ActionRunnable() { - - override fun onFinishRun(result: Result) { - val memoryToShow = - if (result.isSuccess) { - mNewMemory - } else { - database?.memoryUsage = mOldMemory - mOldMemory - } - preference.summary = memoryToShow.toString() - } } companion object { diff --git a/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/ParallelismPreferenceDialogFragmentCompat.kt b/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/ParallelismPreferenceDialogFragmentCompat.kt index e876203ec..2d675a54b 100644 --- a/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/ParallelismPreferenceDialogFragmentCompat.kt +++ b/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/ParallelismPreferenceDialogFragmentCompat.kt @@ -22,7 +22,6 @@ package com.kunzisoft.keepass.settings.preferencedialogfragment import android.os.Bundle import android.view.View import com.kunzisoft.keepass.R -import com.kunzisoft.keepass.tasks.ActionRunnable class ParallelismPreferenceDialogFragmentCompat : DatabaseSavePreferenceDialogFragmentCompat() { @@ -49,27 +48,9 @@ class ParallelismPreferenceDialogFragmentCompat : DatabaseSavePreferenceDialogFr val oldParallelism = database.parallelism database.parallelism = parallelism - actionInUIThreadAfterSaveDatabase = AfterParallelismSave(parallelism, oldParallelism) + progressDialogThread?.startDatabaseSaveParallelism(oldParallelism, parallelism) } } - - super.onDialogClosed(positiveResult) - } - - private inner class AfterParallelismSave(private val mNewParallelism: Int, - private val mOldParallelism: Int) - : ActionRunnable() { - - override fun onFinishRun(result: Result) { - val parallelismToShow = - if (result.isSuccess) { - mNewParallelism - } else { - database?.parallelism = mOldParallelism - mOldParallelism - } - preference.summary = parallelismToShow.toString() - } } companion object { diff --git a/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/RoundsPreferenceDialogFragmentCompat.kt b/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/RoundsPreferenceDialogFragmentCompat.kt index f4aa89e42..7faa0d370 100644 --- a/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/RoundsPreferenceDialogFragmentCompat.kt +++ b/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/RoundsPreferenceDialogFragmentCompat.kt @@ -23,7 +23,6 @@ import android.os.Bundle import android.view.View import android.widget.Toast import com.kunzisoft.keepass.R -import com.kunzisoft.keepass.tasks.ActionRunnable class RoundsPreferenceDialogFragmentCompat : DatabaseSavePreferenceDialogFragmentCompat() { @@ -55,26 +54,9 @@ class RoundsPreferenceDialogFragmentCompat : DatabaseSavePreferenceDialogFragmen database.numberKeyEncryptionRounds = Long.MAX_VALUE } - actionInUIThreadAfterSaveDatabase = AfterRoundSave(rounds, oldRounds) + progressDialogThread?.startDatabaseSaveIterations(oldRounds, rounds) } } - - super.onDialogClosed(positiveResult) - } - - private inner class AfterRoundSave(private val mNewRounds: Long, - private val mOldRounds: Long) : ActionRunnable() { - - override fun onFinishRun(result: Result) { - val roundsToShow = - if (result.isSuccess) { - mNewRounds - } else { - database?.numberKeyEncryptionRounds = mOldRounds - mOldRounds - } - preference.summary = roundsToShow.toString() - } } companion object {