aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Wong <wongma@protonmail.ch>2015-07-28 09:15:41 -0400
committerMatthew Wong <wongma@protonmail.ch>2015-08-14 17:36:45 -0400
commit8c266187cb1a1264034fe2637d3b22e67284b0b5 (patch)
tree90cb6028e945baba89418e9b7b0653d6730f2cc7
parente937ddf11121e919d27bcb9fd3c3e11e88e3ba3c (diff)
Fill in field immediately after user unlocks
-rw-r--r--app/src/main/java/com/zeapo/pwdstore/AutofillActivity.java6
-rw-r--r--app/src/main/java/com/zeapo/pwdstore/AutofillService.java65
-rw-r--r--app/src/main/res/xml/autofill_config.xml2
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"