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 {
|
||||
private static final String TAG = "KeePassGOAutofill";
|
||||
private static final String APP_SCHEME = "androidapp://";
|
||||
|
||||
@Override
|
||||
public void onConnected() {
|
||||
@@ -51,15 +52,21 @@ public final class KeePassGOAutofillService extends AutofillService {
|
||||
|
||||
AssistStructure structure = contexts.get(contexts.size() - 1).getStructure();
|
||||
ParsedFields fields = new ParsedFields();
|
||||
String webDomain = parseWindow(structure, fields);
|
||||
Log.i(TAG, "parsed domain=" + webDomain + " usernameId=" + fields.usernameId + " passwordId=" + fields.passwordId);
|
||||
ParsedTarget target = parseWindow(structure, fields);
|
||||
Log.i(
|
||||
TAG,
|
||||
"parsed target=" + target.matchTarget
|
||||
+ " package=" + target.packageName
|
||||
+ " usernameId=" + fields.usernameId
|
||||
+ " passwordId=" + fields.passwordId
|
||||
);
|
||||
if (fields.passwordId == null) {
|
||||
Log.i(TAG, "no password field found");
|
||||
callback.onSuccess(null);
|
||||
return;
|
||||
}
|
||||
|
||||
AutofillCacheStore.Entry entry = AutofillCacheStore.findBestMatch(this, webDomain);
|
||||
AutofillCacheStore.Entry entry = AutofillCacheStore.findBestMatch(this, target.matchTarget);
|
||||
if (entry == null) {
|
||||
Log.i(TAG, "no autofill cache match");
|
||||
callback.onSuccess(null);
|
||||
@@ -96,7 +103,7 @@ public final class KeePassGOAutofillService extends AutofillService {
|
||||
callback.onSuccess();
|
||||
}
|
||||
|
||||
private static String parseWindow(AssistStructure structure, ParsedFields fields) {
|
||||
private static ParsedTarget parseWindow(AssistStructure structure, ParsedFields fields) {
|
||||
String domain = "";
|
||||
final int windowCount = structure.getWindowNodeCount();
|
||||
for (int i = 0; i < windowCount; i++) {
|
||||
@@ -106,7 +113,17 @@ public final class KeePassGOAutofillService extends AutofillService {
|
||||
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) {
|
||||
@@ -185,4 +202,14 @@ public final class KeePassGOAutofillService extends AutofillService {
|
||||
AutofillId usernameId;
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
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