Commit 9f4a6205 authored by Michael Bai's avatar Michael Bai Committed by Chromium LUCI CQ

Autofill: Support the server predictions

Make the server prediction available as ViewType, separate it from
mServerType to consistent with AutofillServer protobuf.

Add the tests to cover it.

Bug: 1151542
Change-Id: I1083cdc621d586d32327ee40e973b26f3d724f8f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2623673
Commit-Queue: Michael Bai <michaelbai@chromium.org>
Reviewed-by: default avatarRobert Sesek <rsesek@chromium.org>
Reviewed-by: default avatarDominic Battré <battre@chromium.org>
Cr-Commit-Position: refs/heads/master@{#843640}
parent ab161e05
...@@ -101,10 +101,15 @@ void FormDataAndroid::UpdateFieldTypes(const FormStructure& form_structure) { ...@@ -101,10 +101,15 @@ void FormDataAndroid::UpdateFieldTypes(const FormStructure& form_structure) {
auto form_field_data_android = fields_.begin(); auto form_field_data_android = fields_.begin();
for (const auto& autofill_field : form_structure) { for (const auto& autofill_field : form_structure) {
DCHECK(form_field_data_android->get()->SimilarFieldAs(*autofill_field)); DCHECK(form_field_data_android->get()->SimilarFieldAs(*autofill_field));
std::vector<AutofillType> server_predictions;
for (const auto& prediction : autofill_field->server_predictions()) {
server_predictions.emplace_back(
static_cast<ServerFieldType>(prediction.type()));
}
form_field_data_android->get()->UpdateAutofillTypes( form_field_data_android->get()->UpdateAutofillTypes(
AutofillType(autofill_field->heuristic_type()), AutofillType(autofill_field->heuristic_type()),
AutofillType(autofill_field->server_type()), AutofillType(autofill_field->server_type()),
autofill_field->ComputedType()); autofill_field->ComputedType(), server_predictions);
if (++form_field_data_android == fields_.end()) if (++form_field_data_android == fields_.end())
break; break;
} }
......
...@@ -21,9 +21,28 @@ using base::android::ToJavaArrayOfStrings; ...@@ -21,9 +21,28 @@ using base::android::ToJavaArrayOfStrings;
namespace autofill { namespace autofill {
namespace {
base::android::ScopedJavaLocalRef<jobjectArray> ToJavaArrayOfPredictionString(
JNIEnv* env,
const std::vector<AutofillType>& server_predictions) {
if (!server_predictions.empty()) {
std::vector<std::string> server_prediction_array;
server_prediction_array.reserve(server_predictions.size());
for (const auto& p : server_predictions) {
server_prediction_array.emplace_back(p.ToString());
}
return ToJavaArrayOfStrings(env, server_prediction_array);
}
return nullptr;
}
} // namespace
FormFieldDataAndroid::FormFieldDataAndroid(FormFieldData* field) FormFieldDataAndroid::FormFieldDataAndroid(FormFieldData* field)
: heuristic_type_(AutofillType(UNKNOWN_TYPE)), field_ptr_(field) {} : heuristic_type_(AutofillType(UNKNOWN_TYPE)), field_ptr_(field) {}
FormFieldDataAndroid::~FormFieldDataAndroid() = default;
ScopedJavaLocalRef<jobject> FormFieldDataAndroid::GetJavaPeer() { ScopedJavaLocalRef<jobject> FormFieldDataAndroid::GetJavaPeer() {
JNIEnv* env = AttachCurrentThread(); JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
...@@ -51,10 +70,12 @@ ScopedJavaLocalRef<jobject> FormFieldDataAndroid::GetJavaPeer() { ...@@ -51,10 +70,12 @@ ScopedJavaLocalRef<jobject> FormFieldDataAndroid::GetJavaPeer() {
jheuristic_type = jheuristic_type =
ConvertUTF8ToJavaString(env, heuristic_type_.ToString()); ConvertUTF8ToJavaString(env, heuristic_type_.ToString());
} }
ScopedJavaLocalRef<jstring> jserver_type; ScopedJavaLocalRef<jstring> jserver_type =
jserver_type = ConvertUTF8ToJavaString(env, server_type_.ToString()); ConvertUTF8ToJavaString(env, server_type_.ToString());
ScopedJavaLocalRef<jstring> jcomputed_type; ScopedJavaLocalRef<jstring> jcomputed_type =
jcomputed_type = ConvertUTF8ToJavaString(env, computed_type_.ToString()); ConvertUTF8ToJavaString(env, computed_type_.ToString());
ScopedJavaLocalRef<jobjectArray> jserver_predictions =
ToJavaArrayOfPredictionString(env, server_predictions_);
ScopedJavaLocalRef<jobjectArray> jdatalist_values = ScopedJavaLocalRef<jobjectArray> jdatalist_values =
ToJavaArrayOfStrings(env, field_ptr_->datalist_values); ToJavaArrayOfStrings(env, field_ptr_->datalist_values);
...@@ -66,10 +87,10 @@ ScopedJavaLocalRef<jobject> FormFieldDataAndroid::GetJavaPeer() { ...@@ -66,10 +87,10 @@ ScopedJavaLocalRef<jobject> FormFieldDataAndroid::GetJavaPeer() {
field_ptr_->should_autocomplete, jplaceholder, jtype, jid, field_ptr_->should_autocomplete, jplaceholder, jtype, jid,
joption_values, joption_contents, IsCheckable(field_ptr_->check_status), joption_values, joption_contents, IsCheckable(field_ptr_->check_status),
IsChecked(field_ptr_->check_status), field_ptr_->max_length, IsChecked(field_ptr_->check_status), field_ptr_->max_length,
jheuristic_type, jserver_type, jcomputed_type, field_ptr_->bounds.x(), jheuristic_type, jserver_type, jcomputed_type, jserver_predictions,
field_ptr_->bounds.y(), field_ptr_->bounds.right(), field_ptr_->bounds.x(), field_ptr_->bounds.y(),
field_ptr_->bounds.bottom(), jdatalist_values, jdatalist_labels, field_ptr_->bounds.right(), field_ptr_->bounds.bottom(),
field_ptr_->IsVisible()); jdatalist_values, jdatalist_labels, field_ptr_->IsVisible());
java_ref_ = JavaObjectWeakGlobalRef(env, obj); java_ref_ = JavaObjectWeakGlobalRef(env, obj);
} }
return obj; return obj;
...@@ -113,10 +134,12 @@ bool FormFieldDataAndroid::SimilarFieldAs(const FormFieldData& field) const { ...@@ -113,10 +134,12 @@ bool FormFieldDataAndroid::SimilarFieldAs(const FormFieldData& field) const {
void FormFieldDataAndroid::UpdateAutofillTypes( void FormFieldDataAndroid::UpdateAutofillTypes(
const AutofillType& heuristic_type, const AutofillType& heuristic_type,
const AutofillType& server_type, const AutofillType& server_type,
const AutofillType& computed_type) { const AutofillType& computed_type,
const std::vector<AutofillType>& server_predictions) {
heuristic_type_ = heuristic_type; heuristic_type_ = heuristic_type;
server_type_ = server_type; server_type_ = server_type;
computed_type_ = computed_type; computed_type_ = computed_type;
server_predictions_ = server_predictions;
// Java peer isn't available when this object is instantiated, update to // Java peer isn't available when this object is instantiated, update to
// Java peer if the prediction arrives later. // Java peer if the prediction arrives later.
...@@ -125,12 +148,15 @@ void FormFieldDataAndroid::UpdateAutofillTypes( ...@@ -125,12 +148,15 @@ void FormFieldDataAndroid::UpdateAutofillTypes(
if (obj.is_null()) if (obj.is_null())
return; return;
ScopedJavaLocalRef<jstring> jserver_type; ScopedJavaLocalRef<jstring> jserver_type =
jserver_type = ConvertUTF8ToJavaString(env, server_type_.ToString()); ConvertUTF8ToJavaString(env, server_type_.ToString());
ScopedJavaLocalRef<jstring> jcomputed_type; ScopedJavaLocalRef<jstring> jcomputed_type =
jcomputed_type = ConvertUTF8ToJavaString(env, computed_type_.ToString()); ConvertUTF8ToJavaString(env, computed_type_.ToString());
ScopedJavaLocalRef<jobjectArray> jserver_predictions =
ToJavaArrayOfPredictionString(env, server_predictions_);
Java_FormFieldData_updateFieldTypes(env, obj, jserver_type, jcomputed_type); Java_FormFieldData_updateFieldTypes(env, obj, jserver_type, jcomputed_type,
jserver_predictions);
} }
} // namespace autofill } // namespace autofill
...@@ -16,8 +16,8 @@ namespace autofill { ...@@ -16,8 +16,8 @@ namespace autofill {
// autofill::FormFieldData available in Java. // autofill::FormFieldData available in Java.
class FormFieldDataAndroid { class FormFieldDataAndroid {
public: public:
FormFieldDataAndroid(FormFieldData* field); explicit FormFieldDataAndroid(FormFieldData* field);
virtual ~FormFieldDataAndroid() {} virtual ~FormFieldDataAndroid();
base::android::ScopedJavaLocalRef<jobject> GetJavaPeer(); base::android::ScopedJavaLocalRef<jobject> GetJavaPeer();
void GetValue(); void GetValue();
...@@ -25,12 +25,14 @@ class FormFieldDataAndroid { ...@@ -25,12 +25,14 @@ class FormFieldDataAndroid {
bool SimilarFieldAs(const FormFieldData& field) const; bool SimilarFieldAs(const FormFieldData& field) const;
void UpdateAutofillTypes(const AutofillType& heuristic_type, void UpdateAutofillTypes(const AutofillType& heuristic_type,
const AutofillType& server_type, const AutofillType& server_type,
const AutofillType& computed_type); const AutofillType& computed_type,
const std::vector<AutofillType>& server_predictions);
private: private:
AutofillType heuristic_type_; AutofillType heuristic_type_;
AutofillType server_type_; AutofillType server_type_;
AutofillType computed_type_; AutofillType computed_type_;
std::vector<AutofillType> server_predictions_;
// Not owned. // Not owned.
FormFieldData* field_ptr_; FormFieldData* field_ptr_;
......
...@@ -138,8 +138,13 @@ public class AutofillProvider { ...@@ -138,8 +138,13 @@ public class AutofillProvider {
if (isQueryServerFieldTypesEnabled()) { if (isQueryServerFieldTypesEnabled()) {
builder.addAttribute("crowdsourcing-autofill-hints", field.getServerType()); builder.addAttribute("crowdsourcing-autofill-hints", field.getServerType());
builder.addAttribute("computed-autofill-hints", field.getComputedType()); builder.addAttribute("computed-autofill-hints", field.getComputedType());
// Compose multiple predictions to a string separated by ','.
String[] predictions = field.getServerPredictions();
if (predictions != null && predictions.length > 0) {
builder.addAttribute("crowdsourcing-predictions-autofill-hints",
String.join(",", predictions));
}
} }
switch (field.getControlType()) { switch (field.getControlType()) {
case FormFieldData.ControlType.LIST: case FormFieldData.ControlType.LIST:
child.setAutofillType(View.AUTOFILL_TYPE_LIST); child.setAutofillType(View.AUTOFILL_TYPE_LIST);
...@@ -281,8 +286,8 @@ public class AutofillProvider { ...@@ -281,8 +286,8 @@ public class AutofillProvider {
if (success) { if (success) {
ArrayList<ViewType> viewTypes = new ArrayList<ViewType>(); ArrayList<ViewType> viewTypes = new ArrayList<ViewType>();
for (FormFieldData field : mFormData.mFields) { for (FormFieldData field : mFormData.mFields) {
viewTypes.add(new ViewType( viewTypes.add(new ViewType(field.getAutofillId(), field.getServerType(),
field.getAutofillId(), field.getServerType(), field.getComputedType())); field.getComputedType(), field.getServerPredictions()));
} }
mAutofillHintsService.onViewTypeAvailable(viewTypes); mAutofillHintsService.onViewTypeAvailable(viewTypes);
} else { } else {
......
...@@ -68,14 +68,15 @@ public class FormFieldData { ...@@ -68,14 +68,15 @@ public class FormFieldData {
// after the object instantiated. // after the object instantiated.
private String mServerType; private String mServerType;
private String mComputedType; private String mComputedType;
private String[] mServerPredictions;
private AutofillId mAutofillId; private AutofillId mAutofillId;
private FormFieldData(String name, String label, String value, String autocompleteAttr, private FormFieldData(String name, String label, String value, String autocompleteAttr,
boolean shouldAutocomplete, String placeholder, String type, String id, boolean shouldAutocomplete, String placeholder, String type, String id,
String[] optionValues, String[] optionContents, boolean isCheckField, boolean isChecked, String[] optionValues, String[] optionContents, boolean isCheckField, boolean isChecked,
int maxLength, String heuristicType, String serverType, String computedType, float left, int maxLength, String heuristicType, String serverType, String computedType,
float top, float right, float bottom, String[] datalistValues, String[] datalistLabels, String[] serverPredictions, float left, float top, float right, float bottom,
boolean visible) { String[] datalistValues, String[] datalistLabels, boolean visible) {
mName = name; mName = name;
mLabel = label; mLabel = label;
mValue = value; mValue = value;
...@@ -101,6 +102,7 @@ public class FormFieldData { ...@@ -101,6 +102,7 @@ public class FormFieldData {
mMaxLength = maxLength; mMaxLength = maxLength;
mHeuristicType = heuristicType; mHeuristicType = heuristicType;
mServerType = serverType; mServerType = serverType;
mServerPredictions = serverPredictions;
mComputedType = computedType; mComputedType = computedType;
mBounds = new RectF(left, top, right, bottom); mBounds = new RectF(left, top, right, bottom);
mVisible = visible; mVisible = visible;
...@@ -147,9 +149,11 @@ public class FormFieldData { ...@@ -147,9 +149,11 @@ public class FormFieldData {
} }
@CalledByNative @CalledByNative
private void updateFieldTypes(String serverType, String computedType) { private void updateFieldTypes(
String serverType, String computedType, String[] serverPredictions) {
mServerType = serverType; mServerType = serverType;
mComputedType = computedType; mComputedType = computedType;
mServerPredictions = serverPredictions;
} }
public String getServerType() { public String getServerType() {
...@@ -160,6 +164,10 @@ public class FormFieldData { ...@@ -160,6 +164,10 @@ public class FormFieldData {
return mComputedType; return mComputedType;
} }
public String[] getServerPredictions() {
return mServerPredictions;
}
@CalledByNative @CalledByNative
public boolean isChecked() { public boolean isChecked() {
return mIsChecked; return mIsChecked;
...@@ -188,11 +196,11 @@ public class FormFieldData { ...@@ -188,11 +196,11 @@ public class FormFieldData {
String autocompleteAttr, boolean shouldAutocomplete, String placeholder, String type, String autocompleteAttr, boolean shouldAutocomplete, String placeholder, String type,
String id, String[] optionValues, String[] optionContents, boolean isCheckField, String id, String[] optionValues, String[] optionContents, boolean isCheckField,
boolean isChecked, int maxLength, String heuristicType, String serverType, boolean isChecked, int maxLength, String heuristicType, String serverType,
String computedType, float left, float top, float right, float bottom, String computedType, String[] serverPredictions, float left, float top, float right,
String[] datalistValues, String[] datalistLabels, boolean visible) { float bottom, String[] datalistValues, String[] datalistLabels, boolean visible) {
return new FormFieldData(name, label, value, autocompleteAttr, shouldAutocomplete, return new FormFieldData(name, label, value, autocompleteAttr, shouldAutocomplete,
placeholder, type, id, optionValues, optionContents, isCheckField, isChecked, placeholder, type, id, optionValues, optionContents, isCheckField, isChecked,
maxLength, heuristicType, serverType, computedType, left, top, right, bottom, maxLength, heuristicType, serverType, computedType, serverPredictions, left, top,
datalistValues, datalistLabels, visible); right, bottom, datalistValues, datalistLabels, visible);
} }
} }
...@@ -43,7 +43,11 @@ ...@@ -43,7 +43,11 @@
```java ```java
public void onViewTypeAvailable(List<ViewType> viewTypeList) { public void onViewTypeAvailable(List<ViewType> viewTypeList) {
for(ViewType viewType : viewTypeList) { for(ViewType viewType : viewTypeList) {
Log.d("MyAutofillService", viewType.mAutofillId.toString() + ":" + viewType.mType); if (viewType.getServerPredictions() ! = null) {
// Uses server predictions if they are available.
} else {
// otherwise, uses viewType.mServerType.
}
} }
} }
``` ```
...@@ -14,6 +14,9 @@ import org.chromium.base.annotations.VerifiesOnO; ...@@ -14,6 +14,9 @@ import org.chromium.base.annotations.VerifiesOnO;
/** /**
* This class is used to send the server and computed view type to the autofill service. * This class is used to send the server and computed view type to the autofill service.
* The valid types are listed in the two FieldTypeToStringPiece() functions in
* components/autofill/core/browser/field_types.cc. Note that the list of possibly returned strings
* can and will change in the future.
*/ */
@TargetApi(Build.VERSION_CODES.O) @TargetApi(Build.VERSION_CODES.O)
@VerifiesOnO @VerifiesOnO
...@@ -24,17 +27,17 @@ public class ViewType implements Parcelable { ...@@ -24,17 +27,17 @@ public class ViewType implements Parcelable {
public final AutofillId mAutofillId; public final AutofillId mAutofillId;
/** /**
* The type from Chrome autofill server. The valid types are listed in the two * The type from Chrome autofill server.
* FieldTypeToStringPiece() functions in components/autofill/core/browser/field_types.cc. Note
* that the list of possibly returned strings can and will change in the future.
*/ */
public final String mServerType; public final String mServerType;
/** /**
* The type computed overall type. The valid types types are the same as for mServerType. * The type computed overall type. The valid types are the same as for mServerType.
*/ */
public final String mComputedType; public final String mComputedType;
private String[] mServerPredictions;
public static final Parcelable.Creator<ViewType> CREATOR = new Parcelable.Creator<ViewType>() { public static final Parcelable.Creator<ViewType> CREATOR = new Parcelable.Creator<ViewType>() {
@Override @Override
public ViewType createFromParcel(Parcel in) { public ViewType createFromParcel(Parcel in) {
...@@ -47,17 +50,21 @@ public class ViewType implements Parcelable { ...@@ -47,17 +50,21 @@ public class ViewType implements Parcelable {
} }
}; };
public ViewType(AutofillId id, String serverType, String computedType) { public ViewType(
AutofillId id, String serverType, String computedType, String[] serverPredictions) {
mAutofillId = id; mAutofillId = id;
mServerType = serverType; mServerType = serverType;
mComputedType = computedType; mComputedType = computedType;
mServerPredictions = serverPredictions;
} }
private ViewType(Parcel in) { private ViewType(Parcel in) {
mAutofillId = AutofillId.CREATOR.createFromParcel(in); mAutofillId = AutofillId.CREATOR.createFromParcel(in);
mServerType = in.readString(); mServerType = in.readString();
mComputedType = in.readString(); mComputedType = in.readString();
in.readStringArray(mServerPredictions);
} }
@Override @Override
public int describeContents() { public int describeContents() {
return 0; return 0;
...@@ -68,5 +75,14 @@ public class ViewType implements Parcelable { ...@@ -68,5 +75,14 @@ public class ViewType implements Parcelable {
mAutofillId.writeToParcel(parcel, flags); mAutofillId.writeToParcel(parcel, flags);
parcel.writeString(mServerType); parcel.writeString(mServerType);
parcel.writeString(mComputedType); parcel.writeString(mComputedType);
parcel.writeStringArray(mServerPredictions);
}
/**
* @return the server predictions, they are in the order of the confidence. The mServerType
* shall be used if the server predictions aren't available.
*/
public String[] getServerPredictions() {
return mServerPredictions;
} }
} }
...@@ -83,11 +83,11 @@ public class AutofillProviderTest { ...@@ -83,11 +83,11 @@ public class AutofillProviderTest {
public void testTransformFormFieldToContainViewCoordinates() { public void testTransformFormFieldToContainViewCoordinates() {
ArrayList<FormFieldData> fields = new ArrayList<FormFieldData>(1); ArrayList<FormFieldData> fields = new ArrayList<FormFieldData>(1);
fields.add(FormFieldData.createFormFieldData(null, null, null, null, false, null, null, fields.add(FormFieldData.createFormFieldData(null, null, null, null, false, null, null,
null, null, null, false, false, 0, null, null, null, 10 /* left */, 20 /* top */, null, null, null, false, false, 0, null, null, null, null, 10 /* left */,
300 /* right */, 60 /*bottom*/, null, null, true)); 20 /* top */, 300 /* right */, 60 /*bottom*/, null, null, true));
fields.add(FormFieldData.createFormFieldData(null, null, null, null, false, null, null, fields.add(FormFieldData.createFormFieldData(null, null, null, null, false, null, null,
null, null, null, false, false, 0, null, null, null, 20 /* left */, 100 /* top */, null, null, null, false, false, 0, null, null, null, null, 20 /* left */,
400 /* right */, 200 /*bottom*/, null, null, true)); 100 /* top */, 400 /* right */, 200 /*bottom*/, null, null, true));
FormData formData = new FormData(null, null, fields); FormData formData = new FormData(null, null, fields);
mAutofillProvider.transformFormFieldToContainViewCoordinates(formData); mAutofillProvider.transformFormFieldToContainViewCoordinates(formData);
RectF result = formData.mFields.get(0).getBoundsInContainerViewCoordinates(); RectF result = formData.mFields.get(0).getBoundsInContainerViewCoordinates();
......
...@@ -85,6 +85,58 @@ JNI_AutofillProviderTestHelper_SimulateMainFrameAutofillServerResponseForTesting ...@@ -85,6 +85,58 @@ JNI_AutofillProviderTestHelper_SimulateMainFrameAutofillServerResponseForTesting
return true; return true;
} }
static jboolean
JNI_AutofillProviderTestHelper_SimulateMainFramePredictionsAutofillServerResponseForTesting(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& jweb_contents,
const base::android::JavaParamRef<jobjectArray>& jfield_ids,
const base::android::JavaParamRef<jobjectArray>& jfield_types) {
std::vector<base::string16> field_ids;
base::android::AppendJavaStringArrayToStringVector(env, jfield_ids,
&field_ids);
std::vector<std::vector<int>> field_types;
base::android::JavaArrayOfIntArrayToIntVector(env, jfield_types,
&field_types);
AutofillHandler* autofill_handler = ToMainFrameAutofillHandler(jweb_contents);
const std::map<FormRendererId, std::unique_ptr<FormStructure>>&
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::AddFieldPredictionsToForm(
form_field_data, 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;
}
static void static void
JNI_AutofillProviderTestHelper_SimulateMainFrameAutofillQueryFailedForTesting( JNI_AutofillProviderTestHelper_SimulateMainFrameAutofillQueryFailedForTesting(
JNIEnv* env, JNIEnv* env,
......
...@@ -19,6 +19,9 @@ import org.chromium.content_public.browser.WebContents; ...@@ -19,6 +19,9 @@ import org.chromium.content_public.browser.WebContents;
@TargetApi(Build.VERSION_CODES.O) @TargetApi(Build.VERSION_CODES.O)
@JNINamespace("autofill") @JNINamespace("autofill")
public class AutofillProviderTestHelper { public class AutofillProviderTestHelper {
/**
* Simulate the primary server type only.
*/
public static boolean simulateMainFrameAutofillServerResponseForTesting( public static boolean simulateMainFrameAutofillServerResponseForTesting(
WebContents webContents, String[] fieldIds, int[] fieldTypes) { WebContents webContents, String[] fieldIds, int[] fieldTypes) {
return AutofillProviderTestHelperJni.get() return AutofillProviderTestHelperJni.get()
...@@ -26,6 +29,16 @@ public class AutofillProviderTestHelper { ...@@ -26,6 +29,16 @@ public class AutofillProviderTestHelper {
webContents, fieldIds, fieldTypes); webContents, fieldIds, fieldTypes);
} }
/**
* Simulate the server predictions, the first prediction will be set as primary server type.
*/
public static boolean simulateMainFramePredictionsAutofillServerResponseForTesting(
WebContents webContents, String[] fieldIds, int[][] fieldTypes) {
return AutofillProviderTestHelperJni.get()
.simulateMainFramePredictionsAutofillServerResponseForTesting(
webContents, fieldIds, fieldTypes);
}
public static void simulateMainFrameAutofillQueryFailedForTesting(WebContents webContents) { public static void simulateMainFrameAutofillQueryFailedForTesting(WebContents webContents) {
AutofillProviderTestHelperJni.get().simulateMainFrameAutofillQueryFailedForTesting( AutofillProviderTestHelperJni.get().simulateMainFrameAutofillQueryFailedForTesting(
webContents); webContents);
...@@ -35,6 +48,8 @@ public class AutofillProviderTestHelper { ...@@ -35,6 +48,8 @@ public class AutofillProviderTestHelper {
interface Natives { interface Natives {
boolean simulateMainFrameAutofillServerResponseForTesting( boolean simulateMainFrameAutofillServerResponseForTesting(
WebContents webContents, String[] fieldIds, int[] fieldTypes); WebContents webContents, String[] fieldIds, int[] fieldTypes);
boolean simulateMainFramePredictionsAutofillServerResponseForTesting(
WebContents webContents, String[] fieldIds, int[][] fieldTypes);
void simulateMainFrameAutofillQueryFailedForTesting(WebContents webContents); void simulateMainFrameAutofillQueryFailedForTesting(WebContents webContents);
} }
} }
...@@ -909,7 +909,7 @@ std::vector<FormSignature> GetEncodedSignatures( ...@@ -909,7 +909,7 @@ std::vector<FormSignature> GetEncodedSignatures(
} }
void AddFieldSuggestionToForm( void AddFieldSuggestionToForm(
autofill::FormFieldData field_data, const autofill::FormFieldData& field_data,
ServerFieldType field_type, ServerFieldType field_type,
::autofill::AutofillQueryResponse_FormSuggestion* form_suggestion) { ::autofill::AutofillQueryResponse_FormSuggestion* form_suggestion) {
auto* field_suggestion = form_suggestion->add_field_suggestions(); auto* field_suggestion = form_suggestion->add_field_suggestions();
...@@ -918,5 +918,32 @@ void AddFieldSuggestionToForm( ...@@ -918,5 +918,32 @@ void AddFieldSuggestionToForm(
field_suggestion->set_primary_type_prediction(field_type); field_suggestion->set_primary_type_prediction(field_type);
} }
void AddFieldPredictionsToForm(
const autofill::FormFieldData& field_data,
const std::vector<int>& field_types,
::autofill::AutofillQueryResponse_FormSuggestion* form_suggestion) {
std::vector<ServerFieldType> types;
for (auto type : field_types) {
types.emplace_back(static_cast<ServerFieldType>(type));
}
AddFieldPredictionsToForm(field_data, types, form_suggestion);
}
void AddFieldPredictionsToForm(
const autofill::FormFieldData& field_data,
const std::vector<ServerFieldType>& field_types,
::autofill::AutofillQueryResponse_FormSuggestion* form_suggestion) {
// According to api_v1.proto, the first element is always set to primary 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_types.begin());
for (auto field_type : field_types) {
AutofillQueryResponse_FormSuggestion_FieldSuggestion_FieldPrediction*
prediction = field_suggestion->add_predictions();
prediction->set_type(field_type);
}
}
} // namespace test } // namespace test
} // namespace autofill } // namespace autofill
...@@ -338,10 +338,22 @@ std::string NextYear(); ...@@ -338,10 +338,22 @@ std::string NextYear();
std::string TenYearsFromNow(); std::string TenYearsFromNow();
void AddFieldSuggestionToForm( void AddFieldSuggestionToForm(
autofill::FormFieldData field_data, const autofill::FormFieldData& field_data,
ServerFieldType field_type, ServerFieldType field_type,
::autofill::AutofillQueryResponse_FormSuggestion* form_suggestion); ::autofill::AutofillQueryResponse_FormSuggestion* form_suggestion);
// Adds |field_types| predictions of |field_data| to |form_suggestion| query
// response. Assumes int type can be cast to ServerFieldType.
void AddFieldPredictionsToForm(
const autofill::FormFieldData& field_data,
const std::vector<int>& field_types,
::autofill::AutofillQueryResponse_FormSuggestion* form_suggestion);
void AddFieldPredictionsToForm(
const autofill::FormFieldData& field_data,
const std::vector<ServerFieldType>& field_types,
::autofill::AutofillQueryResponse_FormSuggestion* form_suggestion);
} // namespace test } // namespace test
} // namespace autofill } // namespace autofill
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment