cleanup: split autofill service into functions
This commit is contained in:
parent
f783ad84ee
commit
54a05daa82
2 changed files with 55 additions and 40 deletions
|
@ -65,6 +65,7 @@ public class AutofillService extends AccessibilityService {
|
||||||
serviceConnection.bindToService();
|
serviceConnection.bindToService();
|
||||||
settings = PreferenceManager.getDefaultSharedPreferences(this);
|
settings = PreferenceManager.getDefaultSharedPreferences(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO change search/search results (just use first result)
|
// TODO change search/search results (just use first result)
|
||||||
@Override
|
@Override
|
||||||
public void onAccessibilityEvent(AccessibilityEvent event) {
|
public void onAccessibilityEvent(AccessibilityEvent event) {
|
||||||
|
@ -84,30 +85,17 @@ public class AutofillService extends AccessibilityService {
|
||||||
if (!event.isPassword()
|
if (!event.isPassword()
|
||||||
|| Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2
|
|| Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2
|
||||||
|| event.getPackageName().equals("org.sufficientlysecure.keychain")) {
|
|| event.getPackageName().equals("org.sufficientlysecure.keychain")) {
|
||||||
// the default keyboard showing/hiding is a window state changed event
|
dismissDialog(event);
|
||||||
// on Android 5+ we can use getWindows() to determine when the original window is not visible
|
|
||||||
// on Android 4.3 we have to use window state changed events and filter out the keyboard ones
|
|
||||||
// there may be other exceptions...
|
|
||||||
boolean dismiss;
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
|
||||||
dismiss = !getWindows().contains(window);
|
|
||||||
} else {
|
|
||||||
dismiss = !(event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
|
|
||||||
&& event.getPackageName().toString().contains("inputmethod"));
|
|
||||||
}
|
|
||||||
if (dismiss && dialog != null && dialog.isShowing()) {
|
|
||||||
dialog.dismiss();
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dialog != null && dialog.isShowing()) {
|
if (dialog != null && dialog.isShowing()) {
|
||||||
// if the view was clicked, the click event follows the focus event
|
// the current dialog must belong to this window; ignore clicks on this password field
|
||||||
// since the focus event was already handled, ignore click event
|
// why handle clicks at all then? some cases e.g. Paypal there is no initial focus event
|
||||||
if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_CLICKED) {
|
if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_CLICKED) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// if past this point, a new dialog will be created, so dismiss the existing
|
// if it was not a click, the field was refocused or another field was focused; recreate
|
||||||
dialog.dismiss();
|
dialog.dismiss();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,7 +107,7 @@ public class AutofillService extends AccessibilityService {
|
||||||
|
|
||||||
info = event.getSource();
|
info = event.getSource();
|
||||||
|
|
||||||
// save the dialog's corresponding window so we can use getWindows() above to check whether dismiss
|
// save the dialog's corresponding window so we can use getWindows() in dismissDialog
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||||
window = info.getWindow();
|
window = info.getWindow();
|
||||||
}
|
}
|
||||||
|
@ -134,10 +122,37 @@ public class AutofillService extends AccessibilityService {
|
||||||
}
|
}
|
||||||
final String appName = (applicationInfo != null ? packageManager.getApplicationLabel(applicationInfo) : "").toString();
|
final String appName = (applicationInfo != null ? packageManager.getApplicationLabel(applicationInfo) : "").toString();
|
||||||
|
|
||||||
|
getMatchingPassword(appName, info.getPackageName().toString());
|
||||||
|
if (items.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
showDialog(appName);
|
||||||
|
}
|
||||||
|
|
||||||
|
// dismiss the dialog if the window has changed
|
||||||
|
private void dismissDialog(AccessibilityEvent event) {
|
||||||
|
// the default keyboard showing/hiding is a window state changed event
|
||||||
|
// on Android 5+ we can use getWindows() to determine when the original window is not visible
|
||||||
|
// on Android 4.3 we have to use window state changed events and filter out the keyboard ones
|
||||||
|
// there may be other exceptions...
|
||||||
|
boolean dismiss;
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||||
|
dismiss = !getWindows().contains(window);
|
||||||
|
} else {
|
||||||
|
dismiss = !(event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
|
||||||
|
&& event.getPackageName().toString().contains("inputmethod"));
|
||||||
|
}
|
||||||
|
if (dismiss && dialog != null && dialog.isShowing()) {
|
||||||
|
dialog.dismiss();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void getMatchingPassword(String appName, String packageName) {
|
||||||
// if autofill_default is checked and prefs.getString DNE, 'Automatically match with password'/"first" otherwise "never"
|
// if autofill_default is checked and prefs.getString DNE, 'Automatically match with password'/"first" otherwise "never"
|
||||||
String defValue = settings.getBoolean("autofill_default", true) ? "/first" : "/never";
|
String defValue = settings.getBoolean("autofill_default", true) ? "/first" : "/never";
|
||||||
SharedPreferences prefs = getSharedPreferences("autofill", Context.MODE_PRIVATE);
|
SharedPreferences prefs = getSharedPreferences("autofill", Context.MODE_PRIVATE);
|
||||||
String preference = prefs.getString(event.getPackageName().toString(), defValue);
|
String preference = prefs.getString(packageName, defValue);
|
||||||
switch (preference) {
|
switch (preference) {
|
||||||
case "/first":
|
case "/first":
|
||||||
if (!PasswordRepository.isInitialized()) {
|
if (!PasswordRepository.isInitialized()) {
|
||||||
|
@ -146,6 +161,7 @@ public class AutofillService extends AccessibilityService {
|
||||||
items = recursiveFilter(appName, null);
|
items = recursiveFilter(appName, null);
|
||||||
break;
|
break;
|
||||||
case "/never":
|
case "/never":
|
||||||
|
items.clear();
|
||||||
return;
|
return;
|
||||||
default:
|
default:
|
||||||
if (!PasswordRepository.isInitialized()) {
|
if (!PasswordRepository.isInitialized()) {
|
||||||
|
@ -156,10 +172,25 @@ public class AutofillService extends AccessibilityService {
|
||||||
items = new ArrayList<>();
|
items = new ArrayList<>();
|
||||||
items.add(PasswordItem.newPassword(file.getName(), file, PasswordRepository.getRepositoryDirectory(this)));
|
items.add(PasswordItem.newPassword(file.getName(), file, PasswordRepository.getRepositoryDirectory(this)));
|
||||||
}
|
}
|
||||||
if (items.isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ArrayList<PasswordItem> recursiveFilter(String filter, File dir) {
|
||||||
|
ArrayList<PasswordItem> items = new ArrayList<>();
|
||||||
|
ArrayList<PasswordItem> passwordItems = dir == null ?
|
||||||
|
PasswordRepository.getPasswords(PasswordRepository.getRepositoryDirectory(this)) :
|
||||||
|
PasswordRepository.getPasswords(dir, PasswordRepository.getRepositoryDirectory(this));
|
||||||
|
for (PasswordItem item : passwordItems) {
|
||||||
|
if (item.getType() == PasswordItem.TYPE_CATEGORY) {
|
||||||
|
items.addAll(recursiveFilter(filter, item.getFile()));
|
||||||
|
}
|
||||||
|
if (item.toString().toLowerCase().contains(filter.toLowerCase())) {
|
||||||
|
items.add(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showDialog(final String appName) {
|
||||||
if (dialog == null) {
|
if (dialog == null) {
|
||||||
AlertDialog.Builder builder = new AlertDialog.Builder(this, R.style.Theme_AppCompat_Dialog);
|
AlertDialog.Builder builder = new AlertDialog.Builder(this, R.style.Theme_AppCompat_Dialog);
|
||||||
builder.setNegativeButton(R.string.dialog_cancel, null);
|
builder.setNegativeButton(R.string.dialog_cancel, null);
|
||||||
|
@ -191,22 +222,6 @@ public class AutofillService extends AccessibilityService {
|
||||||
dialog.show();
|
dialog.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
private ArrayList<PasswordItem> recursiveFilter(String filter, File dir) {
|
|
||||||
ArrayList<PasswordItem> items = new ArrayList<>();
|
|
||||||
ArrayList<PasswordItem> passwordItems = dir == null ?
|
|
||||||
PasswordRepository.getPasswords(PasswordRepository.getRepositoryDirectory(this)) :
|
|
||||||
PasswordRepository.getPasswords(dir, PasswordRepository.getRepositoryDirectory(this));
|
|
||||||
for (PasswordItem item : passwordItems) {
|
|
||||||
if (item.getType() == PasswordItem.TYPE_CATEGORY) {
|
|
||||||
items.addAll(recursiveFilter(filter, item.getFile()));
|
|
||||||
}
|
|
||||||
if (item.toString().toLowerCase().contains(filter.toLowerCase())) {
|
|
||||||
items.add(item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return items;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onInterrupt() {
|
public void onInterrupt() {
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
|
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:description="@string/autofill_description"
|
android:description="@string/autofill_description"
|
||||||
android:accessibilityEventTypes="typeViewFocused|typeViewClicked|typeWindowStateChanged"
|
android:accessibilityEventTypes="typeViewFocused|typeViewClicked|typeWindowStateChanged|typeWindowContentChanged"
|
||||||
android:accessibilityFlags="flagDefault|flagRetrieveInteractiveWindows|flagRequestEnhancedWebAccessibility"
|
android:accessibilityFlags="flagDefault|flagRetrieveInteractiveWindows"
|
||||||
android:accessibilityFeedbackType="feedbackGeneric"
|
android:accessibilityFeedbackType="feedbackGeneric"
|
||||||
android:notificationTimeout="100"
|
android:notificationTimeout="100"
|
||||||
android:canRetrieveWindowContent="true"
|
android:canRetrieveWindowContent="true"
|
||||||
|
|
Loading…
Reference in a new issue