diff options
| author | Fabian Henneke <FabianHenneke@users.noreply.github.com> | 2020-08-06 10:58:20 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-08-06 14:28:20 +0530 |
| commit | 3dace243e4b0fe1378e2d81c46fb70cb236e6ae5 (patch) | |
| tree | a52739e2532e54337adb04468ca66ddd0bd6764d /app/src/main/java/com/zeapo/pwdstore/UserPreference.kt | |
| parent | 14c44bf584cb7d13ada46b264419efca923ed65c (diff) | |
| download | HardenedPass-3dace243e4b0fe1378e2d81c46fb70cb236e6ae5.tar.gz HardenedPass-3dace243e4b0fe1378e2d81c46fb70cb236e6ae5.zip | |
Refactor uses of applicationContext and startActivityForResult (#997)
* Refactor uses of applicationContext and startActivityForResult
This commit applies three types of refactoring:
1. Remove context argument from PasswordRepository companion functions
by relying on Application.instance.
2. Introduce a sharedPrefs extension function on Context that returns
the default SharedPreferences for the applicationContext.
3. Use OpenDocument() and OpenDocumentTree() contracts.
* Drop toPasswordItem argument
Diffstat (limited to 'app/src/main/java/com/zeapo/pwdstore/UserPreference.kt')
| -rw-r--r-- | app/src/main/java/com/zeapo/pwdstore/UserPreference.kt | 150 |
1 files changed, 62 insertions, 88 deletions
diff --git a/app/src/main/java/com/zeapo/pwdstore/UserPreference.kt b/app/src/main/java/com/zeapo/pwdstore/UserPreference.kt index 8938df00..43cab0a0 100644 --- a/app/src/main/java/com/zeapo/pwdstore/UserPreference.kt +++ b/app/src/main/java/com/zeapo/pwdstore/UserPreference.kt @@ -6,6 +6,7 @@ package com.zeapo.pwdstore import android.accessibilityservice.AccessibilityServiceInfo import android.annotation.SuppressLint +import android.content.Context import android.content.Intent import android.content.SharedPreferences import android.content.pm.ShortcutManager @@ -20,8 +21,8 @@ import android.text.TextUtils import android.view.MenuItem import android.view.accessibility.AccessibilityManager import android.widget.Toast -import androidx.activity.result.ActivityResult -import androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult +import androidx.activity.result.contract.ActivityResultContracts.OpenDocument +import androidx.activity.result.contract.ActivityResultContracts.OpenDocumentTree import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.widget.AppCompatTextView import androidx.biometric.BiometricManager @@ -53,6 +54,7 @@ import com.zeapo.pwdstore.utils.PasswordRepository import com.zeapo.pwdstore.utils.PreferenceKeys import com.zeapo.pwdstore.utils.autofillManager import com.zeapo.pwdstore.utils.getEncryptedPrefs +import com.zeapo.pwdstore.utils.sharedPrefs import java.io.File import java.io.IOException @@ -69,15 +71,15 @@ class UserPreference : AppCompatActivity() { private var clearSavedPassPreference: Preference? = null private lateinit var autofillDependencies: List<Preference> private lateinit var oreoAutofillDependencies: List<Preference> - private lateinit var callingActivity: UserPreference + private lateinit var prefsActivity: UserPreference private lateinit var sharedPreferences: SharedPreferences private lateinit var encryptedPreferences: SharedPreferences override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { - callingActivity = requireActivity() as UserPreference + prefsActivity = requireActivity() as UserPreference val context = requireContext() sharedPreferences = preferenceManager.sharedPreferences - encryptedPreferences = requireActivity().applicationContext.getEncryptedPrefs("git_operation") + encryptedPreferences = requireActivity().getEncryptedPrefs("git_operation") addPreferencesFromResource(R.xml.preference) @@ -152,12 +154,12 @@ class UserPreference : AppCompatActivity() { appVersionPreference?.summary = "Version: ${BuildConfig.VERSION_NAME}" sshKeyPreference?.onPreferenceClickListener = ClickListener { - callingActivity.getSshKey() + prefsActivity.getSshKey() true } sshKeygenPreference?.onPreferenceClickListener = ClickListener { - callingActivity.makeSshKey(true) + prefsActivity.makeSshKey(true) true } @@ -185,24 +187,24 @@ class UserPreference : AppCompatActivity() { } gitServerPreference?.onPreferenceClickListener = ClickListener { - startActivity(Intent(callingActivity, GitServerConfigActivity::class.java)) + startActivity(Intent(prefsActivity, GitServerConfigActivity::class.java)) true } gitConfigPreference?.onPreferenceClickListener = ClickListener { - startActivity(Intent(callingActivity, GitConfigActivity::class.java)) + startActivity(Intent(prefsActivity, GitConfigActivity::class.java)) true } deleteRepoPreference?.onPreferenceClickListener = ClickListener { - val repoDir = PasswordRepository.getRepositoryDirectory(callingActivity.applicationContext) - MaterialAlertDialogBuilder(callingActivity) + val repoDir = PasswordRepository.getRepositoryDirectory() + MaterialAlertDialogBuilder(prefsActivity) .setTitle(R.string.pref_dialog_delete_title) .setMessage(resources.getString(R.string.dialog_delete_msg, repoDir)) .setCancelable(false) .setPositiveButton(R.string.dialog_delete) { dialogInterface, _ -> try { - PasswordRepository.getRepositoryDirectory(callingActivity.applicationContext).deleteRecursively() + PasswordRepository.getRepositoryDirectory().deleteRecursively() PasswordRepository.closeRepository() } catch (ignored: Exception) { // TODO Handle the different cases of exceptions @@ -215,7 +217,7 @@ class UserPreference : AppCompatActivity() { } sharedPreferences.edit { putBoolean(PreferenceKeys.REPOSITORY_INITIALIZED, false) } dialogInterface.cancel() - callingActivity.finish() + prefsActivity.finish() } .setNegativeButton(R.string.dialog_do_not_delete) { dialogInterface, _ -> run { dialogInterface.cancel() } } .show() @@ -226,7 +228,7 @@ class UserPreference : AppCompatActivity() { selectExternalGitRepositoryPreference?.summary = sharedPreferences.getString(PreferenceKeys.GIT_EXTERNAL_REPO, context.getString(R.string.no_repo_selected)) selectExternalGitRepositoryPreference?.onPreferenceClickListener = ClickListener { - callingActivity.selectExternalGitRepository() + prefsActivity.selectExternalGitRepository() true } @@ -241,7 +243,7 @@ class UserPreference : AppCompatActivity() { externalGitRepositoryPreference?.onPreferenceChangeListener = resetRepo autoFillAppsPreference?.onPreferenceClickListener = ClickListener { - val intent = Intent(callingActivity, AutofillPreferenceActivity::class.java) + val intent = Intent(prefsActivity, AutofillPreferenceActivity::class.java) startActivity(intent) true } @@ -254,7 +256,7 @@ class UserPreference : AppCompatActivity() { findPreference<Preference>(PreferenceKeys.EXPORT_PASSWORDS)?.apply { isVisible = sharedPreferences.getBoolean(PreferenceKeys.REPOSITORY_INITIALIZED, false) onPreferenceClickListener = Preference.OnPreferenceClickListener { - callingActivity.exportPasswords() + prefsActivity.exportPasswords() true } } @@ -316,7 +318,7 @@ class UserPreference : AppCompatActivity() { val prefCustomXkpwdDictionary = findPreference<Preference>(PreferenceKeys.PREF_KEY_CUSTOM_DICT) prefCustomXkpwdDictionary?.onPreferenceClickListener = ClickListener { - callingActivity.storeCustomDictionaryPath() + prefsActivity.storeCustomDictionaryPath() true } val dictUri = sharedPreferences.getString(PreferenceKeys.PREF_KEY_CUSTOM_DICT, "") @@ -361,8 +363,8 @@ class UserPreference : AppCompatActivity() { } private fun updateAutofillSettings() { - val isAccessibilityServiceEnabled = callingActivity.isAccessibilityServiceEnabled - val isAutofillServiceEnabled = callingActivity.isAutofillServiceEnabled + val isAccessibilityServiceEnabled = prefsActivity.isAccessibilityServiceEnabled + val isAutofillServiceEnabled = prefsActivity.isAutofillServiceEnabled autoFillEnablePreference?.isChecked = isAccessibilityServiceEnabled || isAutofillServiceEnabled autofillDependencies.forEach { @@ -391,16 +393,16 @@ class UserPreference : AppCompatActivity() { } private fun onEnableAutofillClick() { - if (callingActivity.isAccessibilityServiceEnabled) { + if (prefsActivity.isAccessibilityServiceEnabled) { startActivity(Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS)) - } else if (callingActivity.isAutofillServiceEnabled) { + } else if (prefsActivity.isAutofillServiceEnabled) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) - callingActivity.autofillManager!!.disableAutofillServices() + prefsActivity.autofillManager!!.disableAutofillServices() else throw IllegalStateException("isAutofillServiceEnabled == true, but Build.VERSION.SDK_INT < Build.VERSION_CODES.O") } else { - val enableOreoAutofill = callingActivity.isAutofillServiceSupported - MaterialAlertDialogBuilder(callingActivity).run { + val enableOreoAutofill = prefsActivity.isAutofillServiceSupported + MaterialAlertDialogBuilder(prefsActivity).run { setTitle(R.string.pref_autofill_enable_title) if (enableOreoAutofill && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { @SuppressLint("InflateParams") @@ -480,10 +482,8 @@ class UserPreference : AppCompatActivity() { .setTitle(this.resources.getString(R.string.external_repository_dialog_title)) .setMessage(this.resources.getString(R.string.external_repository_dialog_text)) .setPositiveButton(R.string.dialog_ok) { _, _ -> - val i = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE) - registerForActivityResult(StartActivityForResult()) { result -> - if (!validateResult(result)) return@registerForActivityResult - val uri = result.data?.data + registerForActivityResult(OpenDocumentTree()) { uri: Uri? -> + if (uri == null) return@registerForActivityResult tag(TAG).d { "Selected repository URI is $uri" } // TODO: This is fragile. Workaround until PasswordItem is backed by DocumentFile @@ -491,7 +491,7 @@ class UserPreference : AppCompatActivity() { val split = docId.split(":".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() val path = if (split.size > 1) split[1] else split[0] val repoPath = "${Environment.getExternalStorageDirectory()}/$path" - val prefs = PreferenceManager.getDefaultSharedPreferences(applicationContext) + val prefs = sharedPrefs tag(TAG).d { "Selected repository path is $repoPath" } @@ -500,14 +500,14 @@ class UserPreference : AppCompatActivity() { .setTitle(getString(R.string.sdcard_root_warning_title)) .setMessage(getString(R.string.sdcard_root_warning_message)) .setPositiveButton("Remove everything") { _, _ -> - prefs.edit { putString(PreferenceKeys.GIT_EXTERNAL_REPO, uri?.path) } + prefs.edit { putString(PreferenceKeys.GIT_EXTERNAL_REPO, uri.path) } } .setNegativeButton(R.string.dialog_cancel, null) .show() } prefs.edit { putString(PreferenceKeys.GIT_EXTERNAL_REPO, repoPath) } - }.launch(Intent.createChooser(i, "Choose Directory")) + }.launch(null) } .setNegativeButton(R.string.dialog_cancel, null) .show() @@ -528,28 +528,12 @@ class UserPreference : AppCompatActivity() { } /** - * Given a [ActivityResult], validates that the result is usable. - */ - private fun validateResult(result: ActivityResult): Boolean { - if (result.resultCode != RESULT_OK) { - return false - } - if (result.data == null) { - setResult(RESULT_CANCELED) - return false - } - return true - } - - /** * Opens a file explorer to import the private key */ private fun getSshKey() { - registerForActivityResult(StartActivityForResult()) { result -> - if (!validateResult(result)) return@registerForActivityResult + registerForActivityResult(OpenDocument()) { uri: Uri? -> + if (uri == null) return@registerForActivityResult try { - val uri: Uri = result.data?.data ?: throw IOException("Unable to open file") - copySshKey(uri) Toast.makeText( @@ -557,7 +541,7 @@ class UserPreference : AppCompatActivity() { this.resources.getString(R.string.ssh_key_success_dialog_title), Toast.LENGTH_LONG ).show() - val prefs = PreferenceManager.getDefaultSharedPreferences(applicationContext) + val prefs = sharedPrefs prefs.edit { putBoolean(PreferenceKeys.USE_GENERATED_KEY, false) } getEncryptedPrefs("git_operation").edit { remove(PreferenceKeys.SSH_KEY_LOCAL_PASSPHRASE) } @@ -574,44 +558,39 @@ class UserPreference : AppCompatActivity() { .setPositiveButton(resources.getString(R.string.dialog_ok), null) .show() } - }.launch(Intent(Intent.ACTION_OPEN_DOCUMENT).apply { - addCategory(Intent.CATEGORY_OPENABLE) - type = "*/*" - }) + }.launch(arrayOf("*/*")) } /** * Exports the passwords */ private fun exportPasswords() { - val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE).apply { - flags = Intent.FLAG_GRANT_READ_URI_PERMISSION or - Intent.FLAG_GRANT_WRITE_URI_PERMISSION or - Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION or - Intent.FLAG_GRANT_PREFIX_URI_PERMISSION - } - - registerForActivityResult(StartActivityForResult()) { result -> - if (!validateResult(result)) return@registerForActivityResult - val uri = result.data?.data - - if (uri != null) { - val targetDirectory = DocumentFile.fromTreeUri(applicationContext, uri) - - if (targetDirectory != null) { - val service = Intent(applicationContext, PasswordExportService::class.java).apply { - action = PasswordExportService.ACTION_EXPORT_PASSWORD - putExtra("uri", uri) - } + registerForActivityResult(object : OpenDocumentTree() { + override fun createIntent(context: Context, input: Uri?): Intent { + return super.createIntent(context, input).apply { + flags = Intent.FLAG_GRANT_READ_URI_PERMISSION or + Intent.FLAG_GRANT_WRITE_URI_PERMISSION or + Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION or + Intent.FLAG_GRANT_PREFIX_URI_PERMISSION + } + } + }) { uri: Uri? -> + if (uri == null) return@registerForActivityResult + val targetDirectory = DocumentFile.fromTreeUri(applicationContext, uri) + + if (targetDirectory != null) { + val service = Intent(applicationContext, PasswordExportService::class.java).apply { + action = PasswordExportService.ACTION_EXPORT_PASSWORD + putExtra("uri", uri) + } - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - startForegroundService(service) - } else { - startService(service) - } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + startForegroundService(service) + } else { + startService(service) } } - }.launch(intent) + }.launch(null) } /** @@ -630,18 +609,16 @@ class UserPreference : AppCompatActivity() { * Pick custom xkpwd dictionary from sdcard */ private fun storeCustomDictionaryPath() { - registerForActivityResult(StartActivityForResult()) { result -> - if (!validateResult(result)) return@registerForActivityResult - val uri: Uri = result.data?.data ?: throw IOException("Unable to open file") + registerForActivityResult(OpenDocument()) { uri -> + if (uri == null) return@registerForActivityResult Toast.makeText( this, this.resources.getString(R.string.xkpwgen_custom_dict_imported, uri.path), Toast.LENGTH_SHORT ).show() - val prefs = PreferenceManager.getDefaultSharedPreferences(applicationContext) - prefs.edit { putString(PreferenceKeys.PREF_KEY_CUSTOM_DICT, uri.toString()) } + sharedPrefs.edit { putString(PreferenceKeys.PREF_KEY_CUSTOM_DICT, uri.toString()) } val customDictPref = prefsFragment.findPreference<Preference>(PreferenceKeys.PREF_KEY_CUSTOM_DICT) setCustomDictSummary(customDictPref, uri) @@ -653,10 +630,7 @@ class UserPreference : AppCompatActivity() { customDictFile.close() setResult(RESULT_OK) - }.launch(Intent(Intent.ACTION_OPEN_DOCUMENT).apply { - addCategory(Intent.CATEGORY_OPENABLE) - type = "*/*" - }) + }.launch(arrayOf("*/*")) } @Throws(IllegalArgumentException::class, IOException::class) |
