From 8fa173e7d206c2ddff19890d96dbdb2edf6c9139 Mon Sep 17 00:00:00 2001 From: Matthew Wong Date: Sat, 7 Nov 2015 16:25:22 -0500 Subject: set and pick from multiple passwords per app --- .../zeapo/pwdstore/autofill/AutofillFragment.java | 51 ++++++++-- .../pwdstore/autofill/AutofillRecyclerAdapter.java | 2 +- .../zeapo/pwdstore/autofill/AutofillService.java | 51 +++++++--- app/src/main/res/layout/fragment_autofill.xml | 113 +++++++++++---------- 4 files changed, 142 insertions(+), 75 deletions(-) diff --git a/app/src/main/java/com/zeapo/pwdstore/autofill/AutofillFragment.java b/app/src/main/java/com/zeapo/pwdstore/autofill/AutofillFragment.java index 5d342f4a..e4986354 100644 --- a/app/src/main/java/com/zeapo/pwdstore/autofill/AutofillFragment.java +++ b/app/src/main/java/com/zeapo/pwdstore/autofill/AutofillFragment.java @@ -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 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(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")); } } } diff --git a/app/src/main/java/com/zeapo/pwdstore/autofill/AutofillRecyclerAdapter.java b/app/src/main/java/com/zeapo/pwdstore/autofill/AutofillRecyclerAdapter.java index 15f114c6..54be40dc 100644 --- a/app/src/main/java/com/zeapo/pwdstore/autofill/AutofillRecyclerAdapter.java +++ b/app/src/main/java/com/zeapo/pwdstore/autofill/AutofillRecyclerAdapter.java @@ -110,7 +110,7 @@ public class AutofillRecyclerAdapter extends RecyclerView.Adapter 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(); } diff --git a/app/src/main/res/layout/fragment_autofill.xml b/app/src/main/res/layout/fragment_autofill.xml index 7bdf3d84..007147da 100644 --- a/app/src/main/res/layout/fragment_autofill.xml +++ b/app/src/main/res/layout/fragment_autofill.xml @@ -1,57 +1,66 @@ - - - - - - - - - - - + + + android:layout_height="wrap_content"> + + + + + + + + + +