parent
2f657108b3
commit
681c557e9e
10 changed files with 9 additions and 195 deletions
|
@ -18,7 +18,6 @@ All notable changes to this project will be documented in this file.
|
||||||
- Fix authentication failure with usernames that contain the `@` character
|
- Fix authentication failure with usernames that contain the `@` character
|
||||||
- Text input boxes were illegible on dark theme
|
- Text input boxes were illegible on dark theme
|
||||||
- Top-level password names had inconsistent top margin making them look askew
|
- Top-level password names had inconsistent top margin making them look askew
|
||||||
- Autofill can now be made more reliable in Chrome by enabling an accessibility service that works around known Chrome limitations
|
|
||||||
- Password Store no longer ignores the selected OpenKeychain key
|
- Password Store no longer ignores the selected OpenKeychain key
|
||||||
- Password export now happens in a separate process, preventing possible freezes
|
- Password export now happens in a separate process, preventing possible freezes
|
||||||
|
|
||||||
|
|
|
@ -99,19 +99,6 @@
|
||||||
android:name="android.accessibilityservice"
|
android:name="android.accessibilityservice"
|
||||||
android:resource="@xml/autofill_config" />
|
android:resource="@xml/autofill_config" />
|
||||||
</service>
|
</service>
|
||||||
|
|
||||||
<service
|
|
||||||
android:name=".autofill.oreo.ChromeCompatFix"
|
|
||||||
android:enabled="@bool/enable_chrome_compat_fix"
|
|
||||||
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="android.accessibilityservice.AccessibilityService" />
|
|
||||||
</intent-filter>
|
|
||||||
<meta-data
|
|
||||||
android:name="android.accessibilityservice"
|
|
||||||
android:resource="@xml/oreo_autofill_chrome_compat_fix" />
|
|
||||||
</service>
|
|
||||||
|
|
||||||
<service
|
<service
|
||||||
android:name=".ClipboardService"
|
android:name=".ClipboardService"
|
||||||
android:process=":clipboard_service_process" />
|
android:process=":clipboard_service_process" />
|
||||||
|
|
|
@ -41,9 +41,7 @@ import com.github.ajalt.timberkt.w
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
import com.google.android.material.snackbar.Snackbar
|
import com.google.android.material.snackbar.Snackbar
|
||||||
import com.zeapo.pwdstore.autofill.AutofillPreferenceActivity
|
import com.zeapo.pwdstore.autofill.AutofillPreferenceActivity
|
||||||
import com.zeapo.pwdstore.autofill.AutofillService
|
|
||||||
import com.zeapo.pwdstore.autofill.oreo.BrowserAutofillSupportLevel
|
import com.zeapo.pwdstore.autofill.oreo.BrowserAutofillSupportLevel
|
||||||
import com.zeapo.pwdstore.autofill.oreo.ChromeCompatFix
|
|
||||||
import com.zeapo.pwdstore.autofill.oreo.getInstalledBrowsersWithAutofillSupportLevel
|
import com.zeapo.pwdstore.autofill.oreo.getInstalledBrowsersWithAutofillSupportLevel
|
||||||
import com.zeapo.pwdstore.crypto.BasePgpActivity
|
import com.zeapo.pwdstore.crypto.BasePgpActivity
|
||||||
import com.zeapo.pwdstore.crypto.GetKeyIdsActivity
|
import com.zeapo.pwdstore.crypto.GetKeyIdsActivity
|
||||||
|
@ -72,7 +70,6 @@ class UserPreference : AppCompatActivity() {
|
||||||
class PrefsFragment : PreferenceFragmentCompat() {
|
class PrefsFragment : PreferenceFragmentCompat() {
|
||||||
|
|
||||||
private var autoFillEnablePreference: SwitchPreferenceCompat? = null
|
private var autoFillEnablePreference: SwitchPreferenceCompat? = null
|
||||||
private var oreoAutofillChromeCompatFix: SwitchPreferenceCompat? = null
|
|
||||||
private var clearSavedPassPreference: Preference? = null
|
private var clearSavedPassPreference: Preference? = null
|
||||||
private lateinit var autofillDependencies: List<Preference>
|
private lateinit var autofillDependencies: List<Preference>
|
||||||
private lateinit var oreoAutofillDependencies: List<Preference>
|
private lateinit var oreoAutofillDependencies: List<Preference>
|
||||||
|
@ -118,7 +115,6 @@ class UserPreference : AppCompatActivity() {
|
||||||
|
|
||||||
// Autofill preferences
|
// Autofill preferences
|
||||||
autoFillEnablePreference = findPreference(PreferenceKeys.AUTOFILL_ENABLE)
|
autoFillEnablePreference = findPreference(PreferenceKeys.AUTOFILL_ENABLE)
|
||||||
oreoAutofillChromeCompatFix = findPreference(PreferenceKeys.OREO_AUTOFILL_CHROME_COMPAT_FIX)
|
|
||||||
val oreoAutofillDirectoryStructurePreference = findPreference<ListPreference>(PreferenceKeys.OREO_AUTOFILL_DIRECTORY_STRUCTURE)
|
val oreoAutofillDirectoryStructurePreference = findPreference<ListPreference>(PreferenceKeys.OREO_AUTOFILL_DIRECTORY_STRUCTURE)
|
||||||
val oreoAutofillDefaultUsername = findPreference<EditTextPreference>(PreferenceKeys.OREO_AUTOFILL_DEFAULT_USERNAME)
|
val oreoAutofillDefaultUsername = findPreference<EditTextPreference>(PreferenceKeys.OREO_AUTOFILL_DEFAULT_USERNAME)
|
||||||
val oreoAutofillCustomPublixSuffixes = findPreference<EditTextPreference>(PreferenceKeys.OREO_AUTOFILL_CUSTOM_PUBLIC_SUFFIXES)
|
val oreoAutofillCustomPublixSuffixes = findPreference<EditTextPreference>(PreferenceKeys.OREO_AUTOFILL_CUSTOM_PUBLIC_SUFFIXES)
|
||||||
|
@ -277,16 +273,6 @@ class UserPreference : AppCompatActivity() {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
oreoAutofillChromeCompatFix?.onPreferenceClickListener = ClickListener {
|
|
||||||
if (oreoAutofillChromeCompatFix!!.isChecked) {
|
|
||||||
startActivity(Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS))
|
|
||||||
true
|
|
||||||
} else {
|
|
||||||
// Service will disable itself on startup if the preference has the value false.
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
findPreference<Preference>(PreferenceKeys.EXPORT_PASSWORDS)?.apply {
|
findPreference<Preference>(PreferenceKeys.EXPORT_PASSWORDS)?.apply {
|
||||||
isVisible = sharedPreferences.getBoolean(PreferenceKeys.REPOSITORY_INITIALIZED, false)
|
isVisible = sharedPreferences.getBoolean(PreferenceKeys.REPOSITORY_INITIALIZED, false)
|
||||||
onPreferenceClickListener = Preference.OnPreferenceClickListener {
|
onPreferenceClickListener = Preference.OnPreferenceClickListener {
|
||||||
|
@ -409,20 +395,16 @@ class UserPreference : AppCompatActivity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateAutofillSettings() {
|
private fun updateAutofillSettings() {
|
||||||
val isAccessibilityAutofillServiceEnabled = callingActivity.isAccessibilityAutofillServiceEnabled
|
val isAccessibilityServiceEnabled = callingActivity.isAccessibilityServiceEnabled
|
||||||
val isAutofillServiceEnabled = callingActivity.isAutofillServiceEnabled
|
val isAutofillServiceEnabled = callingActivity.isAutofillServiceEnabled
|
||||||
autoFillEnablePreference?.isChecked =
|
autoFillEnablePreference?.isChecked =
|
||||||
isAccessibilityAutofillServiceEnabled || isAutofillServiceEnabled
|
isAccessibilityServiceEnabled || isAutofillServiceEnabled
|
||||||
autofillDependencies.forEach {
|
autofillDependencies.forEach {
|
||||||
it.isVisible = isAccessibilityAutofillServiceEnabled
|
it.isVisible = isAccessibilityServiceEnabled
|
||||||
}
|
}
|
||||||
oreoAutofillDependencies.forEach {
|
oreoAutofillDependencies.forEach {
|
||||||
it.isVisible = isAutofillServiceEnabled
|
it.isVisible = isAutofillServiceEnabled
|
||||||
}
|
}
|
||||||
oreoAutofillChromeCompatFix?.apply {
|
|
||||||
isChecked = callingActivity.isChromeCompatFixServiceEnabled
|
|
||||||
isVisible = callingActivity.isChromeCompatFixServiceSupported
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateClearSavedPassphrasePrefs() {
|
private fun updateClearSavedPassphrasePrefs() {
|
||||||
|
@ -443,16 +425,13 @@ class UserPreference : AppCompatActivity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onEnableAutofillClick() {
|
private fun onEnableAutofillClick() {
|
||||||
if (callingActivity.isAccessibilityAutofillServiceEnabled) {
|
if (callingActivity.isAccessibilityServiceEnabled) {
|
||||||
startActivity(Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS))
|
startActivity(Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS))
|
||||||
} else if (callingActivity.isAutofillServiceEnabled) {
|
} else if (callingActivity.isAutofillServiceEnabled) {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
|
||||||
callingActivity.autofillManager!!.disableAutofillServices()
|
callingActivity.autofillManager!!.disableAutofillServices()
|
||||||
ChromeCompatFix.setStatusInPreferences(requireContext(), false)
|
else
|
||||||
updateAutofillSettings()
|
|
||||||
} else {
|
|
||||||
throw IllegalStateException("isAutofillServiceEnabled == true, but Build.VERSION.SDK_INT < Build.VERSION_CODES.O")
|
throw IllegalStateException("isAutofillServiceEnabled == true, but Build.VERSION.SDK_INT < Build.VERSION_CODES.O")
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
val enableOreoAutofill = callingActivity.isAutofillServiceSupported
|
val enableOreoAutofill = callingActivity.isAutofillServiceSupported
|
||||||
MaterialAlertDialogBuilder(callingActivity).run {
|
MaterialAlertDialogBuilder(callingActivity).run {
|
||||||
|
@ -744,32 +723,14 @@ class UserPreference : AppCompatActivity() {
|
||||||
File("$filesDir/.ssh_key").writeText(lines.joinToString("\n"))
|
File("$filesDir/.ssh_key").writeText(lines.joinToString("\n"))
|
||||||
}
|
}
|
||||||
|
|
||||||
private val isAccessibilityAutofillServiceEnabled: Boolean
|
private val isAccessibilityServiceEnabled: Boolean
|
||||||
get() {
|
get() {
|
||||||
val am = getSystemService<AccessibilityManager>() ?: return false
|
val am = getSystemService<AccessibilityManager>() ?: return false
|
||||||
val runningServices = am
|
val runningServices = am
|
||||||
.getEnabledAccessibilityServiceList(AccessibilityServiceInfo.FEEDBACK_GENERIC)
|
.getEnabledAccessibilityServiceList(AccessibilityServiceInfo.FEEDBACK_GENERIC)
|
||||||
return runningServices
|
return runningServices
|
||||||
.mapNotNull { it?.resolveInfo?.serviceInfo }
|
.map { it.id.substringBefore("/") }
|
||||||
.any { it.packageName == BuildConfig.APPLICATION_ID && it.name == AutofillService::class.java.name }
|
.any { it == BuildConfig.APPLICATION_ID }
|
||||||
}
|
|
||||||
|
|
||||||
private val isChromeCompatFixServiceEnabled: Boolean
|
|
||||||
get() {
|
|
||||||
val am = getSystemService<AccessibilityManager>() ?: return false
|
|
||||||
val runningServices = am
|
|
||||||
.getEnabledAccessibilityServiceList(AccessibilityServiceInfo.FEEDBACK_GENERIC)
|
|
||||||
return runningServices
|
|
||||||
.mapNotNull { it?.resolveInfo?.serviceInfo }
|
|
||||||
.any { it.packageName == BuildConfig.APPLICATION_ID && it.name == ChromeCompatFix::class.java.name }
|
|
||||||
}
|
|
||||||
|
|
||||||
private val isChromeCompatFixServiceSupported: Boolean
|
|
||||||
get() {
|
|
||||||
// Autofill compat mode is only available starting with Android Pie and only makes sense
|
|
||||||
// when used with Autofill enabled.
|
|
||||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) return false
|
|
||||||
return isAutofillServiceEnabled
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private val isAutofillServiceSupported: Boolean
|
private val isAutofillServiceSupported: Boolean
|
||||||
|
|
|
@ -1,94 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright © 2014-2020 The Android Password Store Authors. All Rights Reserved.
|
|
||||||
* SPDX-License-Identifier: GPL-3.0-only
|
|
||||||
*/
|
|
||||||
package com.zeapo.pwdstore.autofill.oreo
|
|
||||||
|
|
||||||
import android.accessibilityservice.AccessibilityService
|
|
||||||
import android.content.Context
|
|
||||||
import android.content.SharedPreferences
|
|
||||||
import android.os.Build
|
|
||||||
import android.os.Handler
|
|
||||||
import android.os.Looper
|
|
||||||
import android.view.accessibility.AccessibilityEvent
|
|
||||||
import androidx.annotation.RequiresApi
|
|
||||||
import androidx.core.content.edit
|
|
||||||
import androidx.preference.PreferenceManager
|
|
||||||
import com.github.ajalt.timberkt.i
|
|
||||||
import com.github.ajalt.timberkt.v
|
|
||||||
import com.github.ajalt.timberkt.w
|
|
||||||
import com.zeapo.pwdstore.utils.PreferenceKeys
|
|
||||||
import com.zeapo.pwdstore.utils.autofillManager
|
|
||||||
|
|
||||||
@RequiresApi(Build.VERSION_CODES.P)
|
|
||||||
class ChromeCompatFix : AccessibilityService() {
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
|
|
||||||
fun setStatusInPreferences(context: Context, enabled: Boolean) {
|
|
||||||
PreferenceManager.getDefaultSharedPreferences(context).edit {
|
|
||||||
putBoolean(PreferenceKeys.OREO_AUTOFILL_CHROME_COMPAT_FIX, enabled)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private val isEnabledInPreferences
|
|
||||||
get() = PreferenceManager.getDefaultSharedPreferences(this).getBoolean(PreferenceKeys.OREO_AUTOFILL_CHROME_COMPAT_FIX, true)
|
|
||||||
|
|
||||||
private val handler = Handler(Looper.getMainLooper())
|
|
||||||
private val forceRootNodePopulation = Runnable {
|
|
||||||
val rootPackageName = rootInActiveWindow?.packageName.toString()
|
|
||||||
v { "$rootPackageName: forced root node population" }
|
|
||||||
}
|
|
||||||
private val disableListener = SharedPreferences.OnSharedPreferenceChangeListener { prefs: SharedPreferences, key: String ->
|
|
||||||
if (key != PreferenceKeys.OREO_AUTOFILL_CHROME_COMPAT_FIX)
|
|
||||||
return@OnSharedPreferenceChangeListener
|
|
||||||
if (!isEnabledInPreferences) {
|
|
||||||
i { "Disabled in settings, shutting down..." }
|
|
||||||
disableSelf()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onAccessibilityEvent(event: AccessibilityEvent) {
|
|
||||||
handler.removeCallbacks(forceRootNodePopulation)
|
|
||||||
when (event.eventType) {
|
|
||||||
AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED, AccessibilityEvent.TYPE_ANNOUNCEMENT -> {
|
|
||||||
// WINDOW_STATE_CHANGED: Triggered on long press in a text field, replacement for
|
|
||||||
// the missing Autofill action menu item.
|
|
||||||
// ANNOUNCEMENT: Triggered when a password field is selected.
|
|
||||||
//
|
|
||||||
// These events are triggered only by user actions and thus don't need to be handled
|
|
||||||
// with debounce. However, they only trigger Autofill popups on the *next* input
|
|
||||||
// field selected by the user.
|
|
||||||
forceRootNodePopulation.run()
|
|
||||||
v { "${event.packageName} (${AccessibilityEvent.eventTypeToString(event.eventType)}): forced root node population" }
|
|
||||||
}
|
|
||||||
AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED -> {
|
|
||||||
// WINDOW_CONTENT_CHANGED: Triggered whenever the page contents change.
|
|
||||||
//
|
|
||||||
// This event is triggered many times during page load, which makes a debounce
|
|
||||||
// necessary to prevent huge performance regressions in Chrome. However, it is the
|
|
||||||
// only event that reliably runs before the user selects a text field.
|
|
||||||
handler.postDelayed(forceRootNodePopulation, 300)
|
|
||||||
v { "${event.packageName} (${AccessibilityEvent.eventTypeToString(event.eventType)}): debounced root node population" }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onServiceConnected() {
|
|
||||||
super.onServiceConnected()
|
|
||||||
// Allow the service to be activated only if the Autofill service is already enabled.
|
|
||||||
if (autofillManager?.hasEnabledAutofillServices() != true) {
|
|
||||||
w { "Autofill service not enabled, shutting down..." }
|
|
||||||
disableSelf()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// Update preferences if the user manually activated the service.
|
|
||||||
setStatusInPreferences(this, true)
|
|
||||||
|
|
||||||
PreferenceManager.getDefaultSharedPreferences(this).registerOnSharedPreferenceChangeListener(disableListener)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onInterrupt() {}
|
|
||||||
}
|
|
||||||
|
|
|
@ -40,7 +40,6 @@ object PreferenceKeys {
|
||||||
const val OPENPGP_KEY_IDS_SET = "openpgp_key_ids_set"
|
const val OPENPGP_KEY_IDS_SET = "openpgp_key_ids_set"
|
||||||
const val OPENPGP_KEY_ID_PREF = "openpgp_key_id_pref"
|
const val OPENPGP_KEY_ID_PREF = "openpgp_key_id_pref"
|
||||||
const val OPENPGP_PROVIDER_LIST = "openpgp_provider_list"
|
const val OPENPGP_PROVIDER_LIST = "openpgp_provider_list"
|
||||||
const val OREO_AUTOFILL_CHROME_COMPAT_FIX = "oreo_autofill_chrome_compat_fix"
|
|
||||||
const val OREO_AUTOFILL_CUSTOM_PUBLIC_SUFFIXES = "oreo_autofill_custom_public_suffixes"
|
const val OREO_AUTOFILL_CUSTOM_PUBLIC_SUFFIXES = "oreo_autofill_custom_public_suffixes"
|
||||||
const val OREO_AUTOFILL_DEFAULT_USERNAME = "oreo_autofill_default_username"
|
const val OREO_AUTOFILL_DEFAULT_USERNAME = "oreo_autofill_default_username"
|
||||||
const val OREO_AUTOFILL_DIRECTORY_STRUCTURE = "oreo_autofill_directory_structure"
|
const val OREO_AUTOFILL_DIRECTORY_STRUCTURE = "oreo_autofill_directory_structure"
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?><!--
|
|
||||||
~ Copyright © 2014-2020 The Android Password Store Authors. All Rights Reserved.
|
|
||||||
~ SPDX-License-Identifier: GPL-3.0-only
|
|
||||||
-->
|
|
||||||
|
|
||||||
<resources>
|
|
||||||
<bool name="enable_chrome_compat_fix">true</bool>
|
|
||||||
</resources>
|
|
|
@ -7,5 +7,4 @@
|
||||||
<bool name="leak_canary_allow_in_non_debuggable_build">true</bool>
|
<bool name="leak_canary_allow_in_non_debuggable_build">true</bool>
|
||||||
<bool name="enable_accessibility_autofill">true</bool>
|
<bool name="enable_accessibility_autofill">true</bool>
|
||||||
<bool name="light_status_bar">true</bool>
|
<bool name="light_status_bar">true</bool>
|
||||||
<bool name="enable_chrome_compat_fix">false</bool>
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -275,16 +275,6 @@
|
||||||
<string name="oreo_autofill_enable_dialog_description">Password Store can offer to fill login forms and even save credentials you enter in apps or on websites.</string>
|
<string name="oreo_autofill_enable_dialog_description">Password Store can offer to fill login forms and even save credentials you enter in apps or on websites.</string>
|
||||||
<string name="oreo_autofill_enable_dialog_instructions">To enable this feature, tap OK to go to Autofill settings. There, select Password Store from the list and confirm the confirmation prompt with OK.</string>
|
<string name="oreo_autofill_enable_dialog_instructions">To enable this feature, tap OK to go to Autofill settings. There, select Password Store from the list and confirm the confirmation prompt with OK.</string>
|
||||||
<string name="oreo_autofill_enable_dialog_installed_browsers">Autofill support with installed browsers:</string>
|
<string name="oreo_autofill_enable_dialog_installed_browsers">Autofill support with installed browsers:</string>
|
||||||
<string name="oreo_autofill_chrome_compat_fix_summary">Make Autofill more reliable in Chrome</string>
|
|
||||||
<string name="oreo_autofill_chrome_compat_fix_description">This accessibility service makes
|
|
||||||
Autofill work more reliably in Chrome. It can only be activated if you are already using
|
|
||||||
Password Store as your Autofill service.\n\nThis service is only active while you are
|
|
||||||
using Chrome. It does not access any data or take any actions on your behalf, but forces
|
|
||||||
Chrome to properly forward user interactions to the Password Store Autofill
|
|
||||||
service.\n\nChrome\'s performance should not be noticeably affected. If you are experiencing
|
|
||||||
any problems with this service, please create an issue at
|
|
||||||
https://msfjarvis.dev/aps.
|
|
||||||
</string>
|
|
||||||
|
|
||||||
<!-- Autofill -->
|
<!-- Autofill -->
|
||||||
<string name="autofill_description">Autofills password fields in apps. Only works for Android versions 4.3 and up. Does not rely on the clipboard for Android versions 5.0 and up.</string>
|
<string name="autofill_description">Autofills password fields in apps. Only works for Android versions 4.3 and up. Does not rely on the clipboard for Android versions 5.0 and up.</string>
|
||||||
|
@ -399,7 +389,6 @@
|
||||||
<string name="otp_import_success">Successfully imported TOTP configuration</string>
|
<string name="otp_import_success">Successfully imported TOTP configuration</string>
|
||||||
<string name="otp_import_failure">Failed to import TOTP configuration</string>
|
<string name="otp_import_failure">Failed to import TOTP configuration</string>
|
||||||
<string name="oreo_autofill_chrome_compat_fix_preference_title">Improve reliability in Chrome</string>
|
<string name="oreo_autofill_chrome_compat_fix_preference_title">Improve reliability in Chrome</string>
|
||||||
<string name="oreo_autofill_chrome_compat_fix_preference_summary">Requires activating an accessibility service and may affect overall Chrome performance</string>
|
|
||||||
<string name="exporting_passwords">Exporting passwords…</string>
|
<string name="exporting_passwords">Exporting passwords…</string>
|
||||||
<string name="invalid_filename_text">File name must not contain \'/\', set directory above</string>
|
<string name="invalid_filename_text">File name must not contain \'/\', set directory above</string>
|
||||||
<string name="directory_hint">Directory</string>
|
<string name="directory_hint">Directory</string>
|
||||||
|
|
|
@ -1,13 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?><!--
|
|
||||||
~ Copyright © 2014-2020 The Android Password Store Authors. All Rights Reserved.
|
|
||||||
~ SPDX-License-Identifier: GPL-3.0-only
|
|
||||||
-->
|
|
||||||
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:accessibilityEventTypes="typeWindowContentChanged|typeAnnouncement|typeWindowStateChanged"
|
|
||||||
android:accessibilityFeedbackType="feedbackGeneric"
|
|
||||||
android:accessibilityFlags="flagDefault"
|
|
||||||
android:canRetrieveWindowContent="true"
|
|
||||||
android:description="@string/oreo_autofill_chrome_compat_fix_description"
|
|
||||||
android:notificationTimeout="100"
|
|
||||||
android:packageNames="com.android.chrome,com.chrome.beta,com.chrome.dev,com.chrome.canary"
|
|
||||||
android:summary="@string/oreo_autofill_chrome_compat_fix_summary" />
|
|
|
@ -10,11 +10,6 @@
|
||||||
app:defaultValue="true"
|
app:defaultValue="true"
|
||||||
app:key="autofill_enable"
|
app:key="autofill_enable"
|
||||||
app:title="@string/pref_autofill_enable_title" />
|
app:title="@string/pref_autofill_enable_title" />
|
||||||
<SwitchPreferenceCompat
|
|
||||||
app:defaultValue="true"
|
|
||||||
app:key="oreo_autofill_chrome_compat_fix"
|
|
||||||
app:summary="@string/oreo_autofill_chrome_compat_fix_preference_summary"
|
|
||||||
app:title="@string/oreo_autofill_chrome_compat_fix_preference_title" />
|
|
||||||
<ListPreference
|
<ListPreference
|
||||||
app:defaultValue="file"
|
app:defaultValue="file"
|
||||||
app:entries="@array/oreo_autofill_directory_structure_entries"
|
app:entries="@array/oreo_autofill_directory_structure_entries"
|
||||||
|
|
Loading…
Reference in a new issue