Merge branch 'feature/Button_Block_Autofill' into develop

This commit is contained in:
J-Jamet
2020-06-18 14:14:58 +02:00
30 changed files with 367 additions and 209 deletions

View File

@@ -69,7 +69,7 @@ android {
buildConfigField "String", "BUILD_VERSION", "\"free\""
buildConfigField "boolean", "FULL_VERSION", "false"
buildConfigField "boolean", "CLOSED_STORE", "true"
buildConfigField "String[]", "STYLES_DISABLED", "{\"KeepassDXStyle_Dark\",\"KeepassDXStyle_Blue\",\"KeepassDXStyle_Red\",\"KeepassDXStyle_Purple\"}"
buildConfigField "String[]", "STYLES_DISABLED", "{}"
buildConfigField "String[]", "ICON_PACKS_DISABLED", "{}"
manifestPlaceholders = [ googleAndroidBackupAPIKey:"AEdPqrEAAAAIbRfbV8fHLItXo8OcHwrO0sSNblqhPwkc0DPTqg" ]
}

View File

@@ -26,25 +26,43 @@ import android.content.Intent
import android.content.IntentSender
import android.os.Build
import android.os.Bundle
import android.widget.Toast
import androidx.annotation.RequiresApi
import androidx.appcompat.app.AppCompatActivity
import com.kunzisoft.keepass.R
import com.kunzisoft.keepass.autofill.AutofillHelper
import com.kunzisoft.keepass.autofill.KeeAutofillService
import com.kunzisoft.keepass.database.element.Database
import com.kunzisoft.keepass.database.search.SearchHelper
import com.kunzisoft.keepass.model.SearchInfo
import com.kunzisoft.keepass.settings.PreferencesUtil
@RequiresApi(api = Build.VERSION_CODES.O)
class AutofillLauncherActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
// Build search param
val searchInfo = SearchInfo().apply {
applicationId = intent.getStringExtra(KEY_SEARCH_APPLICATION_ID)
webDomain = intent.getStringExtra(KEY_SEARCH_DOMAIN)
}
// Pass extra for Autofill (EXTRA_ASSIST_STRUCTURE)
val assistStructure = AutofillHelper.retrieveAssistStructure(intent)
if (assistStructure != null) {
// Build search param
val searchInfo = SearchInfo().apply {
applicationId = intent.getStringExtra(KEY_SEARCH_APPLICATION_ID)
webDomain = intent.getStringExtra(KEY_SEARCH_DOMAIN)
}
if (assistStructure == null) {
setResult(Activity.RESULT_CANCELED)
finish()
} else if (!KeeAutofillService.searchAllowedFor(searchInfo.applicationId,
PreferencesUtil.applicationIdBlocklist(this))
|| !KeeAutofillService.searchAllowedFor(searchInfo.webDomain,
PreferencesUtil.webDomainBlocklist(this))) {
// If item not allowed, show a toast
Toast.makeText(this.applicationContext, R.string.autofill_block_restart, Toast.LENGTH_LONG).show()
setResult(Activity.RESULT_CANCELED)
finish()
} else {
// If database is open
SearchHelper.checkAutoSearchInfo(this,
Database.getInstance(),
@@ -57,17 +75,17 @@ class AutofillLauncherActivity : AppCompatActivity() {
{
// Show the database UI to select the entry
GroupActivity.launchForAutofillResult(this,
assistStructure)
assistStructure,
false,
searchInfo)
},
{
// If database not open
FileDatabaseSelectActivity.launchForAutofillResult(this,
assistStructure, searchInfo)
assistStructure,
searchInfo)
}
)
} else {
setResult(Activity.RESULT_CANCELED)
finish()
}
super.onCreate(savedInstanceState)

View File

@@ -24,6 +24,7 @@ import android.content.Intent
import android.net.Uri
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import com.kunzisoft.keepass.R
import com.kunzisoft.keepass.activities.helpers.EntrySelectionHelper
import com.kunzisoft.keepass.database.element.Database
import com.kunzisoft.keepass.database.search.SearchHelper
@@ -54,14 +55,14 @@ class EntrySelectionLauncherActivity : AppCompatActivity() {
else -> {}
}
// Setting to integrate Magikeyboard
val searchShareForMagikeyboard = PreferencesUtil.isKeyboardSearchShareEnable(this)
// Build search param
val searchInfo = SearchInfo().apply {
webDomain = sharedWebDomain
}
// Setting to integrate Magikeyboard
val searchShareForMagikeyboard = PreferencesUtil.isKeyboardSearchShareEnable(this)
// If database is open
SearchHelper.checkAutoSearchInfo(this,
Database.getInstance(),
@@ -72,29 +73,41 @@ class EntrySelectionLauncherActivity : AppCompatActivity() {
if (items.size == 1) {
// Automatically populate keyboard
val entryPopulate = items[0]
populateKeyboardAndMoveAppToBackground(this, entryPopulate, intent)
populateKeyboardAndMoveAppToBackground(this,
entryPopulate,
intent)
} else {
// Select the one we want
GroupActivity.launchForEntrySelectionResult(this, searchInfo)
GroupActivity.launchForEntrySelectionResult(this,
true,
searchInfo)
}
} else {
GroupActivity.launch(this, searchInfo)
GroupActivity.launch(this,
true,
searchInfo)
}
},
{
// Show the database UI to select the entry
if (searchShareForMagikeyboard) {
GroupActivity.launchForEntrySelectionResult(this)
GroupActivity.launchForEntrySelectionResult(this,
false,
searchInfo)
} else {
GroupActivity.launch(this)
GroupActivity.launch(this,
false,
searchInfo)
}
},
{
// If database not open
if (searchShareForMagikeyboard) {
FileDatabaseSelectActivity.launchForEntrySelectionResult(this, searchInfo)
FileDatabaseSelectActivity.launchForEntrySelectionResult(this,
searchInfo)
} else {
FileDatabaseSelectActivity.launch(this, searchInfo)
FileDatabaseSelectActivity.launch(this,
searchInfo)
}
}
)

View File

@@ -55,7 +55,6 @@ import com.kunzisoft.keepass.model.SearchInfo
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_CREATE_TASK
import com.kunzisoft.keepass.settings.PreferencesUtil
import com.kunzisoft.keepass.utils.*
import com.kunzisoft.keepass.view.SpecialModeView
import com.kunzisoft.keepass.view.asError
import kotlinx.android.synthetic.main.activity_file_selection.*
import java.io.FileNotFoundException
@@ -69,7 +68,6 @@ class FileDatabaseSelectActivity : SpecialModeActivity(),
private var databaseButtonsContainerView: View? = null
private var createDatabaseButtonView: View? = null
private var openDatabaseButtonView: View? = null
private var specialModeView: SpecialModeView? = null
// Adapter to manage database history list
private var mAdapterDatabaseHistory: FileDatabaseHistoryAdapter? = null
@@ -115,9 +113,6 @@ class FileDatabaseSelectActivity : SpecialModeActivity(),
}
}
// Special mode view
specialModeView = findViewById(R.id.special_mode_view)
// History list
val fileDatabaseHistoryRecyclerView = findViewById<RecyclerView>(R.id.file_list)
fileDatabaseHistoryRecyclerView.layoutManager = LinearLayoutManager(this, RecyclerView.VERTICAL, false)
@@ -241,11 +236,13 @@ class FileDatabaseSelectActivity : SpecialModeActivity(),
EntrySelectionHelper.doEntrySelectionAction(intent,
{
GroupActivity.launch(this@FileDatabaseSelectActivity,
false,
searchInfo,
readOnly)
},
{
GroupActivity.launchForEntrySelectionResult(this@FileDatabaseSelectActivity,
false,
searchInfo,
readOnly)
// Do not keep history
@@ -255,6 +252,7 @@ class FileDatabaseSelectActivity : SpecialModeActivity(),
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
GroupActivity.launchForAutofillResult(this@FileDatabaseSelectActivity,
assistStructure,
false,
searchInfo,
readOnly)
}
@@ -271,14 +269,6 @@ class FileDatabaseSelectActivity : SpecialModeActivity(),
override fun onResume() {
super.onResume()
// To show the selection mode
specialModeView?.apply {
visible = mSelectionMode
onCancelButtonClickListener = View.OnClickListener {
onBackPressed()
}
}
// Show open and create button or special mode
if (mSelectionMode) {
// Disable buttons if in selection mode or request for autofill

View File

@@ -94,7 +94,6 @@ class GroupActivity : LockingActivity(),
private var toolbarAction: ToolbarAction? = null
private var iconView: ImageView? = null
private var numberChildrenView: TextView? = null
private var specialModeView: SpecialModeView? = null
private var addNodeButtonView: AddNodeButtonView? = null
private var groupNameView: TextView? = null
@@ -136,7 +135,6 @@ class GroupActivity : LockingActivity(),
searchTitleView = findViewById(R.id.search_title)
groupNameView = findViewById(R.id.group_name)
toolbarAction = findViewById(R.id.toolbar_action)
specialModeView = findViewById(R.id.special_mode_view)
lockView = findViewById(R.id.lock_button)
lockView?.setOnClickListener {
@@ -286,7 +284,7 @@ class GroupActivity : LockingActivity(),
intent?.let { intentNotNull ->
// To transform KEY_SEARCH_INFO in ACTION_SEARCH
manageSearchInfoIntent(intent)
manageSearchInfoIntent(intentNotNull)
Log.d(TAG, "setNewIntent: $intentNotNull")
setIntent(intentNotNull)
mCurrentGroupIsASearch = if (Intent.ACTION_SEARCH == intentNotNull.action) {
@@ -306,9 +304,9 @@ class GroupActivity : LockingActivity(),
private fun manageSearchInfoIntent(intent: Intent): Boolean {
// To relaunch the activity as ACTION_SEARCH
val searchInfo: SearchInfo? = intent.getParcelableExtra(KEY_SEARCH_INFO)
if (searchInfo != null) {
val autoSearch = intent.getBooleanExtra(AUTO_SEARCH_KEY, false)
if (searchInfo != null && autoSearch) {
intent.action = Intent.ACTION_SEARCH
intent.removeExtra(KEY_SEARCH_INFO)
intent.putExtra(SearchManager.QUERY, searchInfo.getSearchString(this))
return true
}
@@ -463,24 +461,6 @@ class GroupActivity : LockingActivity(),
// Assign number of children
refreshNumberOfChildren()
// Show selection mode message if needed
specialModeView?.apply {
visible = mSelectionMode
onCancelButtonClickListener = View.OnClickListener {
// To remove the navigation history and
EntrySelectionHelper.removeEntrySelectionModeFromIntent(intent)
val fragmentManager = supportFragmentManager
if (mSelectionModeCountBackStack > 0) {
for (selectionMode in 0 .. mSelectionModeCountBackStack) {
fragmentManager.popBackStack()
}
}
// Reinit the counter for navigation history
mSelectionModeCountBackStack = 0
backToTheAppCaller()
}
}
// Show button if allowed
addNodeButtonView?.apply {
@@ -498,6 +478,20 @@ class GroupActivity : LockingActivity(),
}
}
override fun onCancelSpecialMode() {
// To remove the navigation history and
EntrySelectionHelper.removeEntrySelectionModeFromIntent(intent)
val fragmentManager = supportFragmentManager
if (mSelectionModeCountBackStack > 0) {
for (selectionMode in 0 .. mSelectionModeCountBackStack) {
fragmentManager.popBackStack()
}
}
// Reinit the counter for navigation history
mSelectionModeCountBackStack = 0
backToTheAppCaller()
}
private fun refreshNumberOfChildren() {
numberChildrenView?.apply {
if (PreferencesUtil.showNumberEntries(context)) {
@@ -1002,6 +996,8 @@ class GroupActivity : LockingActivity(),
}
// Else in root, lock if needed
else {
intent.removeExtra(AUTO_SEARCH_KEY)
intent.removeExtra(KEY_SEARCH_INFO)
if (PreferencesUtil.isLockDatabaseWhenBackButtonOnRootClicked(this)) {
lockAndExit()
super.onBackPressed()
@@ -1023,6 +1019,7 @@ class GroupActivity : LockingActivity(),
private const val LIST_NODES_FRAGMENT_TAG = "LIST_NODES_FRAGMENT_TAG"
private const val SEARCH_FRAGMENT_TAG = "SEARCH_FRAGMENT_TAG"
private const val OLD_GROUP_TO_UPDATE_KEY = "OLD_GROUP_TO_UPDATE_KEY"
private const val AUTO_SEARCH_KEY = "AUTO_SEARCH_KEY"
private fun buildIntent(context: Context,
group: Group?,
@@ -1060,12 +1057,14 @@ class GroupActivity : LockingActivity(),
* -------------------------
*/
fun launch(context: Context,
autoSearch: Boolean = false,
searchInfo: SearchInfo? = null,
readOnly: Boolean = PreferencesUtil.enableReadOnlyDatabase(context)) {
checkTimeAndBuildIntent(context, null, readOnly) { intent ->
searchInfo?.let {
intent.putExtra(KEY_SEARCH_INFO, it)
}
intent.putExtra(AUTO_SEARCH_KEY, autoSearch)
context.startActivity(intent)
}
}
@@ -1076,9 +1075,11 @@ class GroupActivity : LockingActivity(),
* -------------------------
*/
fun launchForEntrySelectionResult(context: Context,
autoSearch: Boolean = false,
searchInfo: SearchInfo? = null,
readOnly: Boolean = PreferencesUtil.enableReadOnlyDatabase(context)) {
checkTimeAndBuildIntent(context, null, readOnly) { intent ->
intent.putExtra(AUTO_SEARCH_KEY, autoSearch)
EntrySelectionHelper.startActivityForEntrySelectionResult(context, intent, searchInfo)
}
}
@@ -1091,9 +1092,11 @@ class GroupActivity : LockingActivity(),
@RequiresApi(api = Build.VERSION_CODES.O)
fun launchForAutofillResult(activity: Activity,
assistStructure: AssistStructure,
autoSearch: Boolean = false,
searchInfo: SearchInfo? = null,
readOnly: Boolean = PreferencesUtil.enableReadOnlyDatabase(activity)) {
checkTimeAndBuildIntent(activity, null, readOnly) { intent ->
intent.putExtra(AUTO_SEARCH_KEY, autoSearch)
AutofillHelper.startActivityForAutofillResult(activity, intent, assistStructure, searchInfo)
}
}

View File

@@ -69,7 +69,6 @@ import com.kunzisoft.keepass.utils.MenuUtil
import com.kunzisoft.keepass.utils.UriUtil
import com.kunzisoft.keepass.view.AdvancedUnlockInfoView
import com.kunzisoft.keepass.view.KeyFileSelectionView
import com.kunzisoft.keepass.view.SpecialModeView
import com.kunzisoft.keepass.view.asError
import kotlinx.android.synthetic.main.activity_password.*
import java.io.FileNotFoundException
@@ -78,7 +77,6 @@ open class PasswordActivity : SpecialModeActivity() {
// Views
private var toolbar: Toolbar? = null
private var specialModeView: SpecialModeView? = null
private var filenameView: TextView? = null
private var passwordView: EditText? = null
private var keyFileSelectionView: KeyFileSelectionView? = null
@@ -125,7 +123,6 @@ open class PasswordActivity : SpecialModeActivity() {
supportActionBar?.setDisplayHomeAsUpEnabled(true)
supportActionBar?.setDisplayShowHomeEnabled(true)
specialModeView = findViewById(R.id.special_mode_view)
confirmButtonView = findViewById(R.id.activity_password_open_button)
filenameView = findViewById(R.id.filename)
passwordView = findViewById(R.id.password)
@@ -266,9 +263,10 @@ open class PasswordActivity : SpecialModeActivity() {
EntrySelectionHelper.doEntrySelectionAction(intent,
{
GroupActivity.launch(this@PasswordActivity,
true,
searchInfo,
readOnly)
// Remove the search info from intent
// Finish activity if no search info
if (searchInfo != null) {
finish()
}
@@ -285,13 +283,16 @@ open class PasswordActivity : SpecialModeActivity() {
intent)
} else {
// Select the one we want
GroupActivity.launchForEntrySelectionResult(this, searchInfo)
GroupActivity.launchForEntrySelectionResult(this,
true,
searchInfo)
}
},
{
// Here no search info found
// Here no search info found, disable auto search
GroupActivity.launchForEntrySelectionResult(this@PasswordActivity,
null,
false,
searchInfo,
readOnly)
},
{
@@ -312,10 +313,11 @@ open class PasswordActivity : SpecialModeActivity() {
finish()
},
{
// Here no search info found
// Here no search info found, disable auto search
GroupActivity.launchForAutofillResult(this@PasswordActivity,
assistStructure,
null,
false,
searchInfo,
readOnly)
},
{
@@ -340,14 +342,6 @@ open class PasswordActivity : SpecialModeActivity() {
override fun onResume() {
super.onResume()
// To show the selection mode
specialModeView?.apply {
visible = mSelectionMode
onCancelButtonClickListener = View.OnClickListener {
onBackPressed()
}
}
if (Database.getInstance().loaded) {
launchGroupActivity()
} else {

View File

@@ -1,9 +1,15 @@
package com.kunzisoft.keepass.activities.selection
import android.os.Build
import android.view.View
import android.widget.Toast
import com.kunzisoft.keepass.R
import com.kunzisoft.keepass.activities.helpers.EntrySelectionHelper
import com.kunzisoft.keepass.activities.stylish.StylishActivity
import com.kunzisoft.keepass.autofill.AutofillHelper
import com.kunzisoft.keepass.model.SearchInfo
import com.kunzisoft.keepass.settings.PreferencesUtil
import com.kunzisoft.keepass.view.SpecialModeView
/**
* Activity to manage special mode (ie: selection mode)
@@ -14,6 +20,12 @@ abstract class SpecialModeActivity : StylishActivity() {
protected var mAutofillSelection: Boolean = false
private var specialModeView: SpecialModeView? = null
open fun onCancelSpecialMode() {
onBackPressed()
}
override fun onResume() {
super.onResume()
@@ -21,5 +33,58 @@ abstract class SpecialModeActivity : StylishActivity() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
mAutofillSelection = AutofillHelper.retrieveAssistStructure(intent) != null
}
val searchInfo: SearchInfo? = intent.getParcelableExtra(EntrySelectionHelper.KEY_SEARCH_INFO)
// To show the selection mode
specialModeView = findViewById(R.id.special_mode_view)
specialModeView?.apply {
// Populate title
val typeModeId = if (mAutofillSelection)
R.string.autofill
else
R.string.magic_keyboard_title
title = "${resources.getString(R.string.selection_mode)} (${getString(typeModeId)})"
// Populate subtitle
subtitle = searchInfo?.getName(resources)
// Show the toolbar or not
visible = mSelectionMode
// Add back listener
onCancelButtonClickListener = View.OnClickListener {
onCancelSpecialMode()
}
// Create menu
menu.clear()
if (mAutofillSelection) {
menuInflater.inflate(R.menu.autofill, menu)
setOnMenuItemClickListener { menuItem ->
when (menuItem.itemId) {
R.id.menu_block_autofill -> {
blockAutofill(searchInfo)
}
}
true
}
}
}
}
fun blockAutofill(searchInfo: SearchInfo?) {
val webDomain = searchInfo?.webDomain
val applicationId = searchInfo?.applicationId
if (webDomain != null) {
PreferencesUtil.addWebDomainToBlocklist(this,
webDomain)
} else if (applicationId != null) {
PreferencesUtil.addApplicationIdToBlocklist(this,
applicationId)
}
onCancelSpecialMode()
Toast.makeText(this.applicationContext,
R.string.autofill_block_restart,
Toast.LENGTH_LONG).show()
}
}

View File

@@ -119,29 +119,33 @@ object AutofillHelper {
* Build the Autofill response for many entry
*/
fun buildResponse(activity: Activity, entriesInfo: List<EntryInfo>) {
var setResultOk = false
activity.intent?.extras?.let { extras ->
if (extras.containsKey(ASSIST_STRUCTURE)) {
activity.intent?.getParcelableExtra<AssistStructure>(ASSIST_STRUCTURE)?.let { structure ->
StructureParser(structure).parse()?.let { result ->
// New Response
val responseBuilder = FillResponse.Builder()
entriesInfo.forEach {
responseBuilder.addDataset(buildDataset(activity, it, result))
if (entriesInfo.isEmpty()) {
activity.setResult(Activity.RESULT_CANCELED)
} else {
var setResultOk = false
activity.intent?.extras?.let { extras ->
if (extras.containsKey(ASSIST_STRUCTURE)) {
activity.intent?.getParcelableExtra<AssistStructure>(ASSIST_STRUCTURE)?.let { structure ->
StructureParser(structure).parse()?.let { result ->
// New Response
val responseBuilder = FillResponse.Builder()
entriesInfo.forEach {
responseBuilder.addDataset(buildDataset(activity, it, result))
}
val mReplyIntent = Intent()
Log.d(activity.javaClass.name, "Successed Autofill auth.")
mReplyIntent.putExtra(
AutofillManager.EXTRA_AUTHENTICATION_RESULT,
responseBuilder.build())
setResultOk = true
activity.setResult(Activity.RESULT_OK, mReplyIntent)
}
val mReplyIntent = Intent()
Log.d(activity.javaClass.name, "Successed Autofill auth.")
mReplyIntent.putExtra(
AutofillManager.EXTRA_AUTHENTICATION_RESULT,
responseBuilder.build())
setResultOk = true
activity.setResult(Activity.RESULT_OK, mReplyIntent)
}
}
}
if (!setResultOk) {
Log.w(activity.javaClass.name, "Failed Autofill auth.")
activity.setResult(Activity.RESULT_CANCELED)
if (!setResultOk) {
Log.w(activity.javaClass.name, "Failed Autofill auth.")
activity.setResult(Activity.RESULT_CANCELED)
}
}
}
}

View File

@@ -57,27 +57,8 @@ class KeeAutofillService : AutofillService() {
StructureParser(latestStructure).parse()?.let { parseResult ->
// Build search info only if applicationId or webDomain are not blocked
var searchAllowed = true
parseResult.applicationId?.let { appId ->
if (applicationIdBlocklist?.any { appIdBlocked ->
appId.contains(appIdBlocked)
} == true
) {
searchAllowed = false
Log.d(TAG, "Autofill not allowed for $appId")
}
}
parseResult.domain?.let { domain ->
if (webDomainBlocklist?.any { webDomainBlocked ->
domain.contains(webDomainBlocked)
} == true
) {
searchAllowed = false
Log.d(TAG, "Autofill not allowed for $domain")
}
}
if (searchAllowed) {
if (searchAllowedFor(parseResult.applicationId, applicationIdBlocklist)
&& searchAllowedFor(parseResult.domain, webDomainBlocklist)) {
val searchInfo = SearchInfo().apply {
applicationId = parseResult.applicationId
webDomain = parseResult.domain
@@ -150,5 +131,18 @@ class KeeAutofillService : AutofillService() {
companion object {
private val TAG = KeeAutofillService::class.java.name
fun searchAllowedFor(element: String?, blockList: Set<String>?): Boolean {
element?.let { elementNotNull ->
if (blockList?.any { appIdBlocked ->
elementNotNull.contains(appIdBlocked)
} == true
) {
Log.d(TAG, "Autofill not allowed for $elementNotNull")
return false
}
}
return true
}
}
}

View File

@@ -46,7 +46,7 @@ class SearchInfo : ObjectNameResource, Parcelable {
}
override fun getName(resources: Resources): String {
return applicationId ?: webDomain ?: ""
return toString()
}
fun containsOnlyNullValues(): Boolean {

View File

@@ -20,8 +20,10 @@
package com.kunzisoft.keepass.settings
import android.content.Context
import android.content.res.Resources
import android.net.Uri
import androidx.preference.PreferenceManager
import com.kunzisoft.keepass.BuildConfig
import com.kunzisoft.keepass.R
import com.kunzisoft.keepass.database.element.SortNodeEnum
import com.kunzisoft.keepass.timeout.TimeoutHelper
@@ -373,10 +375,20 @@ object PreferencesUtil {
context.resources.getBoolean(R.bool.autofill_auto_search_default))
}
/**
* Retrieve the default Blocklist for application ID, including the current app
*/
fun getDefaultApplicationIdBlocklist(resources: Resources?): Set<String> {
return resources?.getStringArray(R.array.autofill_application_id_blocklist_default)
?.toMutableSet()?.apply {
add(BuildConfig.APPLICATION_ID)
} ?: emptySet()
}
fun applicationIdBlocklist(context: Context): Set<String> {
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
return prefs.getStringSet(context.getString(R.string.autofill_application_id_blocklist_key),
context.resources.getStringArray(R.array.autofill_application_id_blocklist_default).toMutableSet())
getDefaultApplicationIdBlocklist(context.resources))
?: emptySet()
}
@@ -386,4 +398,22 @@ object PreferencesUtil {
context.resources.getStringArray(R.array.autofill_web_domain_blocklist_default).toMutableSet())
?: emptySet()
}
fun addApplicationIdToBlocklist(context: Context, applicationId: String) {
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
val setItems: MutableSet<String> = applicationIdBlocklist(context).toMutableSet()
setItems.add(applicationId)
prefs.edit()
.putStringSet(context.getString(R.string.autofill_application_id_blocklist_key), setItems)
.apply()
}
fun addWebDomainToBlocklist(context: Context, webDomain: String) {
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
val setItems: MutableSet<String> = webDomainBlocklist(context).toMutableSet()
setItems.add(webDomain)
prefs.edit()
.putStringSet(context.getString(R.string.autofill_web_domain_blocklist_key), setItems)
.apply()
}
}

View File

@@ -20,8 +20,8 @@
package com.kunzisoft.keepass.settings.preferencedialogfragment
import android.os.Bundle
import com.kunzisoft.keepass.R
import com.kunzisoft.keepass.model.SearchInfo
import com.kunzisoft.keepass.settings.PreferencesUtil
class AutofillBlocklistAppIdPreferenceDialogFragmentCompat
: AutofillBlocklistPreferenceDialogFragmentCompat() {
@@ -34,10 +34,7 @@ class AutofillBlocklistAppIdPreferenceDialogFragmentCompat
}
override fun getDefaultValues(): Set<String> {
return context?.resources
?.getStringArray(R.array.autofill_application_id_blocklist_default)
?.toMutableSet()
?: emptySet()
return PreferencesUtil.getDefaultApplicationIdBlocklist(this.resources)
}
companion object {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2019 Jeremy Jamet / Kunzisoft.
* Copyright 2020 Jeremy Jamet / Kunzisoft.
*
* This file is part of KeePassDX.
*
@@ -21,39 +21,24 @@ package com.kunzisoft.keepass.view
import android.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.View
import android.widget.TextView
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.appcompat.widget.Toolbar
import com.kunzisoft.keepass.R
class SpecialModeView @JvmOverloads constructor(context: Context,
attrs: AttributeSet? = null,
defStyle: Int = 0)
: ConstraintLayout(context, attrs, defStyle) {
private var cancelButton: View? = null
private var titleView: TextView? = null
defStyle: Int = androidx.appcompat.R.attr.toolbarStyle)
: Toolbar(context, attrs, defStyle) {
init {
val inflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater?
inflater?.inflate(R.layout.selection_mode_view, this)
cancelButton = findViewById(R.id.special_mode_cancel_button)
titleView = findViewById(R.id.special_mode_title_view)
setNavigationIcon(R.drawable.ic_close_white_24dp)
title = resources.getString(R.string.selection_mode)
}
var title: CharSequence?
get() {
return titleView?.text
}
set(value) {
titleView?.text = value
}
var onCancelButtonClickListener: OnClickListener? = null
set(value) {
cancelButton?.setOnClickListener(value)
if (value != null)
setNavigationOnClickListener(value)
}
var visible: Boolean = false

View File

@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#FFFFFF"
android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM4,12c0,-4.42 3.58,-8 8,-8 1.85,0 3.55,0.63 4.9,1.69L5.69,16.9C4.63,15.55 4,13.85 4,12zM12,20c-1.85,0 -3.55,-0.63 -4.9,-1.69L18.31,7.1C19.37,8.45 20,10.15 20,12c0,4.42 -3.58,8 -8,8z"/>
</vector>

View File

@@ -30,6 +30,9 @@
android:id="@+id/special_mode_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="?attr/specialToolbarAppearance"
app:titleTextAppearance="@style/KeepassDXStyle.TextAppearance.Toolbar.Special.Title"
app:subtitleTextAppearance="@style/KeepassDXStyle.TextAppearance.Toolbar.Special.SubTitle"
app:layout_constraintTop_toTopOf="parent" />
<androidx.coordinatorlayout.widget.CoordinatorLayout

View File

@@ -28,6 +28,9 @@
android:id="@+id/special_mode_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="?attr/specialToolbarAppearance"
app:titleTextAppearance="@style/KeepassDXStyle.TextAppearance.Toolbar.Special.Title"
app:subtitleTextAppearance="@style/KeepassDXStyle.TextAppearance.Toolbar.Special.SubTitle"
app:layout_constraintTop_toTopOf="parent" />
<androidx.coordinatorlayout.widget.CoordinatorLayout
@@ -159,7 +162,7 @@
android:layout_height="?attr/actionBarSize"
app:layout_constraintBottom_toBottomOf="parent"
android:elevation="4dp"
android:theme="?attr/toolbarBottomAppearance"
android:theme="?attr/actionToolbarAppearance"
android:background="?attr/colorAccent"
tools:targetApi="lollipop" />

View File

@@ -29,6 +29,9 @@
android:id="@+id/special_mode_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="?attr/specialToolbarAppearance"
app:titleTextAppearance="@style/KeepassDXStyle.TextAppearance.Toolbar.Special.Title"
app:subtitleTextAppearance="@style/KeepassDXStyle.TextAppearance.Toolbar.Special.SubTitle"
app:layout_constraintTop_toTopOf="parent" />
<androidx.coordinatorlayout.widget.CoordinatorLayout
@@ -218,7 +221,7 @@
android:paddingLeft="24dp"
android:paddingEnd="24dp"
android:paddingRight="24dp"
style="@style/KeepassDXStyle.TextAppearance.TinyText"
style="@style/KeepassDXStyle.TextAppearance.Tiny"
android:text="@string/warning_database_link_revoked"
android:textColor="?attr/textColorInverse"
android:background="?attr/colorAccent"

View File

@@ -58,7 +58,7 @@
android:id="@+id/item_attachment_compression"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/KeepassDXStyle.TextAppearance.TinyText"
style="@style/KeepassDXStyle.TextAppearance.Tiny"
android:firstBaselineToTopHeight="0dp"
android:includeFontPadding="false"
android:paddingStart="8dp"

View File

@@ -1,39 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/special_mode_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="4dp"
android:paddingBottom="4dp"
android:paddingStart="8dp"
android:paddingLeft="8dp"
android:paddingEnd="8dp"
android:paddingRight="8dp"
android:background="?attr/colorPrimaryDark">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/special_mode_cancel_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_close_white_24dp"
android:layout_marginStart="8dp"
android:layout_marginLeft="8dp"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:text="@string/entry_cancel"/>
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/special_mode_title_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:text="@string/selection_mode"
android:textColor="?attr/textColorInverse"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2020 Jeremy Jamet / Kunzisoft.
This file is part of KeePassDX.
KeePassDX is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
KeePassDX is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with KeePassDX. If not, see <http://www.gnu.org/licenses/>.
-->
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item android:id="@+id/menu_block_autofill"
android:icon="@drawable/ic_block_white_24dp"
android:title="@string/autofill_block"
android:orderInCategory="1"
app:showAsAction="ifRoom" />
</menu>

View File

@@ -19,7 +19,8 @@
-->
<resources>
<attr name="toolbarAppearance" format="reference" />
<attr name="toolbarBottomAppearance" format="reference" />
<attr name="specialToolbarAppearance" format="reference" />
<attr name="actionToolbarAppearance" format="reference" />
<attr name="toolbarPopupAppearance" format="reference" />
<attr name="colorAccentLight" format="reference|color" />

View File

@@ -42,6 +42,9 @@
<color name="blue_dark">#1976D2</color>
<color name="blue_darker">#1565C0</color>
<color name="cyan_lighter">#33b5e5</color>
<color name="cyan">#2c7a96</color>
<color name="red_lighter">#ef9a9a</color>
<color name="red_light">#f44336</color>
<color name="red">#e53935</color>

View File

@@ -136,9 +136,6 @@
<bool name="autofill_auto_search_default" translatable="false">true</bool>
<string name="autofill_application_id_blocklist_key" translatable="false">autofill_application_id_blocklist_key</string>
<string-array name="autofill_application_id_blocklist_default">
<item translatable="false">com.kunzisoft.keepass.libre</item>
<item translatable="false">com.kunzisoft.keepass.free</item>
<item translatable="false">com.kunzisoft.keepass.pro</item>
</string-array>
<string name="autofill_web_domain_blocklist_key" translatable="false">autofill_web_domain_blocklist_key</string>
<string-array name="autofill_web_domain_blocklist_default">

View File

@@ -388,6 +388,8 @@
<string name="autofill_application_id_blocklist_summary">Blocklist that prevents auto filling of apps</string>
<string name="autofill_web_domain_blocklist_title">Web domain blocklist</string>
<string name="autofill_web_domain_blocklist_summary">Blocklist that prevents auto filling of web domains</string>
<string name="autofill_block">Block autofill</string>
<string name="autofill_block_restart">Restart the app containing the form to activate the blocking.</string>
<string name="allow_no_password_title">Allow no master key</string>
<string name="allow_no_password_summary">Enable the \"Open\" button if no credentials are selected</string>
<string name="delete_entered_password_title">Delete password</string>

View File

@@ -30,12 +30,13 @@
<item name="android:textColorHintInverse">@color/green_light</item>
<item name="android:windowBackground">@color/background_dark</item>
<item name="toolbarAppearance">@style/KeepassDXStyle.Toolbar.Black</item>
<item name="toolbarBottomAppearance">@style/KeepassDXStyle.Toolbar.Black</item>
<item name="specialToolbarAppearance">@style/KeepassDXStyle.Toolbar.Special.Black</item>
<item name="actionToolbarAppearance">@style/KeepassDXStyle.Toolbar.Black</item>
<item name="android:alertDialogTheme">@style/KeepassDXStyle.Black.Dialog</item>
<item name="alertDialogTheme">@style/KeepassDXStyle.Black.Dialog</item>
<item name="actionModeStyle">@style/KeepassDXStyle.ActionMode.Dark</item>
</style>
<!-- Toolbar Style Black Green -->
<!-- Toolbar Style Black -->
<style name="KeepassDXStyle.Toolbar.Black" parent="KeepassDXStyle.Black">
<item name="colorControlNormal">@color/colorTextInverse</item>
<item name="android:textColorPrimary">@color/colorTextInverse</item>
@@ -44,6 +45,11 @@
<item name="android:textColorHint">@color/green_lighter</item>
<item name="android:tint">@color/colorTextInverse</item>
</style>
<!-- Special Toolbar Black -->
<style name="KeepassDXStyle.Toolbar.Special.Black" parent="KeepassDXStyle.Toolbar.Black">
<item name="android:background">@color/black</item>
<item name="background">@color/black</item>
</style>
<!-- Contextual Action Bar Dark -->
<style name="KeepassDXStyle.ActionMode.Black" parent="@style/Widget.AppCompat.ActionMode">
<item name="background">@color/dark</item>

View File

@@ -29,7 +29,8 @@
<item name="android:textColorHintInverse">@color/blue_lighter</item>
<item name="android:windowBackground">@color/background_light</item>
<item name="toolbarAppearance">@style/KeepassDXStyle.Toolbar.Blue</item>
<item name="toolbarBottomAppearance">@style/KeepassDXStyle.Toolbar.Bottom.Blue</item>
<item name="specialToolbarAppearance">@style/KeepassDXStyle.Toolbar.Special.Blue</item>
<item name="actionToolbarAppearance">@style/KeepassDXStyle.Toolbar.Action.Blue</item>
<item name="actionModeStyle">@style/KeepassDXStyle.ActionMode.Blue</item>
</style>
<!-- Toolbar Style Blue -->
@@ -42,7 +43,14 @@
<item name="android:textColorHint">@color/blue_lighter</item>
<item name="android:tint">@color/colorTextInverse</item>
</style>
<style name="KeepassDXStyle.Toolbar.Bottom.Blue" parent="KeepassDXStyle.Toolbar.Blue">
<!-- Special Toolbar Blue -->
<style name="KeepassDXStyle.Toolbar.Special.Blue" parent="KeepassDXStyle.Toolbar.Blue">
<item name="actionMenuTextColor">@color/colorTextInverse</item>
<item name="android:background">@color/blue_dark</item>
<item name="background">@color/blue_dark</item>
</style>
<!-- Action Toolbar Blue -->
<style name="KeepassDXStyle.Toolbar.Action.Blue" parent="KeepassDXStyle.Toolbar.Blue">
<item name="actionMenuTextColor">@color/colorTextInverse</item>
</style>
<!-- Contextual Action Bar Blue -->

View File

@@ -22,14 +22,15 @@
<style name="KeepassDXStyle.Dark" parent="KeepassDXStyle.Night.v21" >
<item name="colorPrimary">#212121</item>
<item name="colorPrimaryDark">@color/dark</item>
<item name="colorAccent">#2c7a96</item>
<item name="colorAccentLight">#33b5e5</item>
<item name="colorControlActivated">#33b5e5</item>
<item name="android:textColorPrimary">#33b5e5</item>
<item name="android:textColorHintInverse">#33b5e5</item>
<item name="colorAccent">@color/cyan</item>
<item name="colorAccentLight">@color/cyan_lighter</item>
<item name="colorControlActivated">@color/cyan_lighter</item>
<item name="android:textColorPrimary">@color/cyan_lighter</item>
<item name="android:textColorHintInverse">@color/cyan_lighter</item>
<item name="android:windowBackground">@color/background_dark</item>
<item name="toolbarAppearance">@style/KeepassDXStyle.Toolbar.Dark</item>
<item name="toolbarBottomAppearance">@style/KeepassDXStyle.Toolbar.Dark</item>
<item name="specialToolbarAppearance">@style/KeepassDXStyle.Toolbar.Special.Dark</item>
<item name="actionToolbarAppearance">@style/KeepassDXStyle.Toolbar.Dark</item>
<item name="android:alertDialogTheme">@style/KeepassDXStyle.Dark.Dialog</item>
<item name="alertDialogTheme">@style/KeepassDXStyle.Dark.Dialog</item>
<item name="actionModeStyle">@style/KeepassDXStyle.ActionMode.Dark</item>
@@ -41,6 +42,11 @@
<item name="android:textColorSecondary">@color/colorTextSecondary</item>
<item name="android:tint">@color/colorTextInverse</item>
</style>
<!-- Special Toolbar Dark -->
<style name="KeepassDXStyle.Toolbar.Special.Dark" parent="KeepassDXStyle.Toolbar.Dark">
<item name="android:background">@color/dark</item>
<item name="background">@color/dark</item>
</style>
<!-- Contextual Action Bar Dark -->
<style name="KeepassDXStyle.ActionMode.Dark" parent="@style/Widget.AppCompat.ActionMode">
<item name="background">@color/dark</item>
@@ -48,6 +54,6 @@
<!-- Dialog -->
<style name="KeepassDXStyle.Dark.Dialog" parent="KeepassDXStyle.Night.Dialog">
<item name="colorAccent">#fefefe</item>
<item name="android:textColorPrimary">#33b5e5</item>
<item name="android:textColorPrimary">@color/cyan_lighter</item>
</style>
</resources>

View File

@@ -29,7 +29,8 @@
<item name="android:textColorHintInverse">@color/purple_lighter</item>
<item name="android:windowBackground">@color/background_purple</item>
<item name="toolbarAppearance">@style/KeepassDXStyle.Toolbar.Purple</item>
<item name="toolbarBottomAppearance">@style/KeepassDXStyle.Toolbar.Bottom.Purple</item>
<item name="specialToolbarAppearance">@style/KeepassDXStyle.Toolbar.Special.Purple</item>
<item name="actionToolbarAppearance">@style/KeepassDXStyle.Toolbar.Action.Purple</item>
<item name="actionModeStyle">@style/KeepassDXStyle.ActionMode.Purple</item>
</style>
<!-- Toolbar Style Purple -->
@@ -42,7 +43,13 @@
<item name="android:textColorHint">@color/purple_lighter</item>
<item name="android:tint">@color/colorTextInverse</item>
</style>
<style name="KeepassDXStyle.Toolbar.Bottom.Purple" parent="KeepassDXStyle.Toolbar.Purple">
<!-- Special Toolbar Purple -->
<style name="KeepassDXStyle.Toolbar.Special.Purple" parent="KeepassDXStyle.Toolbar.Purple">
<item name="android:background">@color/purple_dark</item>
<item name="background">@color/purple_dark</item>
</style>
<!-- Action Toolbar Purple -->
<style name="KeepassDXStyle.Toolbar.Action.Purple" parent="KeepassDXStyle.Toolbar.Purple">
<item name="actionMenuTextColor">@color/colorTextInverse</item>
</style>
<!-- Contextual Action Bar Purple -->

View File

@@ -29,7 +29,8 @@
<item name="android:textColorHintInverse">@color/red_lighter</item>
<item name="android:windowBackground">@color/background_night</item>
<item name="toolbarAppearance">@style/KeepassDXStyle.Toolbar.Red</item>
<item name="toolbarBottomAppearance">@style/KeepassDXStyle.Toolbar.Red</item>
<item name="specialToolbarAppearance">@style/KeepassDXStyle.Toolbar.Special.Red</item>
<item name="actionToolbarAppearance">@style/KeepassDXStyle.Toolbar.Red</item>
<item name="actionModeStyle">@style/KeepassDXStyle.ActionMode.Red</item>
</style>
<!-- Toolbar Style Red -->
@@ -42,6 +43,11 @@
<item name="android:textColorHint">@color/red_lighter</item>
<item name="android:tint">@color/colorTextInverse</item>
</style>
<!-- Special Toolbar Red -->
<style name="KeepassDXStyle.Toolbar.Special.Red" parent="KeepassDXStyle.Toolbar.Red">
<item name="android:background">@color/red_dark</item>
<item name="background">@color/red_dark</item>
</style>
<!-- Contextual Action Bar Red -->
<style name="KeepassDXStyle.ActionMode.Red" parent="@style/Widget.AppCompat.ActionMode">
<item name="background">@color/orange</item>

View File

@@ -74,7 +74,8 @@
<!-- Toolbar -->
<item name="toolbarAppearance">@style/KeepassDXStyle.Toolbar.Light</item>
<item name="toolbarPopupAppearance">@style/KeepassDXStyle.Light.Toolbar.Popup</item>
<item name="toolbarBottomAppearance">@style/KeepassDXStyle.Toolbar.Night</item>
<item name="specialToolbarAppearance">@style/KeepassDXStyle.Toolbar.Special.Light</item>
<item name="actionToolbarAppearance">@style/KeepassDXStyle.Toolbar.Light</item>
<item name="actionModeStyle">@style/KeepassDXStyle.ActionMode</item>
<!-- CollapsingToolbarLayout -->
<item name="expandedTitleTextAppearance">@style/KeepassDXStyle.Expanded.Title</item>
@@ -126,7 +127,8 @@
<!-- Toolbar -->
<item name="toolbarAppearance">@style/KeepassDXStyle.Toolbar.Night</item>
<item name="toolbarPopupAppearance">@style/KeepassDXStyle.Night.Toolbar.Popup</item>
<item name="toolbarBottomAppearance">@style/KeepassDXStyle.Toolbar.Night</item>
<item name="specialToolbarAppearance">@style/KeepassDXStyle.Toolbar.Special.Night</item>
<item name="actionToolbarAppearance">@style/KeepassDXStyle.Toolbar.Night</item>
<item name="actionModeStyle">@style/KeepassDXStyle.ActionMode</item>
<!-- CollapsingToolbarLayout -->
<item name="expandedTitleTextAppearance">@style/KeepassDXStyle.Expanded.Title</item>
@@ -175,8 +177,21 @@
<item name="android:tint">@color/colorTextInverse</item>
</style>
<!-- Special Toolbar Light Style -->
<style name="KeepassDXStyle.Toolbar.Special.Light" parent="KeepassDXStyle.Toolbar.Light">
<item name="android:background">@color/green_dark</item>
<item name="background">@color/green_dark</item>
</style>
<!-- Special Toolbar Night Style -->
<style name="KeepassDXStyle.Toolbar.Special.Night" parent="KeepassDXStyle.Toolbar.Night">
<item name="android:background">@color/green_dark</item>
<item name="background">@color/green_dark</item>
</style>
<!-- Contextual Action Bar -->
<style name="KeepassDXStyle.ActionMode" parent="@style/Widget.AppCompat.ActionMode">
<item name="android:background">@color/orange</item>
<item name="background">@color/orange</item>
</style>
@@ -257,7 +272,7 @@
<item name="android:textColor">?android:attr/textColorPrimary</item>
<item name="android:textSize">20sp</item>
</style>
<style name="KeepassDXStyle.TextAppearance.TinyText" parent="KeepassDXStyle.TextAppearance">
<style name="KeepassDXStyle.TextAppearance.Tiny" parent="KeepassDXStyle.TextAppearance">
<item name="android:textSize">12sp</item>
</style>
<style name="KeepassDXStyle.TextAppearance.WarningTextStyle" parent="KeepassDXStyle.TextAppearance">
@@ -291,6 +306,14 @@
<item name="android:tint">@color/group_subtitle_color</item>
</style>
<!-- Special Toolbar text titlé -->
<style name="KeepassDXStyle.TextAppearance.Toolbar.Special.Title" parent="KeepassDXStyle.TextAppearance.Small">
<item name="android:textColor">?attr/colorAccent</item>
</style>
<style name="KeepassDXStyle.TextAppearance.Toolbar.Special.SubTitle" parent="KeepassDXStyle.TextAppearance.Tiny">
<item name="android:textColor">@color/colorTextInverse</item>
</style>
<!-- Button Style -->
<style name="KeepassDXStyle.v21.Button" parent="Base.TextAppearance.AppCompat.Button">
<item name="android:gravity">center</item>