diff options
author | Matthew Wong <wongma@protonmail.ch> | 2015-07-28 09:15:41 -0400 |
---|---|---|
committer | Matthew Wong <wongma@protonmail.ch> | 2015-08-14 17:36:45 -0400 |
commit | 8c266187cb1a1264034fe2637d3b22e67284b0b5 (patch) | |
tree | 90cb6028e945baba89418e9b7b0653d6730f2cc7 | |
parent | e937ddf11121e919d27bcb9fd3c3e11e88e3ba3c (diff) |
Fill in field immediately after user unlocks
-rw-r--r-- | app/src/main/java/com/zeapo/pwdstore/AutofillActivity.java | 6 | ||||
-rw-r--r-- | app/src/main/java/com/zeapo/pwdstore/AutofillService.java | 65 | ||||
-rw-r--r-- | app/src/main/res/xml/autofill_config.xml | 2 |
3 files changed, 40 insertions, 33 deletions
diff --git a/app/src/main/java/com/zeapo/pwdstore/AutofillActivity.java b/app/src/main/java/com/zeapo/pwdstore/AutofillActivity.java index f52fe0a2..2a1227b9 100644 --- a/app/src/main/java/com/zeapo/pwdstore/AutofillActivity.java +++ b/app/src/main/java/com/zeapo/pwdstore/AutofillActivity.java @@ -7,7 +7,7 @@ import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.util.Log; - +// blank activity started by service for calling startIntentSenderForResult public class AutofillActivity extends AppCompatActivity { public static final int REQUEST_CODE_DECRYPT_AND_VERIFY = 9913; private boolean bound = false; @@ -27,9 +27,9 @@ public class AutofillActivity extends AppCompatActivity { @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { - finish(); + finish(); // go back to the password field app if (resultCode == RESULT_OK) { - AutofillService.getService().decryptAndVerify(); + AutofillService.setUnlockOK(); // report the result to service } } } diff --git a/app/src/main/java/com/zeapo/pwdstore/AutofillService.java b/app/src/main/java/com/zeapo/pwdstore/AutofillService.java index ca738c67..58bb0994 100644 --- a/app/src/main/java/com/zeapo/pwdstore/AutofillService.java +++ b/app/src/main/java/com/zeapo/pwdstore/AutofillService.java @@ -40,29 +40,40 @@ public class AutofillService extends AccessibilityService { private OpenPgpServiceConnection serviceConnection; private SharedPreferences settings; private AccessibilityNodeInfo info; // the original source of the event (the edittext field) - private ArrayList<PasswordItem> items; - private static AutofillService service; + private ArrayList<PasswordItem> items; // password choices + private AlertDialog dialog; + private static boolean unlockOK = false; // if openkeychain user interaction was successful + private static CharSequence packageName; + private static boolean ignoreActionFocus = false; public final class Constants { public static final String TAG = "Keychain"; } + public static void setUnlockOK() { unlockOK = true; } + @Override protected void onServiceConnected() { super.onServiceConnected(); serviceConnection = new OpenPgpServiceConnection(AutofillService.this, "org.sufficientlysecure.keychain"); serviceConnection.bindToService(); settings = PreferenceManager.getDefaultSharedPreferences(this); - service = this; - } - - public static AutofillService getService() { - return service; } @Override public void onAccessibilityEvent(AccessibilityEvent event) { - if (!event.isPassword() || Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) { + if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED + && event.getPackageName().equals(packageName) && unlockOK) { + decryptAndVerify(); + } + if (!event.isPassword() + || Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2 + || (dialog != null && dialog.isShowing()) + || event.getPackageName().equals("org.sufficientlysecure.keychain")) { + return; + } + if (ignoreActionFocus) { + ignoreActionFocus = false; return; } info = event.getSource(); @@ -74,29 +85,23 @@ public class AutofillService extends AccessibilityService { applicationInfo = null; } String appName = (applicationInfo != null ? packageManager.getApplicationLabel(applicationInfo) : "").toString(); - if (appName.equals("OpenKeychain")) { - return; - } items = recursiveFilter(appName, null); if (items.isEmpty()) { return; } - ArrayList<CharSequence> itemNames = new ArrayList<>(); - for (PasswordItem item : items) { - itemNames.add(item.toString()); - } - AlertDialog.Builder builder = new AlertDialog.Builder(this, R.style.Theme_AppCompat_Light_Dialog_Alert); - builder.setNegativeButton("Cancel", null); - builder.setView(R.layout.autofill_layout); - final AlertDialog dialog = builder.create(); - - dialog.setTitle("Fill with Password Store"); - dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); - dialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE); - dialog.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND); + if (dialog == null) { + AlertDialog.Builder builder = new AlertDialog.Builder(this, R.style.Theme_AppCompat_Light_Dialog_Alert); + builder.setNegativeButton("Cancel", null); + builder.setView(R.layout.autofill_layout); + dialog = builder.create(); + dialog.setTitle("Fill with Password Store"); + dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); + dialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE); + dialog.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND); + } dialog.show(); - ((Button) dialog.findViewById(R.id.button)).setText(itemNames.get(0).toString()); + ((Button) dialog.findViewById(R.id.button)).setText(items.get(0).getName()); dialog.findViewById(R.id.button).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { @@ -131,6 +136,8 @@ public class AutofillService extends AccessibilityService { } public void decryptAndVerify() { + unlockOK = false; + packageName = info.getPackageName(); Intent data = new Intent(); data.setAction(OpenPgpApi.ACTION_DECRYPT_VERIFY); InputStream is = null; @@ -147,16 +154,16 @@ public class AutofillService extends AccessibilityService { case OpenPgpApi.RESULT_CODE_SUCCESS: { try { String[] passContent = os.toString("UTF-8").split("\n"); + // if the user focused on something else, take focus back + // but this will open another dialog...hack to ignore this + ignoreActionFocus = true; + info.performAction(AccessibilityNodeInfo.ACTION_FOCUS); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - // if the user focused on something else, take focus back - // but this will open another dialog... - info.performAction(AccessibilityNodeInfo.ACTION_FOCUS); Bundle args = new Bundle(); args.putCharSequence(AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE, passContent[0]); info.performAction(AccessibilityNodeInfo.ACTION_SET_TEXT, args); } else { - info.performAction(AccessibilityNodeInfo.ACTION_FOCUS); ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE); ClipData clip = ClipData.newPlainText("autofill_pm", passContent[0]); clipboard.setPrimaryClip(clip); diff --git a/app/src/main/res/xml/autofill_config.xml b/app/src/main/res/xml/autofill_config.xml index 618442ab..93125a51 100644 --- a/app/src/main/res/xml/autofill_config.xml +++ b/app/src/main/res/xml/autofill_config.xml @@ -1,6 +1,6 @@ <accessibility-service xmlns:android="http://schemas.android.com/apk/res/android" android:description="@string/autofill_description" - android:accessibilityEventTypes="typeViewFocused" + android:accessibilityEventTypes="typeViewFocused|typeWindowStateChanged" android:accessibilityFlags="flagDefault" android:accessibilityFeedbackType="feedbackGeneric" android:notificationTimeout="100" |