Use File instead of PasswordItem for using file to fill
This commit is contained in:
parent
f2a4b944d8
commit
28eae33567
2 changed files with 62 additions and 65 deletions
|
@ -24,7 +24,6 @@ import android.view.accessibility.AccessibilityWindowInfo;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.zeapo.pwdstore.R;
|
import com.zeapo.pwdstore.R;
|
||||||
import com.zeapo.pwdstore.utils.PasswordItem;
|
|
||||||
import com.zeapo.pwdstore.utils.PasswordRepository;
|
import com.zeapo.pwdstore.utils.PasswordRepository;
|
||||||
|
|
||||||
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.io.FileUtils;
|
||||||
|
@ -38,14 +37,13 @@ import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.util.ArrayDeque;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
public class AutofillService extends AccessibilityService {
|
public class AutofillService extends AccessibilityService {
|
||||||
private OpenPgpServiceConnection serviceConnection;
|
private OpenPgpServiceConnection serviceConnection;
|
||||||
private SharedPreferences settings;
|
private SharedPreferences settings;
|
||||||
private AccessibilityNodeInfo info; // the original source of the event (the edittext field)
|
private AccessibilityNodeInfo info; // the original source of the event (the edittext field)
|
||||||
private ArrayList<PasswordItem> items; // password choices
|
private ArrayList<File> items; // password choices
|
||||||
private AlertDialog dialog;
|
private AlertDialog dialog;
|
||||||
private AccessibilityWindowInfo window;
|
private AccessibilityWindowInfo window;
|
||||||
private static Intent resultData = null; // need the intent which contains results from user interaction
|
private static Intent resultData = null; // need the intent which contains results from user interaction
|
||||||
|
@ -136,7 +134,7 @@ 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());
|
setMatchingPasswords(appName, info.getPackageName().toString());
|
||||||
if (items.isEmpty()) {
|
if (items.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -144,26 +142,22 @@ public class AutofillService extends AccessibilityService {
|
||||||
showDialog(appName);
|
showDialog(appName);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void searchWebView(AccessibilityNodeInfo source) {
|
private boolean searchWebView(AccessibilityNodeInfo source) {
|
||||||
ArrayDeque<AccessibilityNodeInfo> q = new ArrayDeque<>();
|
for (int i = 0; i < source.getChildCount(); i++) {
|
||||||
q.add(source);
|
AccessibilityNodeInfo u = source.getChild(i);
|
||||||
while (!q.isEmpty()) {
|
if (u == null) {
|
||||||
AccessibilityNodeInfo u = q.remove();
|
continue;
|
||||||
|
}
|
||||||
|
// this is not likely to always work
|
||||||
if (u.getContentDescription() != null && u.getContentDescription().equals("Web View")) {
|
if (u.getContentDescription() != null && u.getContentDescription().equals("Web View")) {
|
||||||
if (!u.equals(source)) {
|
return true;
|
||||||
u.recycle();
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
for (int i = 0; i < u.getChildCount(); i++) {
|
if (searchWebView(u)) {
|
||||||
if (u.getChild(i) != null) {
|
return true;
|
||||||
q.add(u.getChild(i));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!u.equals(source)) {
|
|
||||||
u.recycle();
|
|
||||||
}
|
}
|
||||||
|
u.recycle();
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// dismiss the dialog if the window has changed
|
// dismiss the dialog if the window has changed
|
||||||
|
@ -184,7 +178,7 @@ public class AutofillService extends AccessibilityService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void getMatchingPassword(String appName, String packageName) {
|
private void setMatchingPasswords(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);
|
||||||
|
@ -194,7 +188,7 @@ public class AutofillService extends AccessibilityService {
|
||||||
if (!PasswordRepository.isInitialized()) {
|
if (!PasswordRepository.isInitialized()) {
|
||||||
PasswordRepository.initialize(this);
|
PasswordRepository.initialize(this);
|
||||||
}
|
}
|
||||||
items = recursiveFilter(appName, null);
|
items = searchPasswords(PasswordRepository.getRepositoryDirectory(this), appName);
|
||||||
break;
|
break;
|
||||||
case "/never":
|
case "/never":
|
||||||
items.clear();
|
items.clear();
|
||||||
|
@ -204,57 +198,61 @@ public class AutofillService extends AccessibilityService {
|
||||||
PasswordRepository.initialize(this);
|
PasswordRepository.initialize(this);
|
||||||
}
|
}
|
||||||
String path = PasswordRepository.getWorkTree() + "/" + preference + ".gpg";
|
String path = PasswordRepository.getWorkTree() + "/" + preference + ".gpg";
|
||||||
File file = new File(path);
|
|
||||||
items = new ArrayList<>();
|
items = new ArrayList<>();
|
||||||
items.add(PasswordItem.newPassword(file.getName(), file, PasswordRepository.getRepositoryDirectory(this)));
|
items.add(new File(path));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private ArrayList<PasswordItem> recursiveFilter(String filter, File dir) {
|
private ArrayList<File> searchPasswords(File path, String appName) {
|
||||||
ArrayList<PasswordItem> items = new ArrayList<>();
|
ArrayList<File> passList
|
||||||
ArrayList<PasswordItem> passwordItems = dir == null ?
|
= PasswordRepository.getFilesList(path);
|
||||||
PasswordRepository.getPasswords(PasswordRepository.getRepositoryDirectory(this)) :
|
|
||||||
PasswordRepository.getPasswords(dir, PasswordRepository.getRepositoryDirectory(this));
|
if (passList.size() == 0) return new ArrayList<>();
|
||||||
for (PasswordItem item : passwordItems) {
|
|
||||||
if (item.getType() == PasswordItem.TYPE_CATEGORY) {
|
ArrayList<File> items = new ArrayList<>();
|
||||||
items.addAll(recursiveFilter(filter, item.getFile()));
|
|
||||||
}
|
for (File file : passList) {
|
||||||
if (item.toString().toLowerCase().contains(filter.toLowerCase())) {
|
if (file.isFile()) {
|
||||||
items.add(item);
|
if (file.toString().toLowerCase().contains(appName.toLowerCase())) {
|
||||||
|
items.add(file);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// ignore .git directory
|
||||||
|
if (file.getName().equals(".git"))
|
||||||
|
continue;
|
||||||
|
items.addAll(searchPasswords(file, appName));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showDialog(final String appName) {
|
private void showDialog(final String appName) {
|
||||||
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);
|
builder.setPositiveButton(R.string.autofill_fill, new DialogInterface.OnClickListener() {
|
||||||
builder.setPositiveButton(R.string.autofill_fill, new DialogInterface.OnClickListener() {
|
@Override
|
||||||
@Override
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
public void onClick(DialogInterface dialog, int which) {
|
bindDecryptAndVerify();
|
||||||
bindDecryptAndVerify();
|
}
|
||||||
}
|
});
|
||||||
});
|
builder.setNeutralButton("Settings", new DialogInterface.OnClickListener() {
|
||||||
builder.setNeutralButton("Settings", new DialogInterface.OnClickListener() {
|
@Override
|
||||||
@Override
|
public void onClick(DialogInterface dialog, int which) { //TODO make icon? gear?
|
||||||
public void onClick(DialogInterface dialog, int which) { //TODO make icon? gear?
|
// the user will have to return to the app themselves.
|
||||||
// the user will have to return to the app themselves.
|
Intent intent = new Intent(AutofillService.this, AutofillPreferenceActivity.class);
|
||||||
Intent intent = new Intent(AutofillService.this, AutofillPreferenceActivity.class);
|
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
|
||||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
|
intent.putExtra("packageName", info.getPackageName());
|
||||||
intent.putExtra("packageName", info.getPackageName());
|
intent.putExtra("appName", appName);
|
||||||
intent.putExtra("appName", appName);
|
startActivity(intent);
|
||||||
startActivity(intent);
|
}
|
||||||
}
|
});
|
||||||
});
|
dialog = builder.create();
|
||||||
dialog = builder.create();
|
dialog.setIcon(R.drawable.ic_launcher);
|
||||||
dialog.setIcon(R.drawable.ic_launcher);
|
dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
|
||||||
dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
|
dialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
|
||||||
dialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
|
dialog.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
|
||||||
dialog.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
|
dialog.getWindow().setLayout(WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT);
|
||||||
dialog.getWindow().setLayout(WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT);
|
dialog.setTitle(items.get(0).getName().replace(".gpg", ""));
|
||||||
}
|
|
||||||
dialog.setTitle(items.get(0).toString());
|
|
||||||
dialog.show();
|
dialog.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -298,7 +296,7 @@ public class AutofillService extends AccessibilityService {
|
||||||
}
|
}
|
||||||
InputStream is = null;
|
InputStream is = null;
|
||||||
try {
|
try {
|
||||||
is = FileUtils.openInputStream(items.get(0).getFile());
|
is = FileUtils.openInputStream(items.get(0));
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,5 +5,4 @@
|
||||||
android:accessibilityFeedbackType="feedbackGeneric"
|
android:accessibilityFeedbackType="feedbackGeneric"
|
||||||
android:notificationTimeout="100"
|
android:notificationTimeout="100"
|
||||||
android:canRetrieveWindowContent="true"
|
android:canRetrieveWindowContent="true"
|
||||||
android:canRequestEnhancedWebAccessibility="true"
|
|
||||||
/>
|
/>
|
Loading…
Reference in a new issue