From 2b33d785acde25054007448f7cfd929f81c869c9 Mon Sep 17 00:00:00 2001 From: J-Jamet Date: Tue, 13 Aug 2019 16:06:30 +0200 Subject: [PATCH] Add clear database option when close clipboard notification --- app/src/main/AndroidManifest.xml | 7 +- .../keepass/activities/EntryActivity.kt | 4 +- .../activities/lock/LockingActivity.kt | 2 +- .../keepass/magikeyboard/MagikIME.kt | 1 + ....kt => ClipboardEntryNotificationField.kt} | 14 ++-- ...t => ClipboardEntryNotificationService.kt} | 83 +++++++++++-------- .../KeyboardEntryNotificationService.kt | 16 ++-- .../keepass/settings/PreferencesUtil.kt | 6 ++ app/src/main/res/values/donottranslate.xml | 2 + app/src/main/res/values/strings.xml | 2 + .../main/res/xml/form_filling_preferences.xml | 5 ++ 11 files changed, 86 insertions(+), 56 deletions(-) rename app/src/main/java/com/kunzisoft/keepass/notifications/{NotificationCopyingField.kt => ClipboardEntryNotificationField.kt} (88%) rename app/src/main/java/com/kunzisoft/keepass/notifications/{CopyingEntryNotificationService.kt => ClipboardEntryNotificationService.kt} (78%) rename app/src/main/java/com/kunzisoft/keepass/{magikeyboard => notifications}/KeyboardEntryNotificationService.kt (94%) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 4b4abb09b..9906df0b5 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -146,7 +146,7 @@ android:enabled="true" android:exported="false" /> @@ -171,7 +171,10 @@ - + 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 7ceb0c44e..5d014dd38 100644 --- a/app/src/main/java/com/kunzisoft/keepass/activities/EntryActivity.kt +++ b/app/src/main/java/com/kunzisoft/keepass/activities/EntryActivity.kt @@ -43,7 +43,7 @@ import com.kunzisoft.keepass.database.element.PwNodeId import com.kunzisoft.keepass.education.EntryActivityEducation import com.kunzisoft.keepass.icons.assignDatabaseIcon import com.kunzisoft.keepass.magikeyboard.MagikIME -import com.kunzisoft.keepass.notifications.CopyingEntryNotificationService +import com.kunzisoft.keepass.notifications.ClipboardEntryNotificationService import com.kunzisoft.keepass.settings.PreferencesUtil import com.kunzisoft.keepass.settings.PreferencesUtil.isFirstTimeAskAllowCopyPasswordAndProtectedFields import com.kunzisoft.keepass.settings.SettingsAutofillActivity @@ -133,7 +133,7 @@ class EntryActivity : LockingHideActivity() { // Manage entry copy to start notification if allowed if (firstLaunchOfActivity) { // Manage entry to launch copying notification if allowed - CopyingEntryNotificationService.launchNotificationIfAllowed(this, entryInfo) + ClipboardEntryNotificationService.launchNotificationIfAllowed(this, entryInfo) // Manage entry to populate Magikeyboard and launch keyboard notification if allowed if (PreferencesUtil.isKeyboardEntrySelectionEnable(this)) { MagikIME.addEntryAndLaunchNotificationIfAllowed(this, entryInfo) diff --git a/app/src/main/java/com/kunzisoft/keepass/activities/lock/LockingActivity.kt b/app/src/main/java/com/kunzisoft/keepass/activities/lock/LockingActivity.kt index 21153aca3..830af1180 100644 --- a/app/src/main/java/com/kunzisoft/keepass/activities/lock/LockingActivity.kt +++ b/app/src/main/java/com/kunzisoft/keepass/activities/lock/LockingActivity.kt @@ -33,7 +33,7 @@ import com.kunzisoft.keepass.activities.helpers.EntrySelectionHelper import com.kunzisoft.keepass.activities.helpers.ReadOnlyHelper import com.kunzisoft.keepass.activities.stylish.StylishActivity import com.kunzisoft.keepass.database.element.Database -import com.kunzisoft.keepass.magikeyboard.KeyboardEntryNotificationService +import com.kunzisoft.keepass.notifications.KeyboardEntryNotificationService import com.kunzisoft.keepass.magikeyboard.MagikIME import com.kunzisoft.keepass.settings.PreferencesUtil import com.kunzisoft.keepass.timeout.TimeoutHelper diff --git a/app/src/main/java/com/kunzisoft/keepass/magikeyboard/MagikIME.kt b/app/src/main/java/com/kunzisoft/keepass/magikeyboard/MagikIME.kt index 13e642325..60c9faa0e 100644 --- a/app/src/main/java/com/kunzisoft/keepass/magikeyboard/MagikIME.kt +++ b/app/src/main/java/com/kunzisoft/keepass/magikeyboard/MagikIME.kt @@ -40,6 +40,7 @@ import com.kunzisoft.keepass.R import com.kunzisoft.keepass.magikeyboard.adapter.FieldsAdapter import com.kunzisoft.keepass.model.EntryInfo import com.kunzisoft.keepass.model.Field +import com.kunzisoft.keepass.notifications.KeyboardEntryNotificationService import com.kunzisoft.keepass.settings.PreferencesUtil import com.kunzisoft.keepass.utils.LOCK_ACTION import com.kunzisoft.keepass.utils.REMOVE_ENTRY_MAGIKEYBOARD_ACTION diff --git a/app/src/main/java/com/kunzisoft/keepass/notifications/NotificationCopyingField.kt b/app/src/main/java/com/kunzisoft/keepass/notifications/ClipboardEntryNotificationField.kt similarity index 88% rename from app/src/main/java/com/kunzisoft/keepass/notifications/NotificationCopyingField.kt rename to app/src/main/java/com/kunzisoft/keepass/notifications/ClipboardEntryNotificationField.kt index 4074f4ed8..08d5a411a 100644 --- a/app/src/main/java/com/kunzisoft/keepass/notifications/NotificationCopyingField.kt +++ b/app/src/main/java/com/kunzisoft/keepass/notifications/ClipboardEntryNotificationField.kt @@ -31,7 +31,7 @@ import java.util.ArrayList /** * Utility class to manage fields in Notifications */ -open class NotificationCopyingField : Parcelable { +open class ClipboardEntryNotificationField : Parcelable { private var id: NotificationFieldId = NotificationFieldId.UNKNOWN var value: String @@ -79,7 +79,7 @@ open class NotificationCopyingField : Parcelable { override fun equals(other: Any?): Boolean { if (this === other) return true if (other == null || javaClass != other.javaClass) return false - val field = other as NotificationCopyingField + val field = other as ClipboardEntryNotificationField return id == field.id } @@ -111,15 +111,15 @@ open class NotificationCopyingField : Parcelable { companion object { - private val TAG = NotificationCopyingField::class.java.name + private val TAG = ClipboardEntryNotificationField::class.java.name @JvmField - val CREATOR: Parcelable.Creator = object : Parcelable.Creator { - override fun createFromParcel(`in`: Parcel): NotificationCopyingField { - return NotificationCopyingField(`in`) + val CREATOR: Parcelable.Creator = object : Parcelable.Creator { + override fun createFromParcel(`in`: Parcel): ClipboardEntryNotificationField { + return ClipboardEntryNotificationField(`in`) } - override fun newArray(size: Int): Array { + override fun newArray(size: Int): Array { return arrayOfNulls(size) } } diff --git a/app/src/main/java/com/kunzisoft/keepass/notifications/CopyingEntryNotificationService.kt b/app/src/main/java/com/kunzisoft/keepass/notifications/ClipboardEntryNotificationService.kt similarity index 78% rename from app/src/main/java/com/kunzisoft/keepass/notifications/CopyingEntryNotificationService.kt rename to app/src/main/java/com/kunzisoft/keepass/notifications/ClipboardEntryNotificationService.kt index 204ce8b54..4fd652678 100644 --- a/app/src/main/java/com/kunzisoft/keepass/notifications/CopyingEntryNotificationService.kt +++ b/app/src/main/java/com/kunzisoft/keepass/notifications/ClipboardEntryNotificationService.kt @@ -30,16 +30,17 @@ import com.kunzisoft.keepass.model.EntryInfo import com.kunzisoft.keepass.settings.PreferencesUtil import com.kunzisoft.keepass.timeout.ClipboardHelper import com.kunzisoft.keepass.timeout.TimeoutHelper.NEVER +import com.kunzisoft.keepass.utils.LOCK_ACTION import java.util.* -class CopyingEntryNotificationService : NotificationService() { +class ClipboardEntryNotificationService : NotificationService() { private var notificationId = 485 - private var cleanNotificationTimer: Thread? = null + private var cleanNotificationTimerTask: Thread? = null private var notificationTimeoutMilliSecs: Long = 0 private var clipboardHelper: ClipboardHelper? = null - private var countingDownTask: Thread? = null + private var cleanCopyNotificationTimerTask: Thread? = null override fun onCreate() { super.onCreate() @@ -47,6 +48,13 @@ class CopyingEntryNotificationService : NotificationService() { clipboardHelper = ClipboardHelper(this) } + private fun stopNotificationAndSendLockIfNeeded() { + // Clear the entry if define in preferences + if (PreferencesUtil.isClearClipboardNotificationEnable(this)) { + sendBroadcast(Intent(LOCK_ACTION)) + } + } + override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { //Get settings val prefs = PreferenceManager.getDefaultSharedPreferences(this) @@ -61,17 +69,18 @@ class CopyingEntryNotificationService : NotificationService() { newNotification(title, constructListOfField(intent)) } ACTION_CLEAN_CLIPBOARD == intent.action -> { - stopTask(countingDownTask) + stopTask(cleanCopyNotificationTimerTask) try { clipboardHelper?.cleanClipboard() } catch (e: SamsungClipboardException) { Log.e(TAG, "Clipboard can't be cleaned", e) } + stopNotificationAndSendLockIfNeeded() } - else -> for (actionKey in NotificationCopyingField.allActionKeys) { + else -> for (actionKey in ClipboardEntryNotificationField.allActionKeys) { if (actionKey == intent.action) { - val fieldToCopy = intent.getParcelableExtra( - NotificationCopyingField.getExtraKeyLinkToActionKey(actionKey)) + val fieldToCopy = intent.getParcelableExtra( + ClipboardEntryNotificationField.getExtraKeyLinkToActionKey(actionKey)) val nextFields = constructListOfField(intent) // Remove the current field from the next fields nextFields.remove(fieldToCopy) @@ -82,8 +91,8 @@ class CopyingEntryNotificationService : NotificationService() { return START_NOT_STICKY } - private fun constructListOfField(intent: Intent?): ArrayList { - var fieldList = ArrayList() + private fun constructListOfField(intent: Intent?): ArrayList { + var fieldList = ArrayList() if (intent != null && intent.extras != null) { if (intent.extras!!.containsKey(EXTRA_FIELDS)) fieldList = intent.getParcelableArrayListExtra(EXTRA_FIELDS) @@ -91,8 +100,8 @@ class CopyingEntryNotificationService : NotificationService() { return fieldList } - private fun getCopyPendingIntent(fieldToCopy: NotificationCopyingField, fieldsToAdd: ArrayList): PendingIntent { - val copyIntent = Intent(this, CopyingEntryNotificationService::class.java) + private fun getCopyPendingIntent(fieldToCopy: ClipboardEntryNotificationField, fieldsToAdd: ArrayList): PendingIntent { + val copyIntent = Intent(this, ClipboardEntryNotificationService::class.java) copyIntent.action = fieldToCopy.actionKey copyIntent.putExtra(fieldToCopy.extraKey, fieldToCopy) copyIntent.putParcelableArrayListExtra(EXTRA_FIELDS, fieldsToAdd) @@ -101,8 +110,8 @@ class CopyingEntryNotificationService : NotificationService() { this, 0, copyIntent, PendingIntent.FLAG_UPDATE_CURRENT) } - private fun newNotification(title: String?, fieldsToAdd: ArrayList) { - stopTask(countingDownTask) + private fun newNotification(title: String?, fieldsToAdd: ArrayList) { + stopTask(cleanCopyNotificationTimerTask) val builder = buildNewNotification() .setSmallIcon(R.drawable.ic_key_white_24dp) @@ -129,24 +138,24 @@ class CopyingEntryNotificationService : NotificationService() { notificationManager?.notify(++notificationId, builder.build()) val myNotificationId = notificationId - stopTask(cleanNotificationTimer) + stopTask(cleanNotificationTimerTask) // If timer if (notificationTimeoutMilliSecs != NEVER) { - cleanNotificationTimer = Thread { + cleanNotificationTimerTask = Thread { try { Thread.sleep(notificationTimeoutMilliSecs) } catch (e: InterruptedException) { - cleanNotificationTimer = null + cleanNotificationTimerTask = null } notificationManager?.cancel(myNotificationId) } - cleanNotificationTimer?.start() + cleanNotificationTimerTask?.start() } } - private fun copyField(fieldToCopy: NotificationCopyingField, nextFields: ArrayList) { - stopTask(countingDownTask) - stopTask(cleanNotificationTimer) + private fun copyField(fieldToCopy: ClipboardEntryNotificationField, nextFields: ArrayList) { + stopTask(cleanCopyNotificationTimerTask) + stopTask(cleanNotificationTimerTask) try { clipboardHelper?.copyToClipboard(fieldToCopy.label, fieldToCopy.value) @@ -165,7 +174,7 @@ class CopyingEntryNotificationService : NotificationService() { builder.setContentText(getString(R.string.clipboard_swipe_clean)) } - val cleanIntent = Intent(this, CopyingEntryNotificationService::class.java) + val cleanIntent = Intent(this, ClipboardEntryNotificationService::class.java) cleanIntent.action = ACTION_CLEAN_CLIPBOARD val cleanPendingIntent = PendingIntent.getService( this, 0, cleanIntent, PendingIntent.FLAG_UPDATE_CURRENT) @@ -174,10 +183,10 @@ class CopyingEntryNotificationService : NotificationService() { val myNotificationId = notificationId if (notificationTimeoutMilliSecs != NEVER) { - countingDownTask = Thread { + cleanCopyNotificationTimerTask = Thread { val maxPos = 100 val posDurationMills = notificationTimeoutMilliSecs / maxPos - for (pos in maxPos downTo 1) { + for (pos in maxPos downTo 0) { builder.setProgress(maxPos, pos, false) notificationManager?.notify(myNotificationId, builder.build()) try { @@ -185,9 +194,11 @@ class CopyingEntryNotificationService : NotificationService() { } catch (e: InterruptedException) { break } - + if (pos <= 0) { + stopNotificationAndSendLockIfNeeded() + } } - countingDownTask = null + stopTask(cleanCopyNotificationTimerTask) notificationManager?.cancel(myNotificationId) // Clean password only if no next field if (nextFields.size <= 0) @@ -197,7 +208,7 @@ class CopyingEntryNotificationService : NotificationService() { Log.e(TAG, "Clipboard can't be cleaned", e) } } - countingDownTask?.start() + cleanCopyNotificationTimerTask?.start() } else { // No timer notificationManager?.notify(myNotificationId, builder.build()) @@ -216,7 +227,7 @@ class CopyingEntryNotificationService : NotificationService() { companion object { - private val TAG = CopyingEntryNotificationService::class.java.name + private val TAG = ClipboardEntryNotificationService::class.java.name const val ACTION_NEW_NOTIFICATION = "ACTION_NEW_NOTIFICATION" const val EXTRA_ENTRY_TITLE = "EXTRA_ENTRY_TITLE" @@ -240,23 +251,23 @@ class CopyingEntryNotificationService : NotificationService() { if (containsUsernameToCopy || containsPasswordToCopy || containsExtraFieldToCopy) { // username already copied, waiting for user's action before copy password. - val intent = Intent(context, CopyingEntryNotificationService::class.java) + val intent = Intent(context, ClipboardEntryNotificationService::class.java) intent.action = ACTION_NEW_NOTIFICATION intent.putExtra(EXTRA_ENTRY_TITLE, entry.title) // Construct notification fields - val notificationFields = ArrayList() + val notificationFields = ArrayList() // Add username if exists to notifications if (containsUsernameToCopy) notificationFields.add( - NotificationCopyingField( - NotificationCopyingField.NotificationFieldId.USERNAME, + ClipboardEntryNotificationField( + ClipboardEntryNotificationField.NotificationFieldId.USERNAME, entry.username, context.resources)) // Add password to notifications if (containsPasswordToCopy) { notificationFields.add( - NotificationCopyingField( - NotificationCopyingField.NotificationFieldId.PASSWORD, + ClipboardEntryNotificationField( + ClipboardEntryNotificationField.NotificationFieldId.PASSWORD, entry.password, context.resources)) } @@ -269,8 +280,8 @@ class CopyingEntryNotificationService : NotificationService() { if (!field.protectedValue.isProtected || PreferencesUtil.allowCopyPasswordAndProtectedFields(context)) { notificationFields.add( - NotificationCopyingField( - NotificationCopyingField.NotificationFieldId.anonymousFieldId[anonymousFieldNumber], + ClipboardEntryNotificationField( + ClipboardEntryNotificationField.NotificationFieldId.anonymousFieldId[anonymousFieldNumber], field.protectedValue.toString(), field.name, context.resources)) @@ -278,7 +289,7 @@ class CopyingEntryNotificationService : NotificationService() { } } } catch (e: ArrayIndexOutOfBoundsException) { - Log.w("NotificationEntryCopyMg", "Only " + NotificationCopyingField.NotificationFieldId.anonymousFieldId.size + + Log.w("NotificationEntryCopyMg", "Only " + ClipboardEntryNotificationField.NotificationFieldId.anonymousFieldId.size + " anonymous notifications are available") } diff --git a/app/src/main/java/com/kunzisoft/keepass/magikeyboard/KeyboardEntryNotificationService.kt b/app/src/main/java/com/kunzisoft/keepass/notifications/KeyboardEntryNotificationService.kt similarity index 94% rename from app/src/main/java/com/kunzisoft/keepass/magikeyboard/KeyboardEntryNotificationService.kt rename to app/src/main/java/com/kunzisoft/keepass/notifications/KeyboardEntryNotificationService.kt index 4a6272554..9024f0d86 100644 --- a/app/src/main/java/com/kunzisoft/keepass/magikeyboard/KeyboardEntryNotificationService.kt +++ b/app/src/main/java/com/kunzisoft/keepass/notifications/KeyboardEntryNotificationService.kt @@ -1,4 +1,4 @@ -package com.kunzisoft.keepass.magikeyboard +package com.kunzisoft.keepass.notifications import android.app.PendingIntent import android.content.BroadcastReceiver @@ -8,8 +8,8 @@ import android.content.IntentFilter import android.support.v7.preference.PreferenceManager import android.util.Log import com.kunzisoft.keepass.R +import com.kunzisoft.keepass.magikeyboard.MagikIME import com.kunzisoft.keepass.model.EntryInfo -import com.kunzisoft.keepass.notifications.NotificationService import com.kunzisoft.keepass.settings.PreferencesUtil import com.kunzisoft.keepass.timeout.TimeoutHelper import com.kunzisoft.keepass.utils.LOCK_ACTION @@ -17,7 +17,7 @@ import com.kunzisoft.keepass.utils.LOCK_ACTION class KeyboardEntryNotificationService : NotificationService() { private val notificationId = 486 - private var cleanNotificationTimer: Thread? = null + private var cleanNotificationTimerTask: Thread? = null private var notificationTimeoutMilliSecs: Long = 0 private var lockBroadcastReceiver: BroadcastReceiver? = null @@ -95,7 +95,7 @@ class KeyboardEntryNotificationService : NotificationService() { notificationManager?.notify(notificationId, builder.build()) - stopTask(cleanNotificationTimer) + stopTask(cleanNotificationTimerTask) // Timeout only if notification clear is available val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this) if (sharedPreferences.getBoolean(getString(R.string.keyboard_notification_entry_clear_close_key), @@ -109,7 +109,7 @@ class KeyboardEntryNotificationService : NotificationService() { } if (notificationTimeoutMilliSecs != TimeoutHelper.NEVER) { - cleanNotificationTimer = Thread { + cleanNotificationTimerTask = Thread { val maxPos = 100 val posDurationMills = notificationTimeoutMilliSecs / maxPos for (pos in maxPos downTo 0) { @@ -125,7 +125,7 @@ class KeyboardEntryNotificationService : NotificationService() { } } } - cleanNotificationTimer?.start() + cleanNotificationTimerTask?.start() } } } @@ -136,8 +136,8 @@ class KeyboardEntryNotificationService : NotificationService() { } private fun destroyKeyboardNotification() { - stopTask(cleanNotificationTimer) - cleanNotificationTimer = null + stopTask(cleanNotificationTimerTask) + cleanNotificationTimerTask = null unregisterReceiver(lockBroadcastReceiver) pendingDeleteIntent?.cancel() diff --git a/app/src/main/java/com/kunzisoft/keepass/settings/PreferencesUtil.kt b/app/src/main/java/com/kunzisoft/keepass/settings/PreferencesUtil.kt index 3c64f9ed5..b760b8384 100644 --- a/app/src/main/java/com/kunzisoft/keepass/settings/PreferencesUtil.kt +++ b/app/src/main/java/com/kunzisoft/keepass/settings/PreferencesUtil.kt @@ -184,6 +184,12 @@ object PreferencesUtil { context.resources.getBoolean(R.bool.allow_copy_password_default)) } + fun isClearClipboardNotificationEnable(context: Context): Boolean { + val prefs = PreferenceManager.getDefaultSharedPreferences(context) + return prefs.getBoolean(context.getString(R.string.clear_clipboard_notification_key), + context.resources.getBoolean(R.bool.clear_clipboard_notification_default)) + } + fun setAllowCopyPasswordAndProtectedFields(context: Context, allowCopy: Boolean) { val prefs = PreferenceManager.getDefaultSharedPreferences(context) prefs.edit() diff --git a/app/src/main/res/values/donottranslate.xml b/app/src/main/res/values/donottranslate.xml index 8159a3d04..c62175a17 100644 --- a/app/src/main/res/values/donottranslate.xml +++ b/app/src/main/res/values/donottranslate.xml @@ -86,6 +86,8 @@ true allow_copy_password_key false + clear_clipboard_notification_key + false recentfile true keyfile diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 8156593f9..09103a1c0 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -270,6 +270,8 @@ Clipboard trust Allow the entry password and protected fields to enter the clipboard WARNING: The clipboard is shared by all apps. If sensitive data is copied, other software may recover it. + Clear at closing + Close the database when closing the notification WARNING: Turning off this feature may prevent opening or saving databases. Link of database file to open Database name diff --git a/app/src/main/res/xml/form_filling_preferences.xml b/app/src/main/res/xml/form_filling_preferences.xml index 4de7e0058..9889666b6 100644 --- a/app/src/main/res/xml/form_filling_preferences.xml +++ b/app/src/main/res/xml/form_filling_preferences.xml @@ -42,6 +42,11 @@ android:title="@string/allow_copy_password_title" android:summary="@string/allow_copy_password_summary" android:defaultValue="@bool/allow_copy_password_default"/> +