set and pick from multiple passwords per app

This commit is contained in:
Matthew Wong
2015-11-07 16:25:22 -05:00
parent 72e32c95f6
commit 8fa173e7d2
4 changed files with 140 additions and 73 deletions

View File

@@ -4,6 +4,7 @@ import android.app.Activity;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
@@ -12,15 +13,20 @@ import android.content.SharedPreferences;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.EditText;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.TextView;
import com.zeapo.pwdstore.PasswordStore;
import com.zeapo.pwdstore.R;
public class AutofillFragment extends DialogFragment {
private static final int MATCH_WITH = 777;
ArrayAdapter<String> adapter;
public AutofillFragment() {
}
@@ -47,6 +53,27 @@ public class AutofillFragment extends DialogFragment {
e.printStackTrace();
}
// set up the listview now for items added by button/from preferences
adapter = new ArrayAdapter<String>(getActivity().getApplicationContext()
, android.R.layout.simple_list_item_1, android.R.id.text1) {
// set text color to black because default is white...
@Override
public View getView(int position, View convertView, ViewGroup parent) {
TextView textView = (TextView) super.getView(position, convertView, parent);
textView.setTextColor(ContextCompat.getColor(getContext(), R.color.grey_black_1000));
return textView;
}
};
((ListView) view.findViewById(R.id.matched)).setAdapter(adapter);
// delete items by clicking them
((ListView) view.findViewById(R.id.matched)).setOnItemClickListener(
new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
adapter.remove(adapter.getItem(position));
}
});
SharedPreferences prefs
= getActivity().getApplicationContext().getSharedPreferences("autofill", Context.MODE_PRIVATE);
String preference = prefs.getString(packageName, "");
@@ -62,9 +89,11 @@ public class AutofillFragment extends DialogFragment {
break;
default:
((RadioButton) view.findViewById(R.id.match)).toggle();
((EditText) view.findViewById(R.id.matched)).setText(preference);
// trim to remove the last blank element
adapter.addAll(preference.trim().split("\n"));
}
// add items with the + button
View.OnClickListener matchPassword = new View.OnClickListener() {
@Override
public void onClick(View v) {
@@ -74,8 +103,7 @@ public class AutofillFragment extends DialogFragment {
startActivityForResult(intent, MATCH_WITH);
}
};
view.findViewById(R.id.match).setOnClickListener(matchPassword);
view.findViewById(R.id.matched).setOnClickListener(matchPassword);
view.findViewById(R.id.matchButton).setOnClickListener(matchPassword);
final SharedPreferences.Editor editor = prefs.edit();
builder.setPositiveButton(R.string.dialog_ok, new DialogInterface.OnClickListener() {
@@ -93,9 +121,14 @@ public class AutofillFragment extends DialogFragment {
editor.putString(packageName, "/never");
break;
default:
EditText matched = (EditText) view.findViewById(R.id.matched);
String path = matched.getText().toString();
editor.putString(packageName, path);
StringBuilder paths = new StringBuilder();
for (int i = 0; i < adapter.getCount(); i++) {
paths.append(adapter.getItem(i));
if (i != adapter.getCount()) {
paths.append("\n");
}
}
editor.putString(packageName, paths.toString());
}
editor.apply();
@@ -113,9 +146,7 @@ public class AutofillFragment extends DialogFragment {
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == Activity.RESULT_OK) {
((EditText) getDialog().findViewById(R.id.matched)).setText(data.getStringExtra("path"));
} else {
((RadioButton) getDialog().findViewById(R.id.use_default)).toggle();
adapter.add(data.getStringExtra("path"));
}
}
}

View File

@@ -110,7 +110,7 @@ public class AutofillRecyclerAdapter extends RecyclerView.Adapter<AutofillRecycl
holder.secondary.setText(R.string.autofill_apps_never);
break;
default:
holder.secondary.setText("Match with " + preference);
holder.secondary.setText("Match with " + preference.split("\n")[0]);
break;
}
}

View File

@@ -44,6 +44,7 @@ public class AutofillService extends AccessibilityService {
private SharedPreferences settings;
private AccessibilityNodeInfo info; // the original source of the event (the edittext field)
private ArrayList<File> items; // password choices
private int lastWhichItem;
private AlertDialog dialog;
private AccessibilityWindowInfo window;
private static Intent resultData = null; // need the intent which contains results from user interaction
@@ -199,9 +200,14 @@ public class AutofillService extends AccessibilityService {
if (!PasswordRepository.isInitialized()) {
PasswordRepository.initialize(this);
}
String path = PasswordRepository.getWorkTree() + "/" + preference + ".gpg";
String preferred[] = preference.split("\n");
items = new ArrayList<>();
items.add(new File(path));
for (String prefer : preferred) {
String path = PasswordRepository.getWorkTree() + "/" + prefer + ".gpg";
if (new File(path).exists()) {
items.add(new File(path));
}
}
}
}
@@ -237,12 +243,12 @@ public class AutofillService extends AccessibilityService {
dialog = null;
}
});
builder.setPositiveButton(R.string.autofill_fill, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
bindDecryptAndVerify();
}
});
// builder.setPositiveButton(R.string.autofill_fill, new DialogInterface.OnClickListener() {
// @Override
// public void onClick(DialogInterface dialog, int which) {
// bindDecryptAndVerify();
// }
// });
builder.setNeutralButton("Settings", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) { //TODO make icon? gear?
@@ -254,13 +260,34 @@ public class AutofillService extends AccessibilityService {
startActivity(intent);
}
});
CharSequence itemNames[] = new CharSequence[items.size()];
for (int i = 0; i < items.size(); i++) {
itemNames[i] = items.get(i).getName().replace(".gpg", "");
}
builder.setItems(itemNames, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
if (which == items.size()) {
// the user will have to return to the app themselves.
Intent intent = new Intent(AutofillService.this, AutofillPreferenceActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
intent.putExtra("packageName", info.getPackageName());
intent.putExtra("appName", appName);
startActivity(intent);
} else {
lastWhichItem = which;
bindDecryptAndVerify();
}
}
});
dialog = builder.create();
dialog.setIcon(R.drawable.ic_launcher);
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.getWindow().setLayout(WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT);
dialog.setTitle(items.get(0).getName().replace(".gpg", ""));
// TODO size dialog
dialog.getWindow().setLayout(WindowManager.LayoutParams.WRAP_CONTENT
, WindowManager.LayoutParams.WRAP_CONTENT);
dialog.show();
}
@@ -304,7 +331,7 @@ public class AutofillService extends AccessibilityService {
}
InputStream is = null;
try {
is = FileUtils.openInputStream(items.get(0));
is = FileUtils.openInputStream(items.get(lastWhichItem));
} catch (IOException e) {
e.printStackTrace();
}

View File

@@ -1,57 +1,66 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="20dp"
android:paddingLeft="24dp"
android:paddingRight="24dp"
android:paddingTop="20dp">
<RadioGroup
android:id="@+id/autofill_radiogroup"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="20dp"
android:paddingLeft="24dp"
android:paddingRight="24dp"
android:paddingTop="20dp">
<RadioButton
android:id="@+id/use_default"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:checked="false"
android:text="@string/autofill_apps_default" />
<RadioButton
android:id="@+id/first"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:checked="false"
android:text="@string/autofill_apps_first" />
<RadioButton
android:id="@+id/match"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:checked="false"
android:text="@string/autofill_apps_match_ellipsis" />
<EditText
android:id="@+id/matched"
<RadioGroup
android:id="@+id/autofill_radiogroup"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:editable="false" />
android:layout_height="wrap_content">
<RadioButton
android:id="@+id/never"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:checked="false"
android:text="@string/autofill_apps_never" />
<RadioButton
android:id="@+id/use_default"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:checked="false"
android:text="@string/autofill_apps_default" />
</RadioGroup>
<RadioButton
android:id="@+id/first"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:checked="false"
android:text="@string/autofill_apps_first" />
</LinearLayout>
<RadioButton
android:id="@+id/match"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:checked="false"
android:text="@string/autofill_apps_match_ellipsis" />
<ListView
android:id="@+id/matched"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_weight="1"/>
<Button
style="?android:attr/buttonStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="+"
android:id="@+id/matchButton"
android:layout_gravity="center_horizontal"/>
<RadioButton
android:id="@+id/never"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:checked="false"
android:text="@string/autofill_apps_never"/>
</RadioGroup>
</LinearLayout>