aboutsummaryrefslogtreecommitdiff
path: root/app/src/main/java/com/zeapo
diff options
context:
space:
mode:
authorMatthew Wong <wongma@protonmail.ch>2015-12-31 03:47:51 -0500
committerMatthew Wong <wongma@protonmail.ch>2015-12-31 03:47:51 -0500
commit1c3a4fe763e6722d7398afe518f22c66254c356e (patch)
tree949c3f4626e41eb45167b32a0aa36ddd07eababf /app/src/main/java/com/zeapo
parentcdf27fc24da18fc7e60b4db5b1b24bcab2b38e4f (diff)
Use URL as package name for app/website settings and match Chrome using URL. But use site title for automatching attempts when URL match not found
Diffstat (limited to 'app/src/main/java/com/zeapo')
-rw-r--r--app/src/main/java/com/zeapo/pwdstore/autofill/AutofillFragment.java184
-rw-r--r--app/src/main/java/com/zeapo/pwdstore/autofill/AutofillPreferenceActivity.java15
-rw-r--r--app/src/main/java/com/zeapo/pwdstore/autofill/AutofillRecyclerAdapter.java41
-rw-r--r--app/src/main/java/com/zeapo/pwdstore/autofill/AutofillService.java33
4 files changed, 155 insertions, 118 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 1c4c2076..dfe4f3c0 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.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.RadioButton;
@@ -27,7 +28,8 @@ import com.zeapo.pwdstore.R;
public class AutofillFragment extends DialogFragment {
private static final int MATCH_WITH = 777;
- ArrayAdapter<String> adapter;
+ private ArrayAdapter<String> adapter;
+ private boolean isWeb;
public AutofillFragment() {
}
@@ -37,28 +39,27 @@ public class AutofillFragment extends DialogFragment {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
// this fragment is only created from the settings page (AutofillPreferenceActivity)
// need to interact with the recyclerAdapter which is a member of activity
- final AutofillPreferenceActivity callingActivity = (AutofillPreferenceActivity) getActivity();
+ AutofillPreferenceActivity callingActivity = (AutofillPreferenceActivity) getActivity();
LayoutInflater inflater = callingActivity.getLayoutInflater();
final View view = inflater.inflate(R.layout.fragment_autofill, null);
builder.setView(view);
- String packageName = getArguments().getString("packageName", "");
- String appName = getArguments().getString("appName", "");
-
- final boolean isWebsite = appName.equals(packageName);
+ String packageName = getArguments().getString("packageName");
+ String appName = getArguments().getString("appName");
+ isWeb = getArguments().getBoolean("isWeb");
// set the dialog icon and title or webName editText
String iconPackageName;
- if (!isWebsite) {
+ if (!isWeb) {
iconPackageName = packageName;
builder.setTitle(appName);
- view.findViewById(R.id.webName).setVisibility(View.GONE);
+ view.findViewById(R.id.webURL).setVisibility(View.GONE);
} else {
iconPackageName = "com.android.browser";
builder.setTitle("Website");
- ((EditText) view.findViewById(R.id.webName)).setText(packageName);
+ ((EditText) view.findViewById(R.id.webURL)).setText(packageName);
}
try {
builder.setIcon(callingActivity.getPackageManager().getApplicationIcon(iconPackageName));
@@ -89,13 +90,12 @@ public class AutofillFragment extends DialogFragment {
// set the existing preference, if any
SharedPreferences prefs;
- String preference;
- if (!isWebsite) {
+ if (!isWeb) {
prefs = getActivity().getApplicationContext().getSharedPreferences("autofill", Context.MODE_PRIVATE);
} else {
prefs = getActivity().getApplicationContext().getSharedPreferences("autofill_web", Context.MODE_PRIVATE);
}
- preference = prefs.getString(packageName, "");
+ String preference = prefs.getString(packageName, "");
switch (preference) {
case "":
((RadioButton) view.findViewById(R.id.use_default)).toggle();
@@ -125,86 +125,106 @@ 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);
- }
- }
+
+ }
+ });
+ builder.setNegativeButton(R.string.dialog_cancel, null);
+ return builder.create();
+ }
+
+ // need to the onClick here for buttons to dismiss dialog only when wanted
+ @Override
+ public void onStart() {
+ super.onStart();
+ AlertDialog ad = (AlertDialog) getDialog();
+ if(ad != null) {
+ Button positiveButton = ad.getButton(Dialog.BUTTON_POSITIVE);
+ positiveButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ AutofillPreferenceActivity callingActivity = (AutofillPreferenceActivity) getActivity();
+ Dialog dialog = getDialog();
+
+ SharedPreferences prefs;
+ if (!isWeb) {
+ prefs = getActivity().getApplicationContext().getSharedPreferences("autofill", Context.MODE_PRIVATE);
+ } else {
+ prefs = getActivity().getApplicationContext().getSharedPreferences("autofill_web", Context.MODE_PRIVATE);
}
- }
+ SharedPreferences.Editor editor = prefs.edit();
- RadioGroup radioGroup = (RadioGroup) view.findViewById(R.id.autofill_radiogroup);
- switch (radioGroup.getCheckedRadioButtonId()) {
- case R.id.use_default:
- editor.remove(key);
- break;
- case R.id.first:
- editor.putString(key, "/first");
- break;
- case R.id.never:
- editor.putString(key, "/never");
- break;
- default:
- StringBuilder paths = new StringBuilder();
- for (int i = 0; i < adapter.getCount(); i++) {
- paths.append(adapter.getItem(i));
- if (i != adapter.getCount()) {
- paths.append("\n");
- }
+ String packageName = getArguments().getString("packageName", "");
+ if (isWeb) {
+ packageName = ((EditText) dialog.findViewById(R.id.webURL)).getText().toString();
+
+ // handle some errors
+ EditText webURL = (EditText) dialog.findViewById(R.id.webURL);
+ if (packageName.equals("")) {
+ webURL.setError("URL cannot be blank");
+ return;
}
- editor.putString(key, paths.toString());
- }
- editor.apply();
-
- // if recyclerAdapter has not loaded yet, there is no need to notify
- if (callingActivity.recyclerAdapter != null) {
- 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);
+ String oldPackageName = getArguments().getString("packageName", "");
+ int position = callingActivity.recyclerAdapter.getPosition(packageName);
+ if (!oldPackageName.equals(packageName) && position != -1) {
+ webURL.setError("URL already exists");
+ return;
+ }
+ }
+ RadioGroup radioGroup = (RadioGroup) dialog.findViewById(R.id.autofill_radiogroup);
+ switch (radioGroup.getCheckedRadioButtonId()) {
+ case R.id.use_default:
+ if (!isWeb) {
+ editor.remove(packageName);
+ } else {
+ editor.putString(packageName, "");
+ }
+ break;
+ case R.id.first:
+ editor.putString(packageName, "/first");
+ break;
+ case R.id.never:
+ editor.putString(packageName, "/never");
+ break;
+ default:
+ 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();
+
+ // if recyclerAdapter has not loaded yet, there is no need to notify
+ if (callingActivity.recyclerAdapter != null) {
+ int position;
+ if (!isWeb) {
+ String appName = getArguments().getString("appName", "");
+ position = callingActivity.recyclerAdapter.getPosition(appName);
+ callingActivity.recyclerAdapter.notifyItemChanged(position);
+ } else {
+ position = callingActivity.recyclerAdapter.getPosition(packageName);
+ String oldPackageName = getArguments().getString("packageName", "");
+ if (oldPackageName.equals(packageName)) {
+ callingActivity.recyclerAdapter.notifyItemChanged(position);
+ } else if (oldPackageName.equals("")){
+ callingActivity.recyclerAdapter.addWebsite(packageName);
+ } else {
+ editor.remove(oldPackageName);
+ callingActivity.recyclerAdapter.updateWebsite(oldPackageName, packageName);
+ }
}
}
+
+ dismiss();
}
- }
- });
- builder.setNegativeButton(R.string.dialog_cancel, null);
- return builder.create();
+ });
+ }
}
@Override
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 7b8a3ba5..81d0ddde 100644
--- a/app/src/main/java/com/zeapo/pwdstore/autofill/AutofillPreferenceActivity.java
+++ b/app/src/main/java/com/zeapo/pwdstore/autofill/AutofillPreferenceActivity.java
@@ -28,7 +28,7 @@ import java.util.Map;
public class AutofillPreferenceActivity extends AppCompatActivity {
- private RecyclerView recyclerView;
+ RecyclerView recyclerView;
AutofillRecyclerAdapter recyclerAdapter; // let fragment have access
private RecyclerView.LayoutManager layoutManager;
@@ -56,7 +56,7 @@ public class AutofillPreferenceActivity extends AppCompatActivity {
if (extras != null) {
recreate = true;
- showDialog(extras.getString("packageName"), extras.getString("appName"));
+ showDialog(extras.getString("packageName"), extras.getString("appName"), extras.getBoolean("isWeb"));
}
setTitle("Autofill Apps");
@@ -65,7 +65,7 @@ public class AutofillPreferenceActivity extends AppCompatActivity {
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
- showDialog("", "");
+ showDialog("", "", true);
}
});
}
@@ -85,16 +85,16 @@ public class AutofillPreferenceActivity extends AppCompatActivity {
for (ResolveInfo app : allAppsResolveInfo) {
allApps.add(new AutofillRecyclerAdapter.AppInfo(app.activityInfo.packageName
- , app.loadLabel(pm).toString(), app.loadIcon(pm)));
+ , app.loadLabel(pm).toString(), false, 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(key, key, pm.getApplicationIcon("com.android.browser")));
+ allApps.add(new AutofillRecyclerAdapter.AppInfo(key, key, true, pm.getApplicationIcon("com.android.browser")));
} catch (PackageManager.NameNotFoundException e) {
- allApps.add(new AutofillRecyclerAdapter.AppInfo(key, key, null));
+ allApps.add(new AutofillRecyclerAdapter.AppInfo(key, key, true, null));
}
}
@@ -158,11 +158,12 @@ public class AutofillPreferenceActivity extends AppCompatActivity {
return super.onOptionsItemSelected(item);
}
- public void showDialog(String packageName, String appName) {
+ public void showDialog(String packageName, String appName, boolean isWeb) {
DialogFragment df = new AutofillFragment();
Bundle args = new Bundle();
args.putString("packageName", packageName);
args.putString("appName", appName);
+ args.putBoolean("isWeb", isWeb);
df.setArguments(args);
df.show(getFragmentManager(), "autofill_dialog");
}
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 2a567254..901ff903 100644
--- a/app/src/main/java/com/zeapo/pwdstore/autofill/AutofillRecyclerAdapter.java
+++ b/app/src/main/java/com/zeapo/pwdstore/autofill/AutofillRecyclerAdapter.java
@@ -24,6 +24,7 @@ public class AutofillRecyclerAdapter extends RecyclerView.Adapter<AutofillRecycl
private ArrayList<AppInfo> allApps; // for filtering, maintain a list of all
private PackageManager pm;
private AutofillPreferenceActivity activity;
+ Drawable browserIcon = null;
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public View view;
@@ -32,6 +33,7 @@ public class AutofillRecyclerAdapter extends RecyclerView.Adapter<AutofillRecycl
public ImageView icon;
public String packageName;
public String appName;
+ public Boolean isWeb;
public ViewHolder(View view) {
super(view);
@@ -44,7 +46,7 @@ public class AutofillRecyclerAdapter extends RecyclerView.Adapter<AutofillRecycl
@Override
public void onClick(View v) {
- activity.showDialog(packageName, appName);
+ activity.showDialog(packageName, appName, isWeb);
}
}
@@ -52,11 +54,13 @@ public class AutofillRecyclerAdapter extends RecyclerView.Adapter<AutofillRecycl
public static class AppInfo {
public String packageName;
public String appName;
+ public boolean isWeb;
public Drawable icon;
- public AppInfo(String packageName, String appName, Drawable icon) {
+ public AppInfo(String packageName, String appName, boolean isWeb, Drawable icon) {
this.packageName = packageName;
this.appName = appName;
+ this.isWeb = isWeb;
this.icon = icon;
}
@@ -91,6 +95,11 @@ public class AutofillRecyclerAdapter extends RecyclerView.Adapter<AutofillRecycl
this.allApps = new ArrayList<>(allApps);
this.pm = pm;
this.activity = activity;
+ try {
+ browserIcon = activity.getPackageManager().getApplicationIcon("com.android.browser");
+ } catch (PackageManager.NameNotFoundException e) {
+ e.printStackTrace();
+ }
}
@Override
@@ -105,6 +114,7 @@ public class AutofillRecyclerAdapter extends RecyclerView.Adapter<AutofillRecycl
AppInfo app = apps.get(position);
holder.packageName = app.packageName;
holder.appName = app.appName;
+ holder.isWeb = app.isWeb;
holder.icon.setImageDrawable(app.icon);
holder.name.setText(app.appName);
@@ -147,23 +157,24 @@ public class AutofillRecyclerAdapter extends RecyclerView.Adapter<AutofillRecycl
}
public int getPosition(String appName) {
- return apps.indexOf(new AppInfo(null, appName, null));
+ return apps.indexOf(new AppInfo(null, appName, false, null));
}
- public void addWebsite(String appName) {
- Drawable icon = null;
- try {
- icon = activity.getPackageManager().getApplicationIcon("com.android.browser");
- } catch (PackageManager.NameNotFoundException e) {
- e.printStackTrace();
- }
- apps.add(new AppInfo(appName, appName, icon));
- allApps.add(new AppInfo(appName, appName, icon));
+ // for websites, URL = packageName == appName
+ public void addWebsite(String packageName) {
+ apps.add(new AppInfo(packageName, packageName, true, browserIcon));
+ allApps.add(new AppInfo(packageName, packageName, true, browserIcon));
+ }
+
+ public void removeWebsite(String packageName) {
+ apps.remove(new AppInfo(null, packageName, false, null));
+ allApps.remove(new AppInfo(null, packageName, false, null)); // compare with equals
}
- public void removeWebsite(String appName) {
- apps.remove(new AppInfo(null, appName, null));
- allApps.remove(new AppInfo(null, appName, null)); // compare with equals
+ public void updateWebsite(String oldPackageName, String packageName) {
+ apps.updateItemAt(getPosition(oldPackageName), new AppInfo (packageName, packageName, true, browserIcon));
+ allApps.remove(new AppInfo(null, oldPackageName, false, null)); // compare with equals
+ allApps.add(new AppInfo(null, packageName, false, null));
}
public void filter(String s) {
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 1025028a..e55d2b7f 100644
--- a/app/src/main/java/com/zeapo/pwdstore/autofill/AutofillService.java
+++ b/app/src/main/java/com/zeapo/pwdstore/autofill/AutofillService.java
@@ -156,8 +156,11 @@ public class AutofillService extends AccessibilityService {
window = info.getWindow();
}
+ String packageName;
String appName;
if (webViewTitle == null) {
+ packageName = info.getPackageName().toString();
+
// get the app name and find a corresponding password
PackageManager packageManager = getPackageManager();
ApplicationInfo applicationInfo;
@@ -169,9 +172,10 @@ public class AutofillService extends AccessibilityService {
appName = (applicationInfo != null ? packageManager.getApplicationLabel(applicationInfo) : "").toString();
setMatchingPasswords(appName, info.getPackageName().toString());
-
} else {
- appName = setMatchingPasswordsWeb(webViewTitle);
+ packageName = setMatchingPasswordsWeb(webViewTitle, webViewURL);
+
+ appName = packageName;
}
// if autofill_always checked, show dialog even if no matches (automatic
@@ -179,7 +183,7 @@ public class AutofillService extends AccessibilityService {
if (items.isEmpty() && !settings.getBoolean("autofill_always", false)) {
return;
}
- showDialog(appName);
+ showDialog(packageName, appName);
}
private String searchWebView(AccessibilityNodeInfo source) {
@@ -244,17 +248,19 @@ public class AutofillService extends AccessibilityService {
}
}
- // return key for opening its Settings. Otherwise just use the title
- private String setMatchingPasswordsWeb(String webViewTitle) {
+ // Return the the matched preference's key, which isn't necessarily equal to
+ // the URL, if a preference is matched so it can be accessed with Settings.
+ private String setMatchingPasswordsWeb(String webViewTitle, String webViewURL) {
SharedPreferences prefs = getSharedPreferences("autofill_web", Context.MODE_PRIVATE);
Map<String, ?> prefsMap = prefs.getAll();
for (String key : prefsMap.keySet()) {
- if (webViewTitle.toLowerCase().contains(key.toLowerCase())) {
+ if (webViewURL.toLowerCase().contains(key.toLowerCase())) {
getPreferredPasswords(prefs.getString(key, ""));
return key;
}
}
- // possible user-defined match not found, try default setting
+
+ // no user-defined match found, maybe auto match using title, not URL
if (settings.getBoolean("autofill_default", true)) {
if (!PasswordRepository.isInitialized()) {
PasswordRepository.initialize(this);
@@ -263,7 +269,7 @@ public class AutofillService extends AccessibilityService {
} else {
items = new ArrayList<>();
}
- return webViewTitle;
+ return webViewURL;
}
// Put the newline separated list of passwords from the SharedPreferences
@@ -305,7 +311,7 @@ public class AutofillService extends AccessibilityService {
return items;
}
- private void showDialog(final String appName) {
+ private void showDialog(final String packageName, final String appName) {
AlertDialog.Builder builder = new AlertDialog.Builder(this, R.style.Theme_AppCompat_Dialog);
builder.setNegativeButton(R.string.dialog_cancel, new DialogInterface.OnClickListener() {
@Override
@@ -320,12 +326,11 @@ 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);
- if (webViewTitle == null) {
- intent.putExtra("packageName", info.getPackageName());
- } else {
- intent.putExtra("packageName", appName);
- }
+ intent.putExtra("packageName", packageName);
intent.putExtra("appName", appName);
+ if (webViewTitle != null) {
+ intent.putExtra("isWeb", true);
+ }
startActivity(intent);
}
});