Use File instead of PasswordItem for using file to fill

This commit is contained in:
Matthew Wong 2015-11-05 23:44:46 -05:00 committed by Matthew Wong
parent f2a4b944d8
commit 28eae33567
2 changed files with 62 additions and 65 deletions

View file

@ -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();
} }

View file

@ -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"
/> />