Skip to content
This repository has been archived by the owner on Oct 15, 2024. It is now read-only.

Break down PGP Activity into focused sections #776

Merged
merged 52 commits into from
Jun 12, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
7d70a38
Squashed bringup of new PGP activities
msfjarvis Jun 1, 2020
7f997b0
Fix lint warning
msfjarvis Jun 1, 2020
760ef6b
Code cleanups
msfjarvis Jun 3, 2020
bf059f1
DecryptActivity: fix derp
msfjarvis Jun 3, 2020
f81042c
Cleanup some PgpActivity uses in preparation for removal
msfjarvis Jun 3, 2020
928e9c7
Wire in password edit support
msfjarvis Jun 7, 2020
38eb5de
Improve OpenKeychain binding code
msfjarvis Jun 7, 2020
941d016
Fix clipboard service startup
msfjarvis Jun 7, 2020
258e0ab
Remove LocalBroadcastManager
msfjarvis Jun 7, 2020
182d271
Port GET_KEY_IDS to BasePgpActivity
msfjarvis Jun 8, 2020
f2d4495
Good bye PgpActivity :wave:
msfjarvis Jun 8, 2020
bdb9bd9
UserPreference: fix braindead code
msfjarvis Jun 8, 2020
437c6f1
Codestyle fixups
msfjarvis Jun 8, 2020
8f6f96f
Fix comment
msfjarvis Jun 8, 2020
7262ace
Document BasePgpActivity methods
msfjarvis Jun 8, 2020
206794f
Fix GetKeyIdsActivity
msfjarvis Jun 8, 2020
e5812b1
style
msfjarvis Jun 8, 2020
f5df642
ClipboardService: privatize const
msfjarvis Jun 8, 2020
c892c8d
Merge branch 'master' into refactor/pgp-activity-breakdown
msfjarvis Jun 9, 2020
a2df464
Merge branch 'master' into refactor/pgp-activity-breakdown
msfjarvis Jun 10, 2020
23ccaf8
Refactor clipboard copy flow and improve layout IDs
msfjarvis Jun 10, 2020
503ea97
Rename and move PasswordCreationActivity extras to const vals
msfjarvis Jun 10, 2020
0efffb7
Fix binding fallback
msfjarvis Jun 10, 2020
fec3190
Disallow editing from password fragment
msfjarvis Jun 10, 2020
abea355
Fix decryptAndVerify not being called when finishing without changes
msfjarvis Jun 10, 2020
d5eee35
Merge branch 'master' into refactor/pgp-activity-breakdown
msfjarvis Jun 10, 2020
7c7556f
Apply #843 changes to BasePgpActivity
msfjarvis Jun 10, 2020
01f1d31
Cleanups
msfjarvis Jun 10, 2020
ca6fbac
remove REQUEST_CODE_EDIT
msfjarvis Jun 10, 2020
34b4c4a
Remove unnecessary ClipboardUtils class
msfjarvis Jun 11, 2020
6630417
Move commitChange method to an activity extension
msfjarvis Jun 11, 2020
7aef90f
DecryptActivity: commit changes if there are any
msfjarvis Jun 11, 2020
c9efe62
Commit silently, without a progress dialog
msfjarvis Jun 11, 2020
14ac83b
DecryptActivity: use full path to file in commit message
msfjarvis Jun 11, 2020
4574556
DecryptActivity: ensure we also pass extra content
msfjarvis Jun 11, 2020
820faed
Constify more intent extras
msfjarvis Jun 11, 2020
a6cfde8
Can't stop cleaning up
msfjarvis Jun 11, 2020
603a7fb
strings: capitalize app name in commit messages
msfjarvis Jun 11, 2020
6963d0c
Merge branch 'master' into refactor/pgp-activity-breakdown
msfjarvis Jun 11, 2020
e1f74e4
PasswordCreationActivity: eagerly bind to OpenKeychain
msfjarvis Jun 11, 2020
ba9510a
Address review comments
msfjarvis Jun 12, 2020
4d64860
Fix use of deprecated MasterKeys
msfjarvis Jun 12, 2020
70d5b92
DecryptActivity: set title to filename
msfjarvis Jun 12, 2020
e96e896
Remove dangling comment
msfjarvis Jun 12, 2020
392edb7
Switch to stdlib API for getRelativePath
msfjarvis Jun 12, 2020
c18ce17
Revert "Switch to stdlib API for getRelativePath"
msfjarvis Jun 12, 2020
f5a408e
update CHANGELOG
msfjarvis Jun 12, 2020
8c5c28e
Remove the godforsaken kotlin-android-extensions plugin
msfjarvis Jun 12, 2020
61e0c1b
UserPreference: remove some unused request codes
msfjarvis Jun 12, 2020
02cebd8
Merge branch 'master' into refactor/pgp-activity-breakdown
Jun 12, 2020
5375842
Address Fabian's comments
msfjarvis Jun 12, 2020
5eacee1
Add missing EXTRA_EDITING
msfjarvis Jun 12, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,14 @@ All notable changes to this project will be documented in this file.
- Completely revamped decypted password view
- Add support for better, more secure Keyex's and MACs with a brand new SSH backend
- Allow manually marking domains for subdomain-level association. This will allow you to keep separate passwords for `site1.example.com` and `site2.example.com` and have them show as such in Autofill.
- Provide better messages for OpenKeychain errors

### Changed
- **BREAKING**: Remove support for HOTP/TOTP secrets - Please use FIDO keys or a dedicated app like [Aegis](https://github.com/beemdevelopment/Aegis) or [andOTP](https://github.com/andOTP/andOTP)
- Reduce Autofill false positives on username fields by removing "name" from list of heuristic terms
- Reduced app size
- Improve IME experience with server config screen
- Removed edit password option from long-press menu.

## [1.8.1] - 2020-05-24

Expand Down
2 changes: 0 additions & 2 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
*/
plugins {
id 'kotlin-android'
id 'kotlin-android-extensions'
}

final def keystorePropertiesFile = rootProject.file 'keystore.properties'
Expand Down Expand Up @@ -83,7 +82,6 @@ dependencies {
implementation deps.androidx.lifecycle_common
implementation deps.androidx.lifecycle_livedata_ktx
implementation deps.androidx.lifecycle_viewmodel_ktx
implementation deps.androidx.local_broadcast_manager
implementation deps.androidx.material
implementation deps.androidx.preference
implementation deps.androidx.recycler_view
Expand Down
21 changes: 16 additions & 5 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,22 @@
android:label="@string/action_settings"
android:parentActivityName=".PasswordStore" />

<activity
android:name=".crypto.PasswordCreationActivity"
android:label="@string/new_password_title"
android:parentActivityName=".PasswordStore"
android:windowSoftInputMode="adjustResize" />

<activity
android:name=".crypto.DecryptActivity"
android:parentActivityName=".PasswordStore"
msfjarvis marked this conversation as resolved.
Show resolved Hide resolved
android:windowSoftInputMode="adjustResize" />

<activity
android:name=".crypto.GetKeyIdsActivity"
android:parentActivityName=".PasswordStore"
android:theme="@style/NoBackgroundTheme" />

<service
android:name=".autofill.AutofillService"
android:enabled="@bool/enable_accessibility_autofill"
Expand Down Expand Up @@ -98,11 +114,6 @@

<activity android:name=".autofill.AutofillPreferenceActivity" />

<activity
android:name=".crypto.PgpActivity"
android:configChanges="orientation|screenSize"
android:parentActivityName=".PasswordStore"
android:windowSoftInputMode="adjustResize" />
<activity android:name=".SelectFolderActivity" />
<activity
android:name=".sshkeygen.SshKeyGenActivity"
Expand Down
30 changes: 16 additions & 14 deletions app/src/main/java/com/zeapo/pwdstore/ClipboardService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,16 @@ import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.app.Service
import android.content.ClipboardManager
import android.content.ClipData
import android.content.Intent
import android.content.SharedPreferences
import android.os.Build
import android.os.IBinder
import androidx.core.app.NotificationCompat
import androidx.core.content.getSystemService
import androidx.localbroadcastmanager.content.LocalBroadcastManager
import androidx.preference.PreferenceManager
import com.github.ajalt.timberkt.d
import com.zeapo.pwdstore.utils.ClipboardUtils
import com.zeapo.pwdstore.utils.clipboard
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
Expand Down Expand Up @@ -60,7 +59,6 @@ class ClipboardService : Service() {
startTimer(time)
}
withContext(Dispatchers.Main) {
emitBroadcast()
clearClipboard()
stopForeground(true)
stopSelf()
Expand All @@ -85,11 +83,21 @@ class ClipboardService : Service() {

private fun clearClipboard() {
val deepClear = settings.getBoolean("clear_clipboard_20x", false)
val clipboardManager = getSystemService<ClipboardManager>()
val clipboard = clipboard

if (clipboardManager is ClipboardManager) {
if (clipboard != null) {
scope.launch {
fmeum marked this conversation as resolved.
Show resolved Hide resolved
ClipboardUtils.clearClipboard(clipboardManager, deepClear)
d { "Clearing the clipboard" }
val clip = ClipData.newPlainText("pgp_handler_result_pm", "")
clipboard.setPrimaryClip(clip)
if (deepClear) {
withContext(Dispatchers.IO) {
repeat(20) {
val count = (it * 500).toString()
clipboard.setPrimaryClip(ClipData.newPlainText(count, count))
}
}
}
}
} else {
d { "Cannot get clipboard manager service" }
Expand All @@ -105,12 +113,6 @@ class ClipboardService : Service() {
}
}

private fun emitBroadcast() {
val localBroadcastManager = LocalBroadcastManager.getInstance(this)
val clearIntent = Intent(ACTION_CLEAR)
localBroadcastManager.sendBroadcast(clearIntent)
}

private fun createNotification() {
createNotificationChannel()
val clearIntent = Intent(this, ClipboardService::class.java)
Expand Down Expand Up @@ -151,7 +153,7 @@ class ClipboardService : Service() {

companion object {
private const val ACTION_CLEAR = "ACTION_CLEAR_CLIPBOARD"
private const val ACTION_START = "ACTION_START_CLIPBOARD_TIMER"
const val ACTION_START = "ACTION_START_CLIPBOARD_TIMER"
private const val CHANNEL_ID = "NotificationService"
}
}
11 changes: 7 additions & 4 deletions app/src/main/java/com/zeapo/pwdstore/LaunchActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import android.os.Handler
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.edit
import androidx.preference.PreferenceManager
import com.zeapo.pwdstore.crypto.PgpActivity
import com.zeapo.pwdstore.crypto.DecryptActivity
import com.zeapo.pwdstore.utils.BiometricAuthenticator

class LaunchActivity : AppCompatActivity() {
Expand Down Expand Up @@ -39,18 +39,21 @@ class LaunchActivity : AppCompatActivity() {
}

private fun startTargetActivity(noAuth: Boolean) {
if (intent?.getStringExtra("OPERATION") == "DECRYPT") {
val decryptIntent = Intent(this, PgpActivity::class.java)
if (intent.action == ACTION_DECRYPT_PASS) {
val decryptIntent = Intent(this, DecryptActivity::class.java)
decryptIntent.putExtra("NAME", intent.getStringExtra("NAME"))
decryptIntent.putExtra("FILE_PATH", intent.getStringExtra("FILE_PATH"))
decryptIntent.putExtra("REPO_PATH", intent.getStringExtra("REPO_PATH"))
decryptIntent.putExtra("LAST_CHANGED_TIMESTAMP", intent.getLongExtra("LAST_CHANGED_TIMESTAMP", 0L))
decryptIntent.putExtra("OPERATION", "DECRYPT")
startActivity(decryptIntent)
msfjarvis marked this conversation as resolved.
Show resolved Hide resolved
} else {
startActivity(Intent(this, PasswordStore::class.java))
}
overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out)
Handler().postDelayed({ finish() }, if (noAuth) 0L else 500L)
}

companion object {
const val ACTION_DECRYPT_PASS = "DECRYPT_PASS"
}
}
13 changes: 1 addition & 12 deletions app/src/main/java/com/zeapo/pwdstore/PasswordFragment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -155,11 +155,7 @@ class PasswordFragment : Fragment(R.layout.password_recycler_view) {
// Called each time the action mode is shown. Always called after onCreateActionMode, but
// may be called multiple times if the mode is invalidated.
override fun onPrepareActionMode(mode: ActionMode, menu: Menu): Boolean {
menu.findItem(R.id.menu_edit_password).isVisible =
recyclerAdapter.getSelectedItems(requireContext())
.map { it.type == PasswordItem.TYPE_PASSWORD }
.singleOrNull() == true
return true // Return false if nothing is done
return true
}

// Called when the user selects a contextual menu item
Expand All @@ -174,13 +170,6 @@ class PasswordFragment : Fragment(R.layout.password_recycler_view) {
mode.finish() // Action picked, so close the CAB
return true
}
R.id.menu_edit_password -> {
requireStore().editPassword(
recyclerAdapter.getSelectedItems(requireContext()).first()
)
mode.finish()
return true
}
R.id.menu_move_password -> {
requireStore().movePasswords(recyclerAdapter.getSelectedItems(requireContext()))
return false
Expand Down
62 changes: 10 additions & 52 deletions app/src/main/java/com/zeapo/pwdstore/PasswordStore.kt
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,10 @@ import com.google.android.material.snackbar.Snackbar
import com.zeapo.pwdstore.autofill.oreo.AutofillMatcher
import com.zeapo.pwdstore.autofill.oreo.BrowserAutofillSupportLevel
import com.zeapo.pwdstore.autofill.oreo.getInstalledBrowsersWithAutofillSupportLevel
import com.zeapo.pwdstore.crypto.PgpActivity
import com.zeapo.pwdstore.crypto.PgpActivity.Companion.getLongName
import com.zeapo.pwdstore.crypto.BasePgpActivity.Companion.getLongName
import com.zeapo.pwdstore.crypto.DecryptActivity
import com.zeapo.pwdstore.crypto.PasswordCreationActivity
import com.zeapo.pwdstore.git.BaseGitActivity
import com.zeapo.pwdstore.git.GitAsyncTask
import com.zeapo.pwdstore.git.GitOperation
import com.zeapo.pwdstore.git.GitOperationActivity
import com.zeapo.pwdstore.git.GitServerConfigActivity
import com.zeapo.pwdstore.git.config.ConnectionMode
Expand All @@ -65,6 +64,7 @@ import com.zeapo.pwdstore.utils.PasswordRepository.Companion.getRepositoryDirect
import com.zeapo.pwdstore.utils.PasswordRepository.Companion.initialize
import com.zeapo.pwdstore.utils.PasswordRepository.Companion.isInitialized
import com.zeapo.pwdstore.utils.PasswordRepository.PasswordSortOrder.Companion.getSortOrder
import com.zeapo.pwdstore.utils.commitChange
import com.zeapo.pwdstore.utils.listFilesRecursively
import org.eclipse.jgit.api.Git
import org.eclipse.jgit.api.errors.GitAPIException
Expand All @@ -73,7 +73,7 @@ import java.io.File
import java.lang.Character.UnicodeBlock
import java.util.Stack

class PasswordStore : AppCompatActivity() {
class PasswordStore : AppCompatActivity(R.layout.activity_pwdstore) {

private lateinit var activity: PasswordStore
private lateinit var searchItem: MenuItem
Expand Down Expand Up @@ -123,7 +123,6 @@ class PasswordStore : AppCompatActivity() {
savedInstance = null
}
super.onCreate(savedInstance)
setContentView(R.layout.activity_pwdstore)

// If user is eligible for Oreo autofill, prompt them to switch.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O &&
Expand Down Expand Up @@ -487,23 +486,24 @@ class PasswordStore : AppCompatActivity() {
}

fun decryptPassword(item: PasswordItem) {
val decryptIntent = Intent(this, PgpActivity::class.java)
val decryptIntent = Intent(this, DecryptActivity::class.java)
val authDecryptIntent = Intent(this, LaunchActivity::class.java)
for (intent in arrayOf(decryptIntent, authDecryptIntent)) {
intent.putExtra("NAME", item.toString())
intent.putExtra("FILE_PATH", item.file.absolutePath)
intent.putExtra("REPO_PATH", getRepositoryDirectory(applicationContext).absolutePath)
intent.putExtra("LAST_CHANGED_TIMESTAMP", getLastChangedTimestamp(item.file.absolutePath))
intent.putExtra("OPERATION", "DECRYPT")
}
// Needs an action to be a shortcut intent
authDecryptIntent.action = LaunchActivity.ACTION_DECRYPT_PASS

// Adds shortcut
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) {
val shortcut = Builder(this, item.fullPathToParent)
.setShortLabel(item.toString())
.setLongLabel(item.fullPathToParent + item.toString())
.setIcon(Icon.createWithResource(this, R.mipmap.ic_launcher))
.setIntent(authDecryptIntent.setAction("DECRYPT_PASS")) // Needs action
.setIntent(authDecryptIntent)
.build()
val shortcuts = shortcutManager!!.dynamicShortcuts
if (shortcuts.size >= shortcutManager!!.maxShortcutCountPerActivity && shortcuts.size > 0) {
Expand All @@ -517,16 +517,6 @@ class PasswordStore : AppCompatActivity() {
startActivityForResult(decryptIntent, REQUEST_CODE_DECRYPT_AND_VERIFY)
}

fun editPassword(item: PasswordItem) {
val intent = Intent(this, PgpActivity::class.java)
intent.putExtra("NAME", item.toString())
intent.putExtra("FILE_PATH", item.file.absolutePath)
intent.putExtra("PARENT_PATH", item.file.parentFile!!.absolutePath)
intent.putExtra("REPO_PATH", getRepositoryDirectory(applicationContext).absolutePath)
intent.putExtra("OPERATION", "EDIT")
startActivityForResult(intent, REQUEST_CODE_EDIT)
}

private fun validateState(): Boolean {
if (!isInitialized) {
MaterialAlertDialogBuilder(this)
Expand All @@ -553,10 +543,9 @@ class PasswordStore : AppCompatActivity() {
if (!validateState()) return
val currentDir = currentDir
tag(TAG).i { "Adding file to : ${currentDir.absolutePath}" }
val intent = Intent(this, PgpActivity::class.java)
val intent = Intent(this, PasswordCreationActivity::class.java)
intent.putExtra("FILE_PATH", currentDir.absolutePath)
intent.putExtra("REPO_PATH", getRepositoryDirectory(applicationContext).absolutePath)
intent.putExtra("OPERATION", "ENCRYPT")
startActivityForResult(intent, REQUEST_CODE_ENCRYPT)
}

Expand Down Expand Up @@ -626,10 +615,6 @@ class PasswordStore : AppCompatActivity() {
private val currentDir: File
get() = plist?.currentDir ?: getRepositoryDirectory(applicationContext)

private fun commitChange(message: String) {
commitChange(this, message)
}

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
if (resultCode == Activity.RESULT_OK) {
when (requestCode) {
Expand All @@ -650,11 +635,6 @@ class PasswordStore : AppCompatActivity() {
data!!.extras!!.getString("LONG_NAME")))
refreshPasswordList()
}
REQUEST_CODE_EDIT -> {
commitChange(resources.getString(R.string.git_commit_edit_text,
data!!.extras!!.getString("LONG_NAME")))
refreshPasswordList()
}
BaseGitActivity.REQUEST_INIT, NEW_REPO_BUTTON -> initializeRepositoryInfo()
BaseGitActivity.REQUEST_SYNC, BaseGitActivity.REQUEST_PULL -> resetPasswordList()
HOME -> checkLocalRepository()
Expand Down Expand Up @@ -821,7 +801,6 @@ class PasswordStore : AppCompatActivity() {
companion object {
const val REQUEST_CODE_ENCRYPT = 9911
const val REQUEST_CODE_DECRYPT_AND_VERIFY = 9913
const val REQUEST_CODE_EDIT = 9916
const val REQUEST_CODE_SELECT_FOLDER = 9917
const val REQUEST_ARG_PATH = "PATH"
private val TAG = PasswordStore::class.java.name
Expand All @@ -836,26 +815,5 @@ class PasswordStore : AppCompatActivity() {
}

private const val PREFERENCE_SEEN_AUTOFILL_ONBOARDING = "seen_autofill_onboarding"

fun commitChange(activity: Activity, message: String, finishWithResultOnEnd: Intent? = null) {
if (!PasswordRepository.isGitRepo()) {
if (finishWithResultOnEnd != null) {
activity.setResult(Activity.RESULT_OK, finishWithResultOnEnd)
activity.finish()
}
return
}
object : GitOperation(getRepositoryDirectory(activity), activity) {
override fun execute() {
tag(TAG).d { "Committing with message $message" }
val git = Git(repository)
val tasks = GitAsyncTask(activity, true, this, finishWithResultOnEnd)
tasks.execute(
git.add().addFilepattern("."),
git.commit().setAll(true).setMessage(message)
)
}
}.execute()
}
}
}
Loading