diff options
author | Matthew Wong <wongma@protonmail.ch> | 2015-12-30 00:15:08 -0500 |
---|---|---|
committer | Matthew Wong <wongma@protonmail.ch> | 2015-12-30 00:15:08 -0500 |
commit | 8c884bcba8a39531dc5c16dab2caebf11760708c (patch) | |
tree | 9349cc280aea720aefb0ad558c90f08924dcbad6 | |
parent | 5cb380bf471c6c7db1d165183296176d564c1ad3 (diff) |
Add websites to autofill preferences
7 files changed, 169 insertions, 63 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<AutofillRecyclerAdapter.AppInfo> 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<String, ?> 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<AutofillRecyclerAdapter.ViewHolder> { private SortedList<AppInfo> apps; - private ArrayList<AppInfo> allApps; + private ArrayList<AppInfo> allApps; // for filtering, maintain a list of all private PackageManager pm; private AutofillPreferenceActivity activity; @@ -31,6 +31,7 @@ public class AutofillRecyclerAdapter extends RecyclerView.Adapter<AutofillRecycl public TextView secondary; public ImageView icon; public String packageName; + public String appName; public ViewHolder(View view) { super(view); @@ -43,40 +44,47 @@ public class AutofillRecyclerAdapter extends RecyclerView.Adapter<AutofillRecycl @Override public void onClick(View v) { - activity.showDialog(packageName, name.getText().toString()); + activity.showDialog(packageName, appName); } } public static class AppInfo { - public String label; public String packageName; + public String appName; public Drawable icon; - public AppInfo(String label, String packageName, Drawable icon) { - this.label = label; + public AppInfo(String packageName, String appName, Drawable icon) { this.packageName = packageName; + this.appName = appName; this.icon = icon; } + + @Override + public boolean equals(Object o) { + return o != null && o instanceof AppInfo && this.appName.equals(((AppInfo) o).appName); + } } public AutofillRecyclerAdapter(List<AppInfo> allApps, final PackageManager pm , AutofillPreferenceActivity activity) { - SortedList.Callback<AppInfo> callback = new SortedListAdapterCallback<AppInfo>(this) { - @Override - public int compare(AppInfo o1, AppInfo o2) { - return o1.label.toLowerCase().compareTo(o2.label.toLowerCase()); - } - - @Override - public boolean areContentsTheSame(AppInfo oldItem, AppInfo newItem) { - return oldItem.label.equals(newItem.label); - } - - @Override - public boolean areItemsTheSame(AppInfo item1, AppInfo item2) { - return item1.packageName.equals(item2.packageName); - } + SortedList.Callback<AppInfo> callback = new SortedListAdapterCallback<AppInfo>(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.appName.equals(newItem.appName); + } + + @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<AutofillRecycl public void onBindViewHolder(AutofillRecyclerAdapter.ViewHolder holder, int position) { AppInfo app = apps.get(position); holder.packageName = app.packageName; + holder.appName = app.appName; holder.icon.setImageDrawable(app.icon); - holder.name.setText(app.label); + holder.name.setText(app.appName); holder.secondary.setVisibility(View.VISIBLE); holder.view.setBackgroundResource(R.color.grey_white_1000); - SharedPreferences prefs - = activity.getApplicationContext().getSharedPreferences("autofill", Context.MODE_PRIVATE); + SharedPreferences prefs; + if (!app.appName.equals(app.packageName)) { + prefs = activity.getApplicationContext().getSharedPreferences("autofill", Context.MODE_PRIVATE); + } else { + prefs = activity.getApplicationContext().getSharedPreferences("autofill_web", Context.MODE_PRIVATE); + } String preference = prefs.getString(holder.packageName, ""); switch (preference) { case "": @@ -118,7 +131,8 @@ public class AutofillRecyclerAdapter extends RecyclerView.Adapter<AutofillRecycl holder.secondary.setText(R.string.autofill_apps_never); break; default: - holder.secondary.setText("Match with " + preference.split("\n")[0]); + holder.secondary.setText(R.string.autofill_apps_match); + holder.secondary.append(" " + preference.split("\n")[0]); if ((preference.trim().split("\n").length - 1) > 0) { holder.secondary.append(" and " + (preference.trim().split("\n").length - 1) + " more"); @@ -132,13 +146,24 @@ public class AutofillRecyclerAdapter extends RecyclerView.Adapter<AutofillRecycl return apps.size(); } - public int getPosition(String packageName) { - for (int i = 0; i < apps.size(); i++) { - if (apps.get(i).packageName.equals(packageName)) { - return i; - } + public int getPosition(String appName) { + return apps.indexOf(new AppInfo(null, appName, null)); + } + + public void addWebsite(String appName) { + Drawable icon = null; + try { + icon = activity.getPackageManager().getApplicationIcon("com.android.browser"); + } catch (PackageManager.NameNotFoundException e) { + e.printStackTrace(); } - return -1; + apps.add(new AppInfo(appName, appName, icon)); + allApps.add(new AppInfo(appName, appName, icon)); + } + + public void removeWebsite(String appName) { + apps.remove(new AppInfo(null, appName, null)); + allApps.remove(new AppInfo(null, appName, null)); // compare with equals } public void filter(String s) { @@ -148,7 +173,7 @@ public class AutofillRecyclerAdapter extends RecyclerView.Adapter<AutofillRecycl } apps.beginBatchedUpdates(); for (AppInfo app : allApps) { - if (app.label.toLowerCase().contains(s.toLowerCase())) { + if (app.appName.toLowerCase().contains(s.toLowerCase())) { apps.add(app); } else { apps.remove(app); diff --git a/app/src/main/java/com/zeapo/pwdstore/autofill/AutofillService.java b/app/src/main/java/com/zeapo/pwdstore/autofill/AutofillService.java index 58fe6609..88580e59 100644 --- a/app/src/main/java/com/zeapo/pwdstore/autofill/AutofillService.java +++ b/app/src/main/java/com/zeapo/pwdstore/autofill/AutofillService.java @@ -146,16 +146,13 @@ public class AutofillService extends AccessibilityService { setMatchingPasswords(appName, info.getPackageName().toString()); } else { - appName = webViewTitle; - - setMatchingPasswordsWeb(webViewTitle); + appName = setMatchingPasswordsWeb(webViewTitle); } if (items.isEmpty()) { // show anyway preference? return; } showDialog(appName); - } private String searchWebView(AccessibilityNodeInfo source) { @@ -220,13 +217,14 @@ public class AutofillService extends AccessibilityService { } } - private void setMatchingPasswordsWeb(String webViewTitle) { + // return key for opening its Settings. Otherwise just use the title + private String setMatchingPasswordsWeb(String webViewTitle) { SharedPreferences prefs = getSharedPreferences("autofill_web", Context.MODE_PRIVATE); Map<String, ?> 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"> + <android.support.design.widget.TextInputLayout xmlns:app="http://schemas.android.com/apk/res-auto" + android:layout_width="match_parent" + android:layout_height="wrap_content" + app:hintTextAppearance="@style/TextAppearance.AppCompat"> + + <EditText + android:id="@+id/webName" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:hint="@string/autofill_webname_hint" + android:inputType="textPersonName"/> + </android.support.design.widget.TextInputLayout> + <RadioGroup android:id="@+id/autofill_radiogroup" android:layout_width="match_parent" diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index 926e051e..baaec873 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -167,6 +167,6 @@ <string name="autofill_fill">Vyplnit</string> <string name="autofill_apps_default">Použít výchozí nastavení</string> <string name="autofill_apps_first">Automaticky spárovat</string> - <string name="autofill_apps_match_ellipsis">Spárovat s…</string> + <string name="autofill_apps_match_ellipsis">Spárovat s</string> <string name="autofill_apps_never">Nikdy nepárovat</string> </resources>
\ 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 @@ <string name="autofill_fill">Fill</string> <string name="autofill_apps_default">Use default setting</string> <string name="autofill_apps_first">Automatically match</string> - <string name="autofill_apps_match_ellipsis">Match with…</string> + <string name="autofill_apps_match">Match with</string> <string name="autofill_apps_never">Never match</string> + <string name="autofill_webname_hint">Name</string> </resources> |