aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFelipe Leme <felipeal@google.com>2018-03-06 15:39:51 -0800
committerFelipe Leme <felipeal@google.com>2018-03-06 23:42:23 +0000
commit849dd8a02a6e2a6963e20623cba0eaa6f19db502 (patch)
tree95fd3da71bccafcd3c05829e0a9e91ea7f347995
parent4ebafcb6bef7ebf49232188abcca622f27ad3147 (diff)
downloadexperimental-849dd8a02a6e2a6963e20623cba0eaa6f19db502.tar.gz
Test: manual verification Bug: 72811034 Change-Id: I69aac5c93887b43c333894fbd893835ff66c8256
-rw-r--r--FillService/AndroidManifest.xml8
-rw-r--r--FillService/res/xml/autofill_service_config.xml20
-rw-r--r--FillService/src/foo/bar/fill/FillService.java120
3 files changed, 114 insertions, 34 deletions
diff --git a/FillService/AndroidManifest.xml b/FillService/AndroidManifest.xml
index f9128e1..da039b6 100644
--- a/FillService/AndroidManifest.xml
+++ b/FillService/AndroidManifest.xml
@@ -4,10 +4,16 @@
<application>
<service android:name=".FillService"
- android:permission="android.permission.BIND_AUTOFILL">
+ android:permission="android.permission.BIND_AUTOFILL_SERVICE">
<intent-filter>
<action android:name="android.service.autofill.AutofillService" />
</intent-filter>
+
+ <meta-data
+ android:name="android.autofill"
+ android:resource="@xml/autofill_service_config">
+ </meta-data>
+
</service>
<activity android:name=".AuthActivity"/>
diff --git a/FillService/res/xml/autofill_service_config.xml b/FillService/res/xml/autofill_service_config.xml
new file mode 100644
index 0000000..dd73a19
--- /dev/null
+++ b/FillService/res/xml/autofill_service_config.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 Google Inc.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<autofill-service xmlns:android="http://schemas.android.com/apk/res/android">
+ <compatibility-package android:name="com.android.chrome" android:maxLongVersionCode="1000000000" android:urlBarResourceId="url_bar"/>
+ <compatibility-package android:name="com.chrome.beta" android:maxLongVersionCode="1000000000" android:urlBarResourceId="url_bar"/>
+</autofill-service>
diff --git a/FillService/src/foo/bar/fill/FillService.java b/FillService/src/foo/bar/fill/FillService.java
index c253e7c..6eebac1 100644
--- a/FillService/src/foo/bar/fill/FillService.java
+++ b/FillService/src/foo/bar/fill/FillService.java
@@ -24,6 +24,7 @@ import android.app.assist.AssistStructure.WindowNode;
import android.app.assist.AssistStructure.ViewNode;
import android.content.Intent;
import android.content.IntentSender;
+import android.content.pm.PackageManager;
import android.os.CancellationSignal;
import android.service.autofill.AutofillService;
import android.service.autofill.Dataset;
@@ -33,16 +34,24 @@ import android.service.autofill.FillResponse;
import android.service.autofill.SaveCallback;
import android.service.autofill.SaveInfo;
import android.service.autofill.SaveRequest;
+import android.util.Log;
import android.view.View;
import android.view.autofill.AutofillId;
+import android.view.autofill.AutofillManager;
import android.view.autofill.AutofillValue;
+import android.widget.EditText;
import android.widget.RemoteViews;
+import java.util.ArrayList;
+import java.util.List;
import java.util.function.Predicate;
+import android.widget.TextView;
import foo.bar.fill.R;
public class FillService extends AutofillService {
+ private static final String LOG_TAG = "FillService";
+
static final boolean TEST_RESPONSE_AUTH = false;
public static final String RESPONSE_ID = "RESPONSE_ID";
@@ -76,8 +85,20 @@ public class FillService extends AutofillService {
@NonNull FillCallback callback) {
AssistStructure structure = request.getFillContexts().get(0).getStructure();
- ViewNode username = findUsername(structure);
- ViewNode password = findPassword(structure);
+ dumpNodeTree(structure);
+
+// ViewNode username = findUsername(structure);
+// ViewNode password = findPassword(structure);
+
+ ViewNode username = null;
+ ViewNode password = null;
+ final List<ViewNode> inputs = findTextInputs(structure);
+ if (inputs.size() > 1) {
+ username = inputs.get(0);
+ password = inputs.get(1);
+ }
+
+ Log.i(LOG_TAG, "found username+username:" + (username != null && password != null));
if (username != null && password != null) {
final FillResponse response;
@@ -134,46 +155,48 @@ public class FillService extends AutofillService {
.setValue(password.getAutofillId(),
AutofillValue.forText(DATASET1_PASSWORD))
.build())
- .addDataset(new Dataset.Builder(presentation2)
- .setValue(username.getAutofillId(),
- AutofillValue.forText(DATASET2_USERNAME))
- .setValue(password.getAutofillId(),
- AutofillValue.forText(DATASET2_PASSWORD))
-// .setAuthentication(sender)
- .build())
- .addDataset(new Dataset.Builder(presentation3)
- .setValue(username.getAutofillId(),
- AutofillValue.forText(DATASET3_USERNAME))
- .setValue(password.getAutofillId(),
- AutofillValue.forText(DATASET3_PASSWORD))
-// .setAuthentication(sender)
- .build())
- .addDataset(new Dataset.Builder(presentation4)
- .setValue(username.getAutofillId(),
- AutofillValue.forText(DATASET4_USERNAME))
- .setValue(password.getAutofillId(),
- AutofillValue.forText(DATASET4_PASSWORD))
+// .addDataset(new Dataset.Builder(presentation2)
+// .setValue(username.getAutofillId(),
+// AutofillValue.forText(DATASET2_USERNAME))
+// .setValue(password.getAutofillId(),
+// AutofillValue.forText(DATASET2_PASSWORD))
+//// .setAuthentication(sender)
+// .build())
+// .addDataset(new Dataset.Builder(presentation3)
+// .setValue(username.getAutofillId(),
+// AutofillValue.forText(DATASET3_USERNAME))
+// .setValue(password.getAutofillId(),
+// AutofillValue.forText(DATASET3_PASSWORD))
+//// .setAuthentication(sender)
+// .build())
+// .addDataset(new Dataset.Builder(presentation4)
+// .setValue(username.getAutofillId(),
+// AutofillValue.forText(DATASET4_USERNAME))
+// .setValue(password.getAutofillId(),
+// AutofillValue.forText(DATASET4_PASSWORD))
+//// .setAuthentication(sender)
+// .build())
+// .addDataset(new Dataset.Builder(presentation5)
+// .setValue(username.getAutofillId(),
+// AutofillValue.forText(DATASET5_USERNAME))
+// .setValue(password.getAutofillId(),
+// AutofillValue.forText(DATASET5_PASSWORD))
// .setAuthentication(sender)
- .build())
- .addDataset(new Dataset.Builder(presentation5)
- .setValue(username.getAutofillId(),
- AutofillValue.forText(DATASET5_USERNAME))
- .setValue(password.getAutofillId(),
- AutofillValue.forText(DATASET5_PASSWORD))
- .setAuthentication(sender)
- .build())
+// .build())
.setSaveInfo(new SaveInfo.Builder(
SaveInfo.SAVE_DATA_TYPE_PASSWORD
| SaveInfo.SAVE_DATA_TYPE_USERNAME,
new AutofillId[] {username.getAutofillId(),
password.getAutofillId()})
+ .setFlags(SaveInfo.FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE)
.build())
.build();
}
callback.onSuccess(response);
} else {
- callback.onFailure("Whoops");
+ //callback.onFailure("Whoops");
+ callback.onSuccess(null);
}
}
@@ -184,20 +207,51 @@ public class FillService extends AutofillService {
ViewNode password = findPassword(structure);
}
+ static void dumpNodeTree(AssistStructure structure) {
+ findByPredicate(structure, (node) -> {
+ if (node.getAutofillValue() != null) {
+ Log.e("class:" + LOG_TAG, node.getClassName() + " value:" + node.getAutofillValue());
+ }
+// Log.e(LOG_TAG, (node.getAutofillValue() != null && node.getAutofillValue().isText())
+// ? node.getAutofillValue().getTextValue().toString() + "-" +node.getAutofillId() : "NOPE");
+ return false;
+ });
+ }
+
+ List<ViewNode > findTextInputs(AssistStructure structure) {
+ final List<ViewNode> inputs = new ArrayList<>();
+ findByPredicate(structure, (node) -> {
+ if (node.getClassName().equals(EditText.class.getName())) {
+ inputs.add(node);
+ }
+ return false;
+ });
+ return inputs;
+ }
+
static ViewNode findUsername(AssistStructure structure) {
return findByPredicate(structure, (node) ->
node.getAutofillType() == View.AUTOFILL_TYPE_TEXT
- && "username".equals(node.getIdEntry())
+ && (autofillTextValueContains(node, "username")
+ || "username".equals(node.getIdEntry()))
);
}
static ViewNode findPassword(AssistStructure structure) {
return findByPredicate(structure, (node) ->
- node.getAutofillType() == View.AUTOFILL_TYPE_TEXT
- && "password".equals(node.getIdEntry())
+ node.getAutofillType() == View.AUTOFILL_TYPE_TEXT
+ && (autofillTextValueContains(node, "password")
+ || "password".equals(node.getIdEntry()))
);
}
+ private static boolean autofillTextValueContains(ViewNode node, String text) {
+ return node.getAutofillValue() != null
+ && node.getAutofillValue().getTextValue() != null
+ && node.getAutofillValue().getTextValue().toString().toLowerCase()
+ .contains(text.toLowerCase());
+ }
+
private static ViewNode findByPredicate(AssistStructure structure,
Predicate<ViewNode> predicate) {
final int windowCount = structure.getWindowNodeCount();