Autofill: Make Server and Computed field type available for Java
Make server and computed field types available for Java when the autofill starts, this patch doesn't work for prediction that arrives after the autofill start. Add the integration test. Change-Id: I2eb23f0244ce4b745eaa15bcaee57e10f41acd2c Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2581146 Commit-Queue: Michael Bai <michaelbai@chromium.org> Reviewed-by: Dominic Battré <battre@chromium.org> Cr-Commit-Position: refs/heads/master@{#835841}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
948fc04f7b
commit
87d86528c4
android_webview
components/autofill
android
provider
DEPSform_data_android.ccform_data_android.hform_field_data_android.ccform_field_data_android.h
java
src
org
chromium
components
junit
src
org
chromium
components
autofill
test_support
core
@ -1,5 +1,6 @@
|
||||
include_rules = [
|
||||
"+components/autofill/android/java",
|
||||
"+components/autofill/android/provider",
|
||||
"+components/background_task_scheduler/android/java",
|
||||
"+components/minidump_uploader/android/java",
|
||||
"+components/minidump_uploader/android/javatests",
|
||||
|
@ -56,6 +56,7 @@ import org.chromium.base.test.util.MinAndroidSdkLevel;
|
||||
import org.chromium.components.autofill.AutofillManagerWrapper;
|
||||
import org.chromium.components.autofill.AutofillPopup;
|
||||
import org.chromium.components.autofill.AutofillProvider;
|
||||
import org.chromium.components.autofill.AutofillProviderTestHelper;
|
||||
import org.chromium.components.autofill.AutofillProviderUMA;
|
||||
import org.chromium.components.embedder_support.util.WebResourceResponseInfo;
|
||||
import org.chromium.content_public.browser.UiThreadTaskTraits;
|
||||
@ -2056,6 +2057,85 @@ public class AwAutofillTest {
|
||||
assertEquals(View.INVISIBLE, viewStructure.getChild(1).getVisibility());
|
||||
}
|
||||
|
||||
@Test
|
||||
@SmallTest
|
||||
@Feature({"AndroidWebView"})
|
||||
public void testServerPredictionArrivesBeforeAutofillStart() throws Throwable {
|
||||
final String data = "<html><head></head><body><form action='a.html' name='formname'>"
|
||||
+ "<input type='text' id='text1' name='username'>"
|
||||
+ "<input type='text' name='email' id='text2'/>"
|
||||
+ "</form></body></html>";
|
||||
final String url = mWebServer.setResponse(FILE, data, null);
|
||||
loadUrlSync(url);
|
||||
TestThreadUtils.runOnUiThreadBlocking(
|
||||
()
|
||||
-> AutofillProviderTestHelper
|
||||
.simulateMainFrameAutofillServerResponseForTesting(
|
||||
mAwContents.getWebContents(),
|
||||
new String[] {"text1", "text2"},
|
||||
new int[] {/*EMAIL_ADDRESS, USERNAME*/ 9, 86}));
|
||||
|
||||
int cnt = 0;
|
||||
executeJavaScriptAndWaitForResult("document.getElementById('text1').select();");
|
||||
dispatchDownAndUpKeyEvents(KeyEvent.KEYCODE_A);
|
||||
|
||||
cnt += waitForCallbackAndVerifyTypes(cnt,
|
||||
new Integer[] {AUTOFILL_CANCEL, AUTOFILL_VIEW_ENTERED, AUTOFILL_SESSION_STARTED,
|
||||
AUTOFILL_VALUE_CHANGED});
|
||||
|
||||
invokeOnProvideAutoFillVirtualStructure();
|
||||
TestViewStructure viewStructure = mTestValues.testViewStructure;
|
||||
assertNotNull(viewStructure);
|
||||
assertEquals(2, viewStructure.getChildCount());
|
||||
assertEquals("EMAIL_ADDRESS",
|
||||
viewStructure.getChild(0).getHtmlInfo().getAttribute(
|
||||
"crowdsourcing-autofill-hints"));
|
||||
assertEquals("EMAIL_ADDRESS",
|
||||
viewStructure.getChild(0).getHtmlInfo().getAttribute("computed-autofill-hints"));
|
||||
assertEquals("USERNAME",
|
||||
viewStructure.getChild(1).getHtmlInfo().getAttribute(
|
||||
"crowdsourcing-autofill-hints"));
|
||||
assertEquals("USERNAME",
|
||||
viewStructure.getChild(1).getHtmlInfo().getAttribute("computed-autofill-hints"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@SmallTest
|
||||
@Feature({"AndroidWebView"})
|
||||
public void testServerPredictionArrivesAfterAutofillStart() throws Throwable {
|
||||
final String data = "<html><head></head><body><form action='a.html' name='formname'>"
|
||||
+ "<input type='text' id='text1' name='username'>"
|
||||
+ "<input type='text' name='email' id='text2'/>"
|
||||
+ "</form></body></html>";
|
||||
final String url = mWebServer.setResponse(FILE, data, null);
|
||||
loadUrlSync(url);
|
||||
|
||||
int cnt = 0;
|
||||
executeJavaScriptAndWaitForResult("document.getElementById('text1').select();");
|
||||
dispatchDownAndUpKeyEvents(KeyEvent.KEYCODE_A);
|
||||
|
||||
cnt += waitForCallbackAndVerifyTypes(cnt,
|
||||
new Integer[] {AUTOFILL_CANCEL, AUTOFILL_VIEW_ENTERED, AUTOFILL_SESSION_STARTED,
|
||||
AUTOFILL_VALUE_CHANGED});
|
||||
|
||||
invokeOnProvideAutoFillVirtualStructure();
|
||||
TestViewStructure viewStructure = mTestValues.testViewStructure;
|
||||
assertNotNull(viewStructure);
|
||||
assertEquals(2, viewStructure.getChildCount());
|
||||
assertEquals("NO_SERVER_DATA",
|
||||
viewStructure.getChild(0).getHtmlInfo().getAttribute(
|
||||
"crowdsourcing-autofill-hints"));
|
||||
assertEquals("NO_SERVER_DATA",
|
||||
viewStructure.getChild(0).getHtmlInfo().getAttribute("computed-autofill-hints"));
|
||||
assertEquals("NO_SERVER_DATA",
|
||||
viewStructure.getChild(1).getHtmlInfo().getAttribute(
|
||||
"crowdsourcing-autofill-hints"));
|
||||
assertEquals("NO_SERVER_DATA",
|
||||
viewStructure.getChild(1).getHtmlInfo().getAttribute("computed-autofill-hints"));
|
||||
|
||||
// TODO(crbug.com/1151542): Complete the test once the prediction update is implemented.
|
||||
}
|
||||
|
||||
private void pollJavascriptResult(String script, String expectedResult) throws Throwable {
|
||||
AwActivityTestRule.pollInstrumentationThread(() -> {
|
||||
try {
|
||||
|
@ -55,6 +55,7 @@ android_apk("webview_instrumentation_apk") {
|
||||
"//android_webview:platform_service_bridge_upstream_implementation_java",
|
||||
"//base:base_java",
|
||||
"//base:base_java_test_support",
|
||||
"//components/autofill/android/provider/test_support:component_autofill_provider_java_test_support",
|
||||
"//components/embedder_support/android:util_java",
|
||||
"//components/heap_profiling/multi_process:heap_profiling_java_test_support",
|
||||
"//components/policy/android:policy_java_test_support",
|
||||
@ -147,6 +148,7 @@ shared_library("libstandalonelibwebviewchromium") {
|
||||
"//android_webview/nonembedded",
|
||||
"//android_webview/public",
|
||||
"//base",
|
||||
"//components/autofill/android/provider/test_support:component_autofill_provider_native_test_support",
|
||||
"//components/heap_profiling/multi_process:test_support",
|
||||
"//content/public/test/android:content_native_test_support",
|
||||
]
|
||||
@ -176,6 +178,7 @@ instrumentation_test_apk("webview_instrumentation_test_apk") {
|
||||
"//base:base_java_test_support",
|
||||
"//components/autofill/android:autofill_java",
|
||||
"//components/autofill/android/provider:java",
|
||||
"//components/autofill/android/provider/test_support:component_autofill_provider_java_test_support",
|
||||
"//components/autofill/core/common/mojom:mojo_types_java",
|
||||
"//components/background_task_scheduler:background_task_scheduler_task_ids_java",
|
||||
"//components/content_capture/android:java",
|
||||
|
3
components/autofill/android/provider/DEPS
Normal file
3
components/autofill/android/provider/DEPS
Normal file
@ -0,0 +1,3 @@
|
||||
include_rules = [
|
||||
"+components/autofill/content",
|
||||
]
|
@ -40,7 +40,7 @@ ScopedJavaLocalRef<jobject> FormDataAndroid::GetJavaPeer(
|
||||
new FormFieldDataAndroid(&form_.fields[i])));
|
||||
}
|
||||
if (form_structure)
|
||||
ApplyHeuristicFieldType(*form_structure);
|
||||
UpdateFieldTypes(*form_structure);
|
||||
ScopedJavaLocalRef<jstring> jname =
|
||||
ConvertUTF16ToJavaString(env, form_.name);
|
||||
ScopedJavaLocalRef<jstring> jhost =
|
||||
@ -96,14 +96,15 @@ bool FormDataAndroid::SimilarFormAs(const FormData& form) {
|
||||
return form_.SimilarFormAs(form);
|
||||
}
|
||||
|
||||
void FormDataAndroid::ApplyHeuristicFieldType(
|
||||
const FormStructure& form_structure) {
|
||||
void FormDataAndroid::UpdateFieldTypes(const FormStructure& form_structure) {
|
||||
DCHECK(form_structure.field_count() == fields_.size());
|
||||
auto form_field_data_android = fields_.begin();
|
||||
for (const auto& autofill_field : form_structure) {
|
||||
DCHECK(form_field_data_android->get()->SimilarFieldAs(*autofill_field));
|
||||
form_field_data_android->get()->set_heuristic_type(
|
||||
AutofillType(autofill_field->heuristic_type()));
|
||||
form_field_data_android->get()->UpdateAutofillTypes(
|
||||
AutofillType(autofill_field->heuristic_type()),
|
||||
AutofillType(autofill_field->server_type()),
|
||||
autofill_field->ComputedType());
|
||||
if (++form_field_data_android == fields_.end())
|
||||
break;
|
||||
}
|
||||
|
@ -52,7 +52,8 @@ class FormDataAndroid {
|
||||
// |value|.
|
||||
void OnFormFieldDidChange(size_t index, const base::string16& value);
|
||||
|
||||
void ApplyHeuristicFieldType(const FormStructure& form);
|
||||
// Updates the field types from the |form|.
|
||||
void UpdateFieldTypes(const FormStructure& form);
|
||||
|
||||
const FormData& form() { return form_; }
|
||||
|
||||
|
@ -47,9 +47,18 @@ ScopedJavaLocalRef<jobject> FormFieldDataAndroid::GetJavaPeer() {
|
||||
ScopedJavaLocalRef<jobjectArray> joption_contents =
|
||||
ToJavaArrayOfStrings(env, field_ptr_->option_contents);
|
||||
ScopedJavaLocalRef<jstring> jheuristic_type;
|
||||
if (!heuristic_type_.IsUnknown())
|
||||
if (!heuristic_type_.IsUnknown()) {
|
||||
jheuristic_type =
|
||||
ConvertUTF8ToJavaString(env, heuristic_type_.ToString());
|
||||
}
|
||||
ScopedJavaLocalRef<jstring> jserver_type;
|
||||
if (!server_type_.IsUnknown()) {
|
||||
jserver_type = ConvertUTF8ToJavaString(env, server_type_.ToString());
|
||||
}
|
||||
ScopedJavaLocalRef<jstring> jcomputed_type;
|
||||
if (!computed_type_.IsUnknown()) {
|
||||
jcomputed_type = ConvertUTF8ToJavaString(env, computed_type_.ToString());
|
||||
}
|
||||
ScopedJavaLocalRef<jobjectArray> jdatalist_values =
|
||||
ToJavaArrayOfStrings(env, field_ptr_->datalist_values);
|
||||
ScopedJavaLocalRef<jobjectArray> jdatalist_labels =
|
||||
@ -60,9 +69,10 @@ ScopedJavaLocalRef<jobject> FormFieldDataAndroid::GetJavaPeer() {
|
||||
field_ptr_->should_autocomplete, jplaceholder, jtype, jid,
|
||||
joption_values, joption_contents, IsCheckable(field_ptr_->check_status),
|
||||
IsChecked(field_ptr_->check_status), field_ptr_->max_length,
|
||||
jheuristic_type, field_ptr_->bounds.x(), field_ptr_->bounds.y(),
|
||||
field_ptr_->bounds.right(), field_ptr_->bounds.bottom(),
|
||||
jdatalist_values, jdatalist_labels, field_ptr_->IsVisible());
|
||||
jheuristic_type, jserver_type, jcomputed_type, field_ptr_->bounds.x(),
|
||||
field_ptr_->bounds.y(), field_ptr_->bounds.right(),
|
||||
field_ptr_->bounds.bottom(), jdatalist_values, jdatalist_labels,
|
||||
field_ptr_->IsVisible());
|
||||
java_ref_ = JavaObjectWeakGlobalRef(env, obj);
|
||||
}
|
||||
return obj;
|
||||
@ -103,4 +113,13 @@ bool FormFieldDataAndroid::SimilarFieldAs(const FormFieldData& field) const {
|
||||
return field_ptr_->SimilarFieldAs(field);
|
||||
}
|
||||
|
||||
void FormFieldDataAndroid::UpdateAutofillTypes(
|
||||
const AutofillType& heuristic_type,
|
||||
const AutofillType& server_type,
|
||||
const AutofillType& computed_type) {
|
||||
heuristic_type_ = heuristic_type;
|
||||
server_type_ = server_type;
|
||||
computed_type_ = computed_type;
|
||||
}
|
||||
|
||||
} // namespace autofill
|
||||
|
@ -23,13 +23,15 @@ class FormFieldDataAndroid {
|
||||
void GetValue();
|
||||
void OnFormFieldDidChange(const base::string16& value);
|
||||
bool SimilarFieldAs(const FormFieldData& field) const;
|
||||
|
||||
void set_heuristic_type(const AutofillType& heuristic_type) {
|
||||
heuristic_type_ = heuristic_type;
|
||||
}
|
||||
void UpdateAutofillTypes(const AutofillType& heuristic_type,
|
||||
const AutofillType& server_type,
|
||||
const AutofillType& computed_type);
|
||||
|
||||
private:
|
||||
AutofillType heuristic_type_;
|
||||
AutofillType server_type_;
|
||||
AutofillType computed_type_;
|
||||
|
||||
// Not owned.
|
||||
FormFieldData* field_ptr_;
|
||||
JavaObjectWeakGlobalRef java_ref_;
|
||||
|
5
components/autofill/android/provider/java/src/org/chromium/components/autofill/AutofillProvider.java
5
components/autofill/android/provider/java/src/org/chromium/components/autofill/AutofillProvider.java
@ -118,6 +118,11 @@ public class AutofillProvider {
|
||||
.addAttribute("ua-autofill-hints", field.mHeuristicType)
|
||||
.addAttribute("id", field.mId);
|
||||
|
||||
// TODO(crbug.com/1151542): Only add the additional attributes if the crowdsourcing
|
||||
// feature is enabled.
|
||||
builder.addAttribute("crowdsourcing-autofill-hints", field.getServerType());
|
||||
builder.addAttribute("computed-autofill-hints", field.getComputedType());
|
||||
|
||||
switch (field.getControlType()) {
|
||||
case FormFieldData.ControlType.LIST:
|
||||
child.setAutofillType(View.AUTOFILL_TYPE_LIST);
|
||||
|
30
components/autofill/android/provider/java/src/org/chromium/components/autofill/FormFieldData.java
30
components/autofill/android/provider/java/src/org/chromium/components/autofill/FormFieldData.java
@ -63,11 +63,17 @@ public class FormFieldData {
|
||||
// Indicates whether this fields was autofilled, but changed by user.
|
||||
private boolean mPreviouslyAutofilled;
|
||||
|
||||
// Provides the field type along with mHeuristicType, but could be changed
|
||||
// after the object instantiated.
|
||||
private String mServerType;
|
||||
private String mComputedType;
|
||||
|
||||
private FormFieldData(String name, String label, String value, String autocompleteAttr,
|
||||
boolean shouldAutocomplete, String placeholder, String type, String id,
|
||||
String[] optionValues, String[] optionContents, boolean isCheckField, boolean isChecked,
|
||||
int maxLength, String heuristicType, float left, float top, float right, float bottom,
|
||||
String[] datalistValues, String[] datalistLabels, boolean visible) {
|
||||
int maxLength, String heuristicType, String serverType, String computedType, float left,
|
||||
float top, float right, float bottom, String[] datalistValues, String[] datalistLabels,
|
||||
boolean visible) {
|
||||
mName = name;
|
||||
mLabel = label;
|
||||
mValue = value;
|
||||
@ -92,6 +98,8 @@ public class FormFieldData {
|
||||
}
|
||||
mMaxLength = maxLength;
|
||||
mHeuristicType = heuristicType;
|
||||
mServerType = serverType;
|
||||
mComputedType = computedType;
|
||||
mBounds = new RectF(left, top, right, bottom);
|
||||
mVisible = visible;
|
||||
}
|
||||
@ -136,6 +144,14 @@ public class FormFieldData {
|
||||
updateAutofillState(false);
|
||||
}
|
||||
|
||||
public String getServerType() {
|
||||
return mServerType;
|
||||
}
|
||||
|
||||
public String getComputedType() {
|
||||
return mComputedType;
|
||||
}
|
||||
|
||||
@CalledByNative
|
||||
public boolean isChecked() {
|
||||
return mIsChecked;
|
||||
@ -155,12 +171,12 @@ public class FormFieldData {
|
||||
public static FormFieldData createFormFieldData(String name, String label, String value,
|
||||
String autocompleteAttr, boolean shouldAutocomplete, String placeholder, String type,
|
||||
String id, String[] optionValues, String[] optionContents, boolean isCheckField,
|
||||
boolean isChecked, int maxLength, String heuristicType, float left, float top,
|
||||
float right, float bottom, String[] datalistValues, String[] datalistLabels,
|
||||
boolean visible) {
|
||||
boolean isChecked, int maxLength, String heuristicType, String serverType,
|
||||
String computedType, float left, float top, float right, float bottom,
|
||||
String[] datalistValues, String[] datalistLabels, boolean visible) {
|
||||
return new FormFieldData(name, label, value, autocompleteAttr, shouldAutocomplete,
|
||||
placeholder, type, id, optionValues, optionContents, isCheckField, isChecked,
|
||||
maxLength, heuristicType, left, top, right, bottom, datalistValues, datalistLabels,
|
||||
visible);
|
||||
maxLength, heuristicType, serverType, computedType, left, top, right, bottom,
|
||||
datalistValues, datalistLabels, visible);
|
||||
}
|
||||
}
|
||||
|
@ -83,10 +83,10 @@ public class AutofillProviderTest {
|
||||
public void testTransformFormFieldToContainViewCoordinates() {
|
||||
ArrayList<FormFieldData> fields = new ArrayList<FormFieldData>(1);
|
||||
fields.add(FormFieldData.createFormFieldData(null, null, null, null, false, null, null,
|
||||
null, null, null, false, false, 0, null, 10 /* left */, 20 /* top */,
|
||||
null, null, null, false, false, 0, null, null, null, 10 /* left */, 20 /* top */,
|
||||
300 /* right */, 60 /*bottom*/, null, null, true));
|
||||
fields.add(FormFieldData.createFormFieldData(null, null, null, null, false, null, null,
|
||||
null, null, null, false, false, 0, null, 20 /* left */, 100 /* top */,
|
||||
null, null, null, false, false, 0, null, null, null, 20 /* left */, 100 /* top */,
|
||||
400 /* right */, 200 /*bottom*/, null, null, true));
|
||||
FormData formData = new FormData(null, null, fields);
|
||||
mAutofillProvider.transformFormFieldToContainViewCoordinates(formData);
|
||||
|
38
components/autofill/android/provider/test_support/BUILD.gn
Normal file
38
components/autofill/android/provider/test_support/BUILD.gn
Normal file
@ -0,0 +1,38 @@
|
||||
# Copyright 2020 The Chromium Authors. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the LICENSE file.
|
||||
|
||||
import("//build/config/android/config.gni")
|
||||
import("//build/config/android/rules.gni")
|
||||
|
||||
testonly = true
|
||||
|
||||
android_library("component_autofill_provider_java_test_support") {
|
||||
annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
|
||||
sources = [
|
||||
"java/src/org/chromium/components/autofill/AutofillProviderTestHelper.java",
|
||||
]
|
||||
deps = [
|
||||
"//base:base_java",
|
||||
"//base:jni_java",
|
||||
"//components/autofill/android/provider:java",
|
||||
"//content/public/android:content_java",
|
||||
"//third_party/android_deps:androidx_annotation_annotation_java",
|
||||
]
|
||||
}
|
||||
generate_jni("jni_headers") {
|
||||
sources = [
|
||||
"java/src/org/chromium/components/autofill/AutofillProviderTestHelper.java",
|
||||
]
|
||||
}
|
||||
|
||||
source_set("component_autofill_provider_native_test_support") {
|
||||
sources = [ "autofill_provider_test_helper.cc" ]
|
||||
deps = [
|
||||
":jni_headers",
|
||||
"//base",
|
||||
"//components/autofill/content/browser",
|
||||
"//components/autofill/core/browser:test_support",
|
||||
"//content/public/browser",
|
||||
]
|
||||
}
|
@ -0,0 +1,75 @@
|
||||
// Copyright 2020 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "components/autofill/android/provider/test_support/jni_headers/AutofillProviderTestHelper_jni.h"
|
||||
|
||||
#include "base/android/jni_array.h"
|
||||
#include "base/base64.h"
|
||||
#include "base/strings/string16.h"
|
||||
#include "components/autofill/content/browser/content_autofill_driver.h"
|
||||
#include "components/autofill/core/browser/autofill_test_utils.h"
|
||||
#include "components/autofill/core/browser/field_types.h"
|
||||
#include "content/public/browser/web_contents.h"
|
||||
|
||||
namespace autofill {
|
||||
|
||||
static jboolean
|
||||
JNI_AutofillProviderTestHelper_SimulateMainFrameAutofillServerResponseForTesting(
|
||||
JNIEnv* env,
|
||||
const base::android::JavaParamRef<jobject>& jweb_contents,
|
||||
const base::android::JavaParamRef<jobjectArray>& jfield_ids,
|
||||
const base::android::JavaParamRef<jintArray>& jfield_types) {
|
||||
std::vector<base::string16> field_ids;
|
||||
base::android::AppendJavaStringArrayToStringVector(env, jfield_ids,
|
||||
&field_ids);
|
||||
std::vector<int> field_types;
|
||||
base::android::JavaIntArrayToIntVector(env, jfield_types, &field_types);
|
||||
|
||||
auto* web_contents = content::WebContents::FromJavaWebContents(jweb_contents);
|
||||
CHECK(web_contents);
|
||||
auto* driver = ContentAutofillDriver::GetForRenderFrameHost(
|
||||
web_contents->GetMainFrame());
|
||||
CHECK(driver);
|
||||
auto* autofill_handler = driver->autofill_handler();
|
||||
CHECK(autofill_handler);
|
||||
auto& form_structures = autofill_handler->form_structures();
|
||||
CHECK(!form_structures.empty());
|
||||
|
||||
// Make API response with suggestions.
|
||||
AutofillQueryResponse response;
|
||||
AutofillQueryResponse::FormSuggestion* form_suggestion;
|
||||
|
||||
form_suggestion = response.add_form_suggestions();
|
||||
size_t found_fields_count = 0;
|
||||
std::vector<FormSignature> signatures;
|
||||
for (auto& j : form_structures) {
|
||||
FormData formData = j.second->ToFormData();
|
||||
for (size_t i = 0; i < field_ids.size(); ++i) {
|
||||
for (auto form_field_data : formData.fields) {
|
||||
if (form_field_data.id_attribute == field_ids[i]) {
|
||||
autofill::test::AddFieldSuggestionToForm(
|
||||
form_field_data,
|
||||
static_cast<autofill::ServerFieldType>(field_types[i]),
|
||||
form_suggestion);
|
||||
found_fields_count++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (found_fields_count > 0) {
|
||||
signatures = autofill::test::GetEncodedSignatures(*(j.second));
|
||||
CHECK(found_fields_count == field_ids.size());
|
||||
}
|
||||
}
|
||||
|
||||
std::string response_string;
|
||||
CHECK(response.SerializeToString(&response_string));
|
||||
std::string encoded_response_string;
|
||||
base::Base64Encode(response_string, &encoded_response_string);
|
||||
autofill_handler->OnLoadedServerPredictionsForTest(encoded_response_string,
|
||||
signatures);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace autofill
|
34
components/autofill/android/provider/test_support/java/src/org/chromium/components/autofill/AutofillProviderTestHelper.java
Normal file
34
components/autofill/android/provider/test_support/java/src/org/chromium/components/autofill/AutofillProviderTestHelper.java
Normal file
@ -0,0 +1,34 @@
|
||||
// Copyright 2012 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
package org.chromium.components.autofill;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.os.Build;
|
||||
|
||||
import org.chromium.base.annotations.JNINamespace;
|
||||
import org.chromium.base.annotations.NativeMethods;
|
||||
import org.chromium.base.annotations.VerifiesOnO;
|
||||
import org.chromium.content_public.browser.WebContents;
|
||||
|
||||
/**
|
||||
* The help class for Autofill Provider test to access the native code.
|
||||
*/
|
||||
@VerifiesOnO
|
||||
@TargetApi(Build.VERSION_CODES.O)
|
||||
@JNINamespace("autofill")
|
||||
public class AutofillProviderTestHelper {
|
||||
public static boolean simulateMainFrameAutofillServerResponseForTesting(
|
||||
WebContents webContents, String[] fieldIds, int[] fieldTypes) {
|
||||
return AutofillProviderTestHelperJni.get()
|
||||
.simulateMainFrameAutofillServerResponseForTesting(
|
||||
webContents, fieldIds, fieldTypes);
|
||||
}
|
||||
|
||||
@NativeMethods
|
||||
interface Natives {
|
||||
boolean simulateMainFrameAutofillServerResponseForTesting(
|
||||
WebContents webContents, String[] fieldIds, int[] fieldTypes);
|
||||
}
|
||||
}
|
@ -170,6 +170,15 @@ class AutofillHandler : public AutofillDownloadManager::Observer {
|
||||
return form_interactions_ukm_logger_.get();
|
||||
}
|
||||
|
||||
// A public wrapper that calls |OnLoadedServerPredictions| for testing
|
||||
// purposes only, it is used by WebView integration test and unit test, so it
|
||||
// can't be in #ifdef UNIT_TEST.
|
||||
void OnLoadedServerPredictionsForTest(
|
||||
std::string response,
|
||||
const std::vector<FormSignature>& queried_form_signatures) {
|
||||
OnLoadedServerPredictions(response, queried_form_signatures);
|
||||
}
|
||||
|
||||
#ifdef UNIT_TEST
|
||||
// A public wrapper that calls |mutable_form_structures| for testing purposes
|
||||
// only.
|
||||
@ -183,13 +192,6 @@ class AutofillHandler : public AutofillDownloadManager::Observer {
|
||||
return ParseForm(form, nullptr);
|
||||
}
|
||||
|
||||
// A public wrapper that calls |OnLoadedServerPredictions| for testing
|
||||
// purposes only.
|
||||
void OnLoadedServerPredictionsForTest(
|
||||
std::string response,
|
||||
const std::vector<FormSignature>& queried_form_signatures) {
|
||||
OnLoadedServerPredictions(response, queried_form_signatures);
|
||||
}
|
||||
#endif // UNIT_TEST
|
||||
|
||||
protected:
|
||||
|
@ -5046,18 +5046,6 @@ TEST_P(AutofillManagerStructuredProfileTest,
|
||||
autofill_manager_.reset();
|
||||
}
|
||||
|
||||
namespace {
|
||||
void AddFieldSuggestionToForm(
|
||||
::autofill::AutofillQueryResponse_FormSuggestion* form_suggestion,
|
||||
autofill::FormFieldData field_data,
|
||||
ServerFieldType field_type) {
|
||||
auto* field_suggestion = form_suggestion->add_field_suggestions();
|
||||
field_suggestion->set_field_signature(
|
||||
CalculateFieldSignatureForField(field_data).value());
|
||||
field_suggestion->set_primary_type_prediction(field_type);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
// Test that OnLoadedServerPredictions can obtain the FormStructure with the
|
||||
// signature of the queried form from the API and apply type predictions.
|
||||
// What we test here:
|
||||
@ -5111,14 +5099,20 @@ TEST_P(AutofillManagerStructuredProfileTest, OnLoadedServerPredictionsFromApi) {
|
||||
AutofillQueryResponse::FormSuggestion* form_suggestion;
|
||||
// Set suggestions for form 1.
|
||||
form_suggestion = response.add_form_suggestions();
|
||||
AddFieldSuggestionToForm(form_suggestion, form.fields[0], ADDRESS_HOME_CITY);
|
||||
AddFieldSuggestionToForm(form_suggestion, form.fields[1], ADDRESS_HOME_STATE);
|
||||
AddFieldSuggestionToForm(form_suggestion, form.fields[2], ADDRESS_HOME_ZIP);
|
||||
autofill::test::AddFieldSuggestionToForm(form.fields[0], ADDRESS_HOME_CITY,
|
||||
form_suggestion);
|
||||
autofill::test::AddFieldSuggestionToForm(form.fields[1], ADDRESS_HOME_STATE,
|
||||
form_suggestion);
|
||||
autofill::test::AddFieldSuggestionToForm(form.fields[2], ADDRESS_HOME_ZIP,
|
||||
form_suggestion);
|
||||
// Set suggestions for form 2.
|
||||
form_suggestion = response.add_form_suggestions();
|
||||
AddFieldSuggestionToForm(form_suggestion, form2.fields[0], NAME_LAST);
|
||||
AddFieldSuggestionToForm(form_suggestion, form2.fields[1], NAME_MIDDLE);
|
||||
AddFieldSuggestionToForm(form_suggestion, form2.fields[2], ADDRESS_HOME_ZIP);
|
||||
autofill::test::AddFieldSuggestionToForm(form2.fields[0], NAME_LAST,
|
||||
form_suggestion);
|
||||
autofill::test::AddFieldSuggestionToForm(form2.fields[1], NAME_MIDDLE,
|
||||
form_suggestion);
|
||||
autofill::test::AddFieldSuggestionToForm(form2.fields[2], ADDRESS_HOME_ZIP,
|
||||
form_suggestion);
|
||||
|
||||
std::string response_string;
|
||||
ASSERT_TRUE(response.SerializeToString(&response_string));
|
||||
@ -5234,15 +5228,16 @@ TEST_P(AutofillManagerStructuredProfileTest,
|
||||
|
||||
AutofillQueryResponse response;
|
||||
auto* form_suggestion = response.add_form_suggestions();
|
||||
AddFieldSuggestionToForm(form_suggestion, form.fields[0],
|
||||
CREDIT_CARD_NAME_FIRST);
|
||||
AddFieldSuggestionToForm(form_suggestion, form.fields[1],
|
||||
CREDIT_CARD_NAME_LAST);
|
||||
AddFieldSuggestionToForm(form_suggestion, form.fields[2], CREDIT_CARD_NUMBER);
|
||||
AddFieldSuggestionToForm(form_suggestion, form.fields[3],
|
||||
CREDIT_CARD_EXP_MONTH);
|
||||
AddFieldSuggestionToForm(form_suggestion, form.fields[4],
|
||||
CREDIT_CARD_EXP_4_DIGIT_YEAR);
|
||||
autofill::test::AddFieldSuggestionToForm(
|
||||
form.fields[0], CREDIT_CARD_NAME_FIRST, form_suggestion);
|
||||
autofill::test::AddFieldSuggestionToForm(
|
||||
form.fields[1], CREDIT_CARD_NAME_LAST, form_suggestion);
|
||||
autofill::test::AddFieldSuggestionToForm(form.fields[2], CREDIT_CARD_NUMBER,
|
||||
form_suggestion);
|
||||
autofill::test::AddFieldSuggestionToForm(
|
||||
form.fields[3], CREDIT_CARD_EXP_MONTH, form_suggestion);
|
||||
autofill::test::AddFieldSuggestionToForm(
|
||||
form.fields[4], CREDIT_CARD_EXP_4_DIGIT_YEAR, form_suggestion);
|
||||
|
||||
std::string response_string;
|
||||
ASSERT_TRUE(response.SerializeToString(&response_string));
|
||||
|
@ -912,5 +912,15 @@ std::vector<FormSignature> GetEncodedSignatures(
|
||||
return all_signatures;
|
||||
}
|
||||
|
||||
void AddFieldSuggestionToForm(
|
||||
autofill::FormFieldData field_data,
|
||||
ServerFieldType field_type,
|
||||
::autofill::AutofillQueryResponse_FormSuggestion* form_suggestion) {
|
||||
auto* field_suggestion = form_suggestion->add_field_suggestions();
|
||||
field_suggestion->set_field_signature(
|
||||
CalculateFieldSignatureForField(field_data).value());
|
||||
field_suggestion->set_primary_type_prediction(field_type);
|
||||
}
|
||||
|
||||
} // namespace test
|
||||
} // namespace autofill
|
||||
|
@ -337,6 +337,11 @@ std::string LastYear();
|
||||
std::string NextYear();
|
||||
std::string TenYearsFromNow();
|
||||
|
||||
void AddFieldSuggestionToForm(
|
||||
autofill::FormFieldData field_data,
|
||||
ServerFieldType field_type,
|
||||
::autofill::AutofillQueryResponse_FormSuggestion* form_suggestion);
|
||||
|
||||
} // namespace test
|
||||
} // namespace autofill
|
||||
|
||||
|
Reference in New Issue
Block a user