From 8c884bcba8a39531dc5c16dab2caebf11760708c Mon Sep 17 00:00:00 2001 From: Matthew Wong Date: Wed, 30 Dec 2015 00:15:08 -0500 Subject: [PATCH] Add websites to autofill preferences --- .../pwdstore/autofill/AutofillFragment.java | 95 +++++++++++++++---- .../autofill/AutofillPreferenceActivity.java | 11 ++- .../autofill/AutofillRecyclerAdapter.java | 83 ++++++++++------ .../pwdstore/autofill/AutofillService.java | 21 ++-- app/src/main/res/layout/fragment_autofill.xml | 13 +++ app/src/main/res/values-cs/strings.xml | 2 +- app/src/main/res/values/strings.xml | 3 +- 7 files changed, 167 insertions(+), 61 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 4a5a37cd..1c4c2076 100644 --- a/app/src/main/java/com/zeapo/pwdstore/autofill/AutofillFragment.java +++ b/app/src/main/java/com/zeapo/pwdstore/autofill/AutofillFragment.java @@ -16,6 +16,7 @@ import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.ArrayAdapter; +import android.widget.EditText; import android.widget.ListView; import android.widget.RadioButton; import android.widget.RadioGroup; @@ -39,18 +40,28 @@ public class AutofillFragment extends DialogFragment { final AutofillPreferenceActivity callingActivity = (AutofillPreferenceActivity) getActivity(); LayoutInflater inflater = callingActivity.getLayoutInflater(); - // if... hide textview final View view = inflater.inflate(R.layout.fragment_autofill, null); builder.setView(view); - final String packageName = getArguments().getString("packageName"); - String appName = getArguments().getString("appName"); + String packageName = getArguments().getString("packageName", ""); + String appName = getArguments().getString("appName", ""); - builder.setTitle(appName); + final boolean isWebsite = appName.equals(packageName); + + // set the dialog icon and title or webName editText + String iconPackageName; + if (!isWebsite) { + iconPackageName = packageName; + builder.setTitle(appName); + view.findViewById(R.id.webName).setVisibility(View.GONE); + } else { + iconPackageName = "com.android.browser"; + builder.setTitle("Website"); + ((EditText) view.findViewById(R.id.webName)).setText(packageName); + } try { - // since we can't (easily?) pass the drawable as an argument - builder.setIcon(callingActivity.getPackageManager().getApplicationIcon(packageName)); + builder.setIcon(callingActivity.getPackageManager().getApplicationIcon(iconPackageName)); } catch (PackageManager.NameNotFoundException e) { e.printStackTrace(); } @@ -76,10 +87,15 @@ public class AutofillFragment extends DialogFragment { } }); - // if... autofill_web - SharedPreferences prefs - = getActivity().getApplicationContext().getSharedPreferences("autofill", Context.MODE_PRIVATE); - String preference = prefs.getString(packageName, ""); + // set the existing preference, if any + SharedPreferences prefs; + String preference; + if (!isWebsite) { + prefs = getActivity().getApplicationContext().getSharedPreferences("autofill", Context.MODE_PRIVATE); + } else { + prefs = getActivity().getApplicationContext().getSharedPreferences("autofill_web", Context.MODE_PRIVATE); + } + preference = prefs.getString(packageName, ""); switch (preference) { case "": ((RadioButton) view.findViewById(R.id.use_default)).toggle(); @@ -108,20 +124,43 @@ public class AutofillFragment extends DialogFragment { }; view.findViewById(R.id.matchButton).setOnClickListener(matchPassword); + // write to preferences when OK clicked final SharedPreferences.Editor editor = prefs.edit(); builder.setPositiveButton(R.string.dialog_ok, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { + String key; + String packageName = getArguments().getString("packageName", ""); + + if (!isWebsite) { + key = packageName; + } else { + key = ((EditText) view.findViewById(R.id.webName)).getText().toString(); + // if key.equals("") show error + + // if new packageName/appName/website name/website title/key + // is different than old, remove the old one. Basically, + // "edit" the old one. + if (!key.equals(packageName) && !packageName.equals("")) { + editor.remove(packageName); + if (callingActivity.recyclerAdapter != null) { + if (callingActivity.recyclerAdapter.getPosition(packageName) != -1) { + callingActivity.recyclerAdapter.removeWebsite(packageName); + } + } + } + } + RadioGroup radioGroup = (RadioGroup) view.findViewById(R.id.autofill_radiogroup); switch (radioGroup.getCheckedRadioButtonId()) { case R.id.use_default: - editor.remove(packageName); + editor.remove(key); break; case R.id.first: - editor.putString(packageName, "/first"); + editor.putString(key, "/first"); break; case R.id.never: - editor.putString(packageName, "/never"); + editor.putString(key, "/never"); break; default: StringBuilder paths = new StringBuilder(); @@ -131,14 +170,36 @@ public class AutofillFragment extends DialogFragment { paths.append("\n"); } } - editor.putString(packageName, paths.toString()); + editor.putString(key, paths.toString()); } editor.apply(); - // if recyclerAdapter has not loaded yet, there is no need to notifyItemChanged + // if recyclerAdapter has not loaded yet, there is no need to notify if (callingActivity.recyclerAdapter != null) { - int position = callingActivity.recyclerAdapter.getPosition(packageName); - callingActivity.recyclerAdapter.notifyItemChanged(position); + int position; + if (!isWebsite) { + String appName = getArguments().getString("appName", ""); + position = callingActivity.recyclerAdapter.getPosition(appName); + callingActivity.recyclerAdapter.notifyItemChanged(position); + } else { + String appName = ((EditText) view.findViewById(R.id.webName)).getText().toString(); + position = callingActivity.recyclerAdapter.getPosition(appName); + switch (radioGroup.getCheckedRadioButtonId()) { + // remove if existed, else do nothing + case R.id.use_default: + if (position != -1) { + callingActivity.recyclerAdapter.removeWebsite(appName); + } + break; + // change if existed, else add + default: + if (position != -1) { + callingActivity.recyclerAdapter.notifyItemChanged(position); + } else { + callingActivity.recyclerAdapter.addWebsite(appName); + } + } + } } } }); diff --git a/app/src/main/java/com/zeapo/pwdstore/autofill/AutofillPreferenceActivity.java b/app/src/main/java/com/zeapo/pwdstore/autofill/AutofillPreferenceActivity.java index 0c721012..7b8a3ba5 100644 --- a/app/src/main/java/com/zeapo/pwdstore/autofill/AutofillPreferenceActivity.java +++ b/app/src/main/java/com/zeapo/pwdstore/autofill/AutofillPreferenceActivity.java @@ -65,6 +65,7 @@ public class AutofillPreferenceActivity extends AppCompatActivity { fab.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { + showDialog("", ""); } }); } @@ -83,17 +84,17 @@ public class AutofillPreferenceActivity extends AppCompatActivity { List allApps = new ArrayList<>(); for (ResolveInfo app : allAppsResolveInfo) { - allApps.add(new AutofillRecyclerAdapter.AppInfo(app.loadLabel(pm).toString() - , app.activityInfo.packageName, app.loadIcon(pm))); + allApps.add(new AutofillRecyclerAdapter.AppInfo(app.activityInfo.packageName + , app.loadLabel(pm).toString(), app.loadIcon(pm))); } SharedPreferences prefs = getSharedPreferences("autofill_web", Context.MODE_PRIVATE); Map prefsMap = prefs.getAll(); for (String key : prefsMap.keySet()) { try { - allApps.add(new AutofillRecyclerAdapter.AppInfo(null, key, pm.getApplicationIcon("com.android.browser"))); + allApps.add(new AutofillRecyclerAdapter.AppInfo(key, key, pm.getApplicationIcon("com.android.browser"))); } catch (PackageManager.NameNotFoundException e) { - allApps.add(new AutofillRecyclerAdapter.AppInfo(null, key, null)); + allApps.add(new AutofillRecyclerAdapter.AppInfo(key, key, null)); } } @@ -108,7 +109,7 @@ public class AutofillPreferenceActivity extends AppCompatActivity { recyclerView.setAdapter(recyclerAdapter); Bundle extras = getIntent().getExtras(); if (extras != null) { - recyclerView.scrollToPosition(recyclerAdapter.getPosition(extras.getString("packageName"))); + recyclerView.scrollToPosition(recyclerAdapter.getPosition(extras.getString("appName"))); } } } 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 e00f1c5b..2a567254 100644 --- a/app/src/main/java/com/zeapo/pwdstore/autofill/AutofillRecyclerAdapter.java +++ b/app/src/main/java/com/zeapo/pwdstore/autofill/AutofillRecyclerAdapter.java @@ -21,7 +21,7 @@ import java.util.List; public class AutofillRecyclerAdapter extends RecyclerView.Adapter { private SortedList apps; - private ArrayList allApps; + private ArrayList allApps; // for filtering, maintain a list of all private PackageManager pm; private AutofillPreferenceActivity activity; @@ -31,6 +31,7 @@ public class AutofillRecyclerAdapter extends RecyclerView.Adapter allApps, final PackageManager pm , AutofillPreferenceActivity activity) { - SortedList.Callback callback = new SortedListAdapterCallback(this) { - @Override - public int compare(AppInfo o1, AppInfo o2) { - return o1.label.toLowerCase().compareTo(o2.label.toLowerCase()); - } + SortedList.Callback callback = new SortedListAdapterCallback(this) { + // don't take into account secondary text. This is good enough + // for the limited add/remove usage for websites + @Override + public int compare(AppInfo o1, AppInfo o2) { + return o1.appName.toLowerCase().compareTo(o2.appName.toLowerCase()); + } - @Override - public boolean areContentsTheSame(AppInfo oldItem, AppInfo newItem) { - return oldItem.label.equals(newItem.label); - } + @Override + public boolean areContentsTheSame(AppInfo oldItem, AppInfo newItem) { + return oldItem.appName.equals(newItem.appName); + } - @Override - public boolean areItemsTheSame(AppInfo item1, AppInfo item2) { - return item1.packageName.equals(item2.packageName); - } + @Override + public boolean areItemsTheSame(AppInfo item1, AppInfo item2) { + return item1.appName.equals(item2.appName); + } }; this.apps = new SortedList<>(AppInfo.class, callback); this.apps.addAll(allApps); @@ -96,15 +104,20 @@ public class AutofillRecyclerAdapter extends RecyclerView.Adapter 0) { holder.secondary.append(" and " + (preference.trim().split("\n").length - 1) + " more"); @@ -132,13 +146,24 @@ public class AutofillRecyclerAdapter extends RecyclerView.Adapter prefsMap = prefs.getAll(); for (String key : prefsMap.keySet()) { if (webViewTitle.toLowerCase().contains(key.toLowerCase())) { getPreferredPasswords(prefs.getString(key, "")); - return; + return key; } } // possible user-defined match not found, try default setting @@ -238,6 +236,7 @@ public class AutofillService extends AccessibilityService { } else { items.clear(); } + return webViewTitle; } // Put the newline separated list of passwords from the SharedPreferences @@ -295,11 +294,16 @@ public class AutofillService extends AccessibilityService { // 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()); + if (webViewTitle == null) { + intent.putExtra("packageName", info.getPackageName()); + } else { + intent.putExtra("packageName", appName); + } intent.putExtra("appName", appName); startActivity(intent); } }); + CharSequence itemNames[] = new CharSequence[items.size()]; for (int i = 0; i < items.size(); i++) { itemNames[i] = items.get(i).getName().replace(".gpg", ""); @@ -312,12 +316,13 @@ public class AutofillService extends AccessibilityService { bindDecryptAndVerify(); } }); + dialog = builder.create(); dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); dialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE); dialog.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND); // arbitrary non-annoying size - int height = 160; + int height = 144; if (items.size() > 1) { height += 48; } diff --git a/app/src/main/res/layout/fragment_autofill.xml b/app/src/main/res/layout/fragment_autofill.xml index 007147da..4ac1fc56 100644 --- a/app/src/main/res/layout/fragment_autofill.xml +++ b/app/src/main/res/layout/fragment_autofill.xml @@ -9,6 +9,19 @@ android:paddingRight="24dp" android:paddingTop="20dp"> + + + + + Vyplnit Použít výchozí nastavení Automaticky spárovat - Spárovat s… + Spárovat s Nikdy nepárovat \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 4047691f..188bf947 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -167,6 +167,7 @@ Fill Use default setting Automatically match - Match with… + Match with Never match + Name