aboutsummaryrefslogtreecommitdiffstats
path: root/app/src/main/java/com/zeapo/pwdstore/UserPreference.kt
diff options
context:
space:
mode:
authorFabian Henneke <FabianHenneke@users.noreply.github.com>2020-03-24 14:03:40 +0100
committerGitHub <noreply@github.com>2020-03-24 14:03:40 +0100
commitbebe43468330f182ea35e01ace555ce8d0512aeb (patch)
tree85899eccd985b302183ee1551054ef54bdb0ada5 /app/src/main/java/com/zeapo/pwdstore/UserPreference.kt
parent98e9f6734a00cfb1d8164227b2de07d2aea150d2 (diff)
downloadHardenedPass-bebe43468330f182ea35e01ace555ce8d0512aeb.tar.gz
HardenedPass-bebe43468330f182ea35e01ace555ce8d0512aeb.zip
Add support for Oreo Autofill (#653)
Adds support for the Autofill feature first available in Android Oreo. In compatible apps and browsers, login forms are automatically detected and the user is presented with options to fill or generate credentials. In most apps and certain browsers, the service will also offer to create new Password Store entries from credentials entered into login forms. Signed-off-by: Harsh Shandilya <me@msfjarvis.dev> Co-authored-by: Harsh Shandilya <me@msfjarvis.dev>
Diffstat (limited to 'app/src/main/java/com/zeapo/pwdstore/UserPreference.kt')
-rw-r--r--app/src/main/java/com/zeapo/pwdstore/UserPreference.kt126
1 files changed, 94 insertions, 32 deletions
diff --git a/app/src/main/java/com/zeapo/pwdstore/UserPreference.kt b/app/src/main/java/com/zeapo/pwdstore/UserPreference.kt
index 8667110a..895338e9 100644
--- a/app/src/main/java/com/zeapo/pwdstore/UserPreference.kt
+++ b/app/src/main/java/com/zeapo/pwdstore/UserPreference.kt
@@ -6,7 +6,6 @@ package com.zeapo.pwdstore
import android.accessibilityservice.AccessibilityServiceInfo
import android.app.Activity
-import android.content.Context
import android.content.Intent
import android.content.pm.ShortcutManager
import android.net.Uri
@@ -20,6 +19,7 @@ import android.view.MenuItem
import android.view.accessibility.AccessibilityManager
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
+import androidx.appcompat.widget.AppCompatTextView
import androidx.biometric.BiometricManager
import androidx.core.content.getSystemService
import androidx.documentfile.provider.DocumentFile
@@ -32,6 +32,8 @@ import androidx.preference.SwitchPreferenceCompat
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.google.android.material.snackbar.Snackbar
import com.zeapo.pwdstore.autofill.AutofillPreferenceActivity
+import com.zeapo.pwdstore.autofill.oreo.BrowserAutofillSupportLevel
+import com.zeapo.pwdstore.autofill.oreo.getInstalledBrowsersWithAutofillSupportLevel
import com.zeapo.pwdstore.crypto.PgpActivity
import com.zeapo.pwdstore.git.GitActivity
import com.zeapo.pwdstore.pwgenxkpwd.XkpwdDictionary
@@ -40,6 +42,7 @@ import com.zeapo.pwdstore.sshkeygen.SshKeyGenActivity
import com.zeapo.pwdstore.utils.PasswordRepository
import com.zeapo.pwdstore.utils.auth.AuthenticationResult
import com.zeapo.pwdstore.utils.auth.Authenticator
+import com.zeapo.pwdstore.utils.autofillManager
import java.io.File
import java.io.IOException
import java.time.LocalDateTime
@@ -127,9 +130,7 @@ class UserPreference : AppCompatActivity() {
openkeystoreIdPreference?.isVisible = sharedPreferences.getString("ssh_openkeystore_keyid", null)?.isNotEmpty()
?: false
- // see if the autofill service is enabled and check the preference accordingly
- autoFillEnablePreference?.isChecked = callingActivity.isServiceEnabled
- autofillDependencies.forEach { it?.isVisible = callingActivity.isServiceEnabled }
+ updateAutofillSettings()
appVersionPreference?.summary = "Version: ${BuildConfig.VERSION_NAME}"
@@ -242,24 +243,7 @@ class UserPreference : AppCompatActivity() {
}
autoFillEnablePreference?.onPreferenceClickListener = ClickListener {
- var isEnabled = callingActivity.isServiceEnabled
- if (isEnabled) {
- startActivity(Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS))
- } else {
- MaterialAlertDialogBuilder(callingActivity)
- .setTitle(R.string.pref_autofill_enable_title)
- .setView(R.layout.autofill_instructions)
- .setPositiveButton(R.string.dialog_ok) { _, _ ->
- startActivity(Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS))
- }
- .setNegativeButton(R.string.dialog_cancel, null)
- .setOnDismissListener {
- isEnabled = callingActivity.isServiceEnabled
- autoFillEnablePreference?.isChecked = isEnabled
- autofillDependencies.forEach { it?.isVisible = isEnabled }
- }
- .show()
- }
+ onEnableAutofillClick()
true
}
@@ -370,11 +354,79 @@ class UserPreference : AppCompatActivity() {
}
}
+ private fun updateAutofillSettings() {
+ val isAccessibilityServiceEnabled = callingActivity.isAccessibilityServiceEnabled
+ autoFillEnablePreference?.isChecked =
+ isAccessibilityServiceEnabled || callingActivity.isAutofillServiceEnabled
+ autofillDependencies.forEach {
+ it?.isVisible = isAccessibilityServiceEnabled
+ }
+ }
+
+ private fun onEnableAutofillClick() {
+ if (callingActivity.isAccessibilityServiceEnabled) {
+ startActivity(Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS))
+ } else if (callingActivity.isAutofillServiceEnabled) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
+ callingActivity.autofillManager!!.disableAutofillServices()
+ else
+ throw IllegalStateException("isAutofillServiceEnabled == true, but Build.VERSION.SDK_INT < Build.VERSION_CODES.O")
+ } else {
+ val enableOreoAutofill = callingActivity.isAutofillServiceSupported
+ MaterialAlertDialogBuilder(callingActivity).run {
+ setTitle(R.string.pref_autofill_enable_title)
+ if (enableOreoAutofill && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ val layout =
+ layoutInflater.inflate(R.layout.oreo_autofill_instructions, null)
+ val supportedBrowsersTextView =
+ layout.findViewById<AppCompatTextView>(R.id.supportedBrowsers)
+ supportedBrowsersTextView.text =
+ getInstalledBrowsersWithAutofillSupportLevel(context).joinToString(
+ separator = "\n"
+ ) {
+ val appLabel = it.first
+ val supportDescription = when (it.second) {
+ BrowserAutofillSupportLevel.None -> getString(R.string.oreo_autofill_no_support)
+ BrowserAutofillSupportLevel.FlakyFill -> getString(R.string.oreo_autofill_flaky_fill_support)
+ BrowserAutofillSupportLevel.Fill -> getString(R.string.oreo_autofill_fill_support)
+ BrowserAutofillSupportLevel.FillAndSave -> getString(R.string.oreo_autofill_fill_and_save_support)
+ }
+ "$appLabel: $supportDescription"
+ }
+ setView(layout)
+ } else {
+ setView(R.layout.autofill_instructions)
+ }
+ setPositiveButton(R.string.dialog_ok) { _, _ ->
+ val intent =
+ if (enableOreoAutofill && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ Intent(Settings.ACTION_REQUEST_SET_AUTOFILL_SERVICE).apply {
+ data = Uri.parse("package:${BuildConfig.APPLICATION_ID}")
+ }
+ } else {
+ Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS)
+ }
+ startActivity(intent)
+ }
+ setNegativeButton(R.string.dialog_cancel, null)
+ setOnDismissListener {
+ val isEnabled =
+ if (enableOreoAutofill && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ callingActivity.isAutofillServiceEnabled
+ } else {
+ callingActivity.isAccessibilityServiceEnabled
+ }
+ autoFillEnablePreference?.isChecked = isEnabled
+ autofillDependencies.forEach { it?.isVisible = isEnabled }
+ }
+ show()
+ }
+ }
+ }
+
override fun onResume() {
super.onResume()
- val isEnabled = callingActivity.isServiceEnabled
- autoFillEnablePreference?.isChecked = isEnabled
- autofillDependencies.forEach { it?.isVisible = isEnabled }
+ updateAutofillSettings()
}
}
@@ -487,16 +539,26 @@ class UserPreference : AppCompatActivity() {
}
}
- // Returns whether the autofill service is enabled
- private val isServiceEnabled: Boolean
+ private val isAccessibilityServiceEnabled: Boolean
get() {
- val am = this
- .getSystemService(Context.ACCESSIBILITY_SERVICE) as AccessibilityManager
+ val am = getSystemService(AccessibilityManager::class.java)
val runningServices = am
- .getEnabledAccessibilityServiceList(AccessibilityServiceInfo.FEEDBACK_GENERIC)
+ .getEnabledAccessibilityServiceList(AccessibilityServiceInfo.FEEDBACK_GENERIC)
return runningServices
- .map { it.id.substringBefore("/") }
- .any { it == BuildConfig.APPLICATION_ID }
+ .map { it.id.substringBefore("/") }
+ .any { it == BuildConfig.APPLICATION_ID }
+ }
+
+ private val isAutofillServiceSupported: Boolean
+ get() {
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) return false
+ return autofillManager?.isAutofillSupported != null
+ }
+
+ private val isAutofillServiceEnabled: Boolean
+ get() {
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) return false
+ return autofillManager?.hasEnabledAutofillServices() == true
}
override fun onActivityResult(