Support Android app targets in autofill service
This commit is contained in:
@@ -21,6 +21,7 @@ import java.util.List;
|
|||||||
|
|
||||||
public final class KeePassGOAutofillService extends AutofillService {
|
public final class KeePassGOAutofillService extends AutofillService {
|
||||||
private static final String TAG = "KeePassGOAutofill";
|
private static final String TAG = "KeePassGOAutofill";
|
||||||
|
private static final String APP_SCHEME = "androidapp://";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onConnected() {
|
public void onConnected() {
|
||||||
@@ -51,15 +52,21 @@ public final class KeePassGOAutofillService extends AutofillService {
|
|||||||
|
|
||||||
AssistStructure structure = contexts.get(contexts.size() - 1).getStructure();
|
AssistStructure structure = contexts.get(contexts.size() - 1).getStructure();
|
||||||
ParsedFields fields = new ParsedFields();
|
ParsedFields fields = new ParsedFields();
|
||||||
String webDomain = parseWindow(structure, fields);
|
ParsedTarget target = parseWindow(structure, fields);
|
||||||
Log.i(TAG, "parsed domain=" + webDomain + " usernameId=" + fields.usernameId + " passwordId=" + fields.passwordId);
|
Log.i(
|
||||||
|
TAG,
|
||||||
|
"parsed target=" + target.matchTarget
|
||||||
|
+ " package=" + target.packageName
|
||||||
|
+ " usernameId=" + fields.usernameId
|
||||||
|
+ " passwordId=" + fields.passwordId
|
||||||
|
);
|
||||||
if (fields.passwordId == null) {
|
if (fields.passwordId == null) {
|
||||||
Log.i(TAG, "no password field found");
|
Log.i(TAG, "no password field found");
|
||||||
callback.onSuccess(null);
|
callback.onSuccess(null);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
AutofillCacheStore.Entry entry = AutofillCacheStore.findBestMatch(this, webDomain);
|
AutofillCacheStore.Entry entry = AutofillCacheStore.findBestMatch(this, target.matchTarget);
|
||||||
if (entry == null) {
|
if (entry == null) {
|
||||||
Log.i(TAG, "no autofill cache match");
|
Log.i(TAG, "no autofill cache match");
|
||||||
callback.onSuccess(null);
|
callback.onSuccess(null);
|
||||||
@@ -96,7 +103,7 @@ public final class KeePassGOAutofillService extends AutofillService {
|
|||||||
callback.onSuccess();
|
callback.onSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String parseWindow(AssistStructure structure, ParsedFields fields) {
|
private static ParsedTarget parseWindow(AssistStructure structure, ParsedFields fields) {
|
||||||
String domain = "";
|
String domain = "";
|
||||||
final int windowCount = structure.getWindowNodeCount();
|
final int windowCount = structure.getWindowNodeCount();
|
||||||
for (int i = 0; i < windowCount; i++) {
|
for (int i = 0; i < windowCount; i++) {
|
||||||
@@ -106,7 +113,17 @@ public final class KeePassGOAutofillService extends AutofillService {
|
|||||||
domain = next;
|
domain = next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return domain;
|
String packageName = "";
|
||||||
|
if (structure.getActivityComponent() != null) {
|
||||||
|
packageName = structure.getActivityComponent().getPackageName();
|
||||||
|
}
|
||||||
|
if (!domain.isEmpty()) {
|
||||||
|
return new ParsedTarget(domain, packageName);
|
||||||
|
}
|
||||||
|
if (packageName != null && !packageName.isEmpty()) {
|
||||||
|
return new ParsedTarget(APP_SCHEME + packageName, packageName);
|
||||||
|
}
|
||||||
|
return new ParsedTarget("", "");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String parseNode(AssistStructure.ViewNode node, ParsedFields fields) {
|
private static String parseNode(AssistStructure.ViewNode node, ParsedFields fields) {
|
||||||
@@ -185,4 +202,14 @@ public final class KeePassGOAutofillService extends AutofillService {
|
|||||||
AutofillId usernameId;
|
AutofillId usernameId;
|
||||||
AutofillId passwordId;
|
AutofillId passwordId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final class ParsedTarget {
|
||||||
|
final String matchTarget;
|
||||||
|
final String packageName;
|
||||||
|
|
||||||
|
ParsedTarget(String matchTarget, String packageName) {
|
||||||
|
this.matchTarget = matchTarget;
|
||||||
|
this.packageName = packageName;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -181,3 +181,57 @@ func TestMatchChoosesLongestPathPrefix(t *testing.T) {
|
|||||||
t.Fatalf("Match() entry = %q, want two", got.ID)
|
t.Fatalf("Match() entry = %q, want two", got.ID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestMatchSupportsAndroidAppPackageTargets(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
cache := File{
|
||||||
|
Entries: []Entry{
|
||||||
|
{
|
||||||
|
ID: "one",
|
||||||
|
Title: "Thunderbird",
|
||||||
|
Username: "mail-user",
|
||||||
|
Password: "secret1",
|
||||||
|
URL: "androidapp://org.mozilla.thunderbird/login",
|
||||||
|
Host: "org.mozilla.thunderbird",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
got, ok := Match(cache, "androidapp://org.mozilla.thunderbird")
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("Match() found no entry")
|
||||||
|
}
|
||||||
|
if got.ID != "one" {
|
||||||
|
t.Fatalf("Match() entry = %q, want one", got.ID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMatchRejectsAmbiguousAndroidAppPackageTargets(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
cache := File{
|
||||||
|
Entries: []Entry{
|
||||||
|
{
|
||||||
|
ID: "one",
|
||||||
|
Title: "Thunderbird Primary",
|
||||||
|
Username: "mail-user",
|
||||||
|
Password: "secret1",
|
||||||
|
URL: "androidapp://org.mozilla.thunderbird",
|
||||||
|
Host: "org.mozilla.thunderbird",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ID: "two",
|
||||||
|
Title: "Thunderbird Secondary",
|
||||||
|
Username: "other-user",
|
||||||
|
Password: "secret2",
|
||||||
|
URL: "androidapp://org.mozilla.thunderbird",
|
||||||
|
Host: "org.mozilla.thunderbird",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := Match(cache, "androidapp://org.mozilla.thunderbird"); ok {
|
||||||
|
t.Fatalf("Match() unexpectedly resolved ambiguous android app package target")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user