aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Wong <wongma@protonmail.ch>2015-12-30 00:15:08 -0500
committerMatthew Wong <wongma@protonmail.ch>2015-12-30 00:15:08 -0500
commit8c884bcba8a39531dc5c16dab2caebf11760708c (patch)
tree9349cc280aea720aefb0ad558c90f08924dcbad6
parent5cb380bf471c6c7db1d165183296176d564c1ad3 (diff)
Add websites to autofill preferences
-rw-r--r--app/src/main/java/com/zeapo/pwdstore/autofill/AutofillFragment.java95
-rw-r--r--app/src/main/java/com/zeapo/pwdstore/autofill/AutofillPreferenceActivity.java11
-rw-r--r--app/src/main/java/com/zeapo/pwdstore/autofill/AutofillRecyclerAdapter.java87
-rw-r--r--app/src/main/java/com/zeapo/pwdstore/autofill/AutofillService.java21
-rw-r--r--app/src/main/res/layout/fragment_autofill.xml13
-rw-r--r--app/src/main/res/values-cs/strings.xml2
-rw-r--r--app/src/main/res/values/strings.xml3
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>