Add autofill server prediction log events when predicting field types
We are working on improving the UKM recording of Autofill and better understand the Autofill performance from the UKM events. We are creating four types of log events from four field type prediction, local heuristic, autofill server, autocomplete and rationalizer. We log various of interesting field types, heuristic_type, heuristic_default_type,..., server_type, html_type, overall_type ... into UKM. This CL is working on adding the autofill crowdsourced server prediction log event for the fields on the form. Autofill UKM Data Structure doc: https://docs.google.com/document/d/1Tgp5Op4tGhf03lYT4CfWr5f_FjvcpqWhqY0qPJcR-cM/edit#heading=h.k5jx6iluw4yt https://docs.google.com/document/d/1ZH0JbL6bES3cD4KqZWsGR6n8I-rhnkx6no6nQOgYq5w/. Bug: 1325851 Change-Id: I4a80f1883c44cc6a1099a33a1ab2b087fb53f662 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4167412 Reviewed-by: Dominic Battré <battre@chromium.org> Reviewed-by: Christoph Schwering <schwering@google.com> Commit-Queue: Lan Wei <lanwei@chromium.org> Reviewed-by: Robert Kaplow <rkaplow@chromium.org> Cr-Commit-Position: refs/heads/main@{#1096507}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
e8ebd45aa0
commit
dcaf205e47
components/autofill/core/browser
tools/metrics
@ -48,7 +48,7 @@ bool AreCollapsibleLogEvents(const AutofillField::FieldLogEventType& event1,
|
||||
}
|
||||
|
||||
static_assert(
|
||||
absl::variant_size<AutofillField::FieldLogEventType>() == 7,
|
||||
absl::variant_size<AutofillField::FieldLogEventType>() == 8,
|
||||
"If you add a new field event type, you need to update this function");
|
||||
|
||||
if (absl::holds_alternative<absl::monostate>(event1)) {
|
||||
@ -86,6 +86,11 @@ bool AreCollapsibleLogEvents(const AutofillField::FieldLogEventType& event1,
|
||||
return AreCollapsible(absl::get<E>(event1), absl::get<E>(event2));
|
||||
}
|
||||
|
||||
if (absl::holds_alternative<ServerPredictionFieldLogEvent>(event1)) {
|
||||
using E = ServerPredictionFieldLogEvent;
|
||||
return AreCollapsible(absl::get<E>(event1), absl::get<E>(event2));
|
||||
}
|
||||
|
||||
NOTREACHED();
|
||||
return false;
|
||||
}
|
||||
|
@ -38,7 +38,8 @@ class AutofillField : public FormFieldData {
|
||||
FillFieldLogEvent,
|
||||
TypingFieldLogEvent,
|
||||
HeuristicPredictionFieldLogEvent,
|
||||
AutocompleteAttributeFieldLogEvent>;
|
||||
AutocompleteAttributeFieldLogEvent,
|
||||
ServerPredictionFieldLogEvent>;
|
||||
|
||||
AutofillField();
|
||||
explicit AutofillField(const FormFieldData& field);
|
||||
|
@ -863,12 +863,34 @@ class BrowserAutofillManagerTest : public testing::Test {
|
||||
expected.rank_in_field_signature_group)));
|
||||
}
|
||||
|
||||
// Matches a ServerPredictionFieldLogEvent by equality of fields.
|
||||
auto Equal(const ServerPredictionFieldLogEvent& expected) {
|
||||
return VariantWith<ServerPredictionFieldLogEvent>(AllOf(
|
||||
Field("server_type1", &ServerPredictionFieldLogEvent::server_type1,
|
||||
expected.server_type1),
|
||||
Field("prediction_source1",
|
||||
&ServerPredictionFieldLogEvent::prediction_source1,
|
||||
expected.prediction_source1),
|
||||
Field("server_type2", &ServerPredictionFieldLogEvent::server_type2,
|
||||
expected.server_type2),
|
||||
Field("prediction_source2",
|
||||
&ServerPredictionFieldLogEvent::prediction_source2,
|
||||
expected.prediction_source2),
|
||||
Field(
|
||||
"server_type_prediction_is_override",
|
||||
&ServerPredictionFieldLogEvent::server_type_prediction_is_override,
|
||||
expected.server_type_prediction_is_override),
|
||||
Field("rank_in_field_signature_group",
|
||||
&ServerPredictionFieldLogEvent::rank_in_field_signature_group,
|
||||
expected.rank_in_field_signature_group)));
|
||||
}
|
||||
|
||||
// Matches a vector of FieldLogEventType objects by equality of fields of each
|
||||
// log event type.
|
||||
auto ArrayEquals(
|
||||
const std::vector<AutofillField::FieldLogEventType>& expected) {
|
||||
static_assert(
|
||||
absl::variant_size<AutofillField::FieldLogEventType>() == 7,
|
||||
absl::variant_size<AutofillField::FieldLogEventType>() == 8,
|
||||
"If you add a new field event type, you need to update this function");
|
||||
std::vector<Matcher<AutofillField::FieldLogEventType>> matchers;
|
||||
for (const auto& event : expected) {
|
||||
@ -889,6 +911,10 @@ class BrowserAutofillManagerTest : public testing::Test {
|
||||
event)) {
|
||||
matchers.push_back(
|
||||
Equal(absl::get<AutocompleteAttributeFieldLogEvent>(event)));
|
||||
} else if (absl::holds_alternative<ServerPredictionFieldLogEvent>(
|
||||
event)) {
|
||||
matchers.push_back(
|
||||
Equal(absl::get<ServerPredictionFieldLogEvent>(event)));
|
||||
} else {
|
||||
NOTREACHED();
|
||||
}
|
||||
@ -5945,6 +5971,120 @@ TEST_F(BrowserAutofillManagerWithLogEventsTest,
|
||||
}
|
||||
}
|
||||
|
||||
// Test that we record field log events correctly for autofill crowdsourced
|
||||
// server prediction.
|
||||
TEST_F(BrowserAutofillManagerWithLogEventsTest,
|
||||
LogEventsParseQueryResponseServerPrediction) {
|
||||
// Set up our form data.
|
||||
FormData form;
|
||||
form.host_frame = test::MakeLocalFrameToken();
|
||||
form.unique_renderer_id = test::MakeFormRendererId();
|
||||
form.name = u"MyForm";
|
||||
form.url = GURL("https://myform.com/form.html");
|
||||
form.action = GURL("https://myform.com/submit.html");
|
||||
FormFieldData field;
|
||||
test::CreateTestFormField(/*label=*/"Name", /*name=*/"name",
|
||||
/*value=*/"", /*type=*/"text", /*field=*/&field);
|
||||
form.fields.push_back(field);
|
||||
test::CreateTestFormField(/*label=*/"Street", /*name=*/"Street",
|
||||
/*value=*/"", /*type=*/"text", /*field=*/&field);
|
||||
form.fields.push_back(field);
|
||||
test::CreateTestFormField(/*label=*/"City", /*name=*/"city",
|
||||
/*value=*/"", /*type=*/"text", /*field=*/&field);
|
||||
form.fields.push_back(field);
|
||||
test::CreateTestFormField(/*label=*/"State", /*name=*/"state",
|
||||
/*value=*/"", /*type=*/"text", /*field=*/&field);
|
||||
form.fields.push_back(field);
|
||||
test::CreateTestFormField(/*label=*/"Postal Code", /*name=*/"zipcode",
|
||||
/*value=*/"", /*type=*/"text", /*field=*/&field);
|
||||
form.fields.push_back(field);
|
||||
// Simulate having seen this form on page load.
|
||||
// |form_structure_instance| will be owned by |browser_autofill_manager_|.
|
||||
auto form_structure_instance = std::make_unique<FormStructure>(form);
|
||||
// This pointer is valid as long as autofill manager lives.
|
||||
FormStructure* form_structure = form_structure_instance.get();
|
||||
form_structure->DetermineHeuristicTypes(nullptr, nullptr);
|
||||
browser_autofill_manager_->AddSeenFormStructure(
|
||||
std::move(form_structure_instance));
|
||||
|
||||
// Make API response with suggestions.
|
||||
AutofillQueryResponse response;
|
||||
AutofillQueryResponse::FormSuggestion* form_suggestion;
|
||||
// Set suggestions for form.
|
||||
form_suggestion = response.add_form_suggestions();
|
||||
autofill::test::AddFieldPredictionsToForm(
|
||||
form.fields[0],
|
||||
{test::CreateFieldPrediction(NAME_FIRST,
|
||||
FieldPrediction::SOURCE_AUTOFILL_DEFAULT),
|
||||
test::CreateFieldPrediction(USERNAME,
|
||||
FieldPrediction::SOURCE_PASSWORDS_DEFAULT)},
|
||||
form_suggestion);
|
||||
autofill::test::AddFieldPredictionsToForm(
|
||||
form.fields[1],
|
||||
{test::CreateFieldPrediction(ADDRESS_HOME_LINE1,
|
||||
FieldPrediction::SOURCE_OVERRIDE)},
|
||||
form_suggestion);
|
||||
autofill::test::AddFieldPredictionToForm(form.fields[2], ADDRESS_HOME_CITY,
|
||||
form_suggestion);
|
||||
autofill::test::AddFieldPredictionToForm(form.fields[3], ADDRESS_HOME_STATE,
|
||||
form_suggestion);
|
||||
autofill::test::AddFieldPredictionToForm(form.fields[4], ADDRESS_HOME_ZIP,
|
||||
form_suggestion);
|
||||
|
||||
std::string response_string;
|
||||
ASSERT_TRUE(response.SerializeToString(&response_string));
|
||||
std::string encoded_response_string;
|
||||
base::Base64Encode(response_string, &encoded_response_string);
|
||||
|
||||
// Query autofill server for the field type prediction.
|
||||
browser_autofill_manager_->OnLoadedServerPredictionsForTest(
|
||||
encoded_response_string, test::GetEncodedSignatures(*form_structure));
|
||||
EXPECT_EQ(NAME_FIRST, form_structure->field(0)->Type().GetStorableType());
|
||||
EXPECT_EQ(ADDRESS_HOME_LINE1,
|
||||
form_structure->field(1)->Type().GetStorableType());
|
||||
EXPECT_EQ(ADDRESS_HOME_CITY,
|
||||
form_structure->field(2)->Type().GetStorableType());
|
||||
EXPECT_EQ(ADDRESS_HOME_STATE,
|
||||
form_structure->field(3)->Type().GetStorableType());
|
||||
EXPECT_EQ(ADDRESS_HOME_ZIP,
|
||||
form_structure->field(4)->Type().GetStorableType());
|
||||
|
||||
// Simulate form submission.
|
||||
FormSubmitted(form);
|
||||
|
||||
for (const auto& autofill_field_ptr : *form_structure) {
|
||||
SCOPED_TRACE(autofill_field_ptr->parseable_label());
|
||||
// All parsed fields share the same expected
|
||||
// HeuristicPredictionFieldLogEvent.
|
||||
std::vector<AutofillField::FieldLogEventType> expected_events =
|
||||
ToHeuristicFieldTypeEvents(autofill_field_ptr->heuristic_type());
|
||||
// The autofill server applies two predictions on the "Name" field.
|
||||
ServerFieldType server_type2 =
|
||||
autofill_field_ptr->parseable_label() == u"Name" ? USERNAME
|
||||
: NO_SERVER_DATA;
|
||||
FieldPrediction::Source prediction_source2 =
|
||||
autofill_field_ptr->parseable_label() == u"Name"
|
||||
? FieldPrediction::SOURCE_PASSWORDS_DEFAULT
|
||||
: FieldPrediction::SOURCE_UNSPECIFIED;
|
||||
// The server prediction overrides the type predicted by local heuristic on
|
||||
// the field of label "Street".
|
||||
bool server_type_prediction_is_override =
|
||||
autofill_field_ptr->parseable_label() == u"Street" ? true : false;
|
||||
expected_events.push_back(ServerPredictionFieldLogEvent{
|
||||
.server_type1 = autofill_field_ptr->server_type(),
|
||||
.prediction_source1 =
|
||||
autofill_field_ptr->server_predictions()[0].source(),
|
||||
.server_type2 = server_type2,
|
||||
.prediction_source2 = prediction_source2,
|
||||
.server_type_prediction_is_override =
|
||||
server_type_prediction_is_override,
|
||||
.rank_in_field_signature_group = 1,
|
||||
});
|
||||
EXPECT_THAT(autofill_field_ptr->field_log_events(),
|
||||
ArrayEquals(expected_events));
|
||||
}
|
||||
}
|
||||
|
||||
// Test that when Autocomplete is enabled and Autofill is disabled, form
|
||||
// submissions are still received by the SingleFieldFormFillRouter.
|
||||
TEST_F(BrowserAutofillManagerTest, FormSubmittedAutocompleteEnabled) {
|
||||
|
@ -581,6 +581,9 @@ void FormStructure::ProcessQueryResponse(
|
||||
|
||||
// Copy the field types into the actual form.
|
||||
for (FormStructure* form : forms) {
|
||||
// Fields can share the same field signature. This map records for each
|
||||
// signature how many fields with the same signature have been observed.
|
||||
std::map<FieldSignature, size_t> field_rank_map;
|
||||
for (auto& field : form->fields_) {
|
||||
// Get the field prediction for |form|'s signature and the |field|'s
|
||||
// host_form_signature. The former takes precedence over the latter.
|
||||
@ -619,6 +622,27 @@ void FormStructure::ProcessQueryResponse(
|
||||
|
||||
if (current_field->has_password_requirements())
|
||||
field->SetPasswordRequirements(current_field->password_requirements());
|
||||
|
||||
++field_rank_map[field->GetFieldSignature()];
|
||||
// Log the field type predicted from Autofill crowdsourced server.
|
||||
field->AppendLogEventIfNotRepeated(ServerPredictionFieldLogEvent{
|
||||
.server_type1 = field->server_type(),
|
||||
.prediction_source1 = field->server_predictions().empty()
|
||||
? FieldPrediction::SOURCE_UNSPECIFIED
|
||||
: field->server_predictions()[0].source(),
|
||||
.server_type2 =
|
||||
field->server_predictions().size() >= 2
|
||||
? ToSafeServerFieldType(field->server_predictions()[1].type(),
|
||||
NO_SERVER_DATA)
|
||||
: NO_SERVER_DATA,
|
||||
.prediction_source2 = field->server_predictions().size() >= 2
|
||||
? field->server_predictions()[1].source()
|
||||
: FieldPrediction::SOURCE_UNSPECIFIED,
|
||||
.server_type_prediction_is_override =
|
||||
field->server_type_prediction_is_override(),
|
||||
.rank_in_field_signature_group =
|
||||
field_rank_map[field->GetFieldSignature()],
|
||||
});
|
||||
}
|
||||
|
||||
AutofillMetrics::LogServerResponseHasDataForForm(base::ranges::any_of(
|
||||
@ -1330,7 +1354,7 @@ void FormStructure::LogDetermineHeuristicTypesMetrics() {
|
||||
void FormStructure::SetFieldTypesFromAutocompleteAttribute() {
|
||||
has_author_specified_types_ = false;
|
||||
has_author_specified_upi_vpa_hint_ = false;
|
||||
std::map<FieldSignature, size_t> field_rank_id_map;
|
||||
std::map<FieldSignature, size_t> field_rank_map;
|
||||
for (const std::unique_ptr<AutofillField>& field : fields_) {
|
||||
if (!field->parsed_autocomplete)
|
||||
continue;
|
||||
@ -1353,12 +1377,12 @@ void FormStructure::SetFieldTypesFromAutocompleteAttribute() {
|
||||
field->parsed_autocomplete->mode);
|
||||
|
||||
// Log the field type predicted from autocomplete attribute.
|
||||
++field_rank_id_map[field->GetFieldSignature()];
|
||||
++field_rank_map[field->GetFieldSignature()];
|
||||
field->AppendLogEventIfNotRepeated(AutocompleteAttributeFieldLogEvent{
|
||||
.html_type = field->parsed_autocomplete->field_type,
|
||||
.html_mode = field->parsed_autocomplete->mode,
|
||||
.rank_in_field_signature_group =
|
||||
field_rank_id_map[field->GetFieldSignature()],
|
||||
field_rank_map[field->GetFieldSignature()],
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -1396,7 +1420,7 @@ void FormStructure::ParseFieldTypesWithPatterns(PatternSource pattern_source,
|
||||
|
||||
// Fields can share the same field signature. This map records for each
|
||||
// signature how many fields with the same signature have been observed.
|
||||
std::map<FieldSignature, size_t> field_rank_id_map;
|
||||
std::map<FieldSignature, size_t> field_rank_map;
|
||||
for (const auto& field : fields_) {
|
||||
auto iter = field_type_map.find(field->global_id());
|
||||
if (iter == field_type_map.end())
|
||||
@ -1404,14 +1428,14 @@ void FormStructure::ParseFieldTypesWithPatterns(PatternSource pattern_source,
|
||||
const FieldCandidates& candidates = iter->second;
|
||||
field->set_heuristic_type(pattern_source, candidates.BestHeuristicType());
|
||||
|
||||
++field_rank_id_map[field->GetFieldSignature()];
|
||||
++field_rank_map[field->GetFieldSignature()];
|
||||
// Log the field type predicted from local heuristics.
|
||||
field->AppendLogEventIfNotRepeated(HeuristicPredictionFieldLogEvent{
|
||||
.field_type = field->heuristic_type(pattern_source),
|
||||
.pattern_source = pattern_source,
|
||||
.is_active_pattern_source = GetActivePatternSource() == pattern_source,
|
||||
.rank_in_field_signature_group =
|
||||
field_rank_id_map[field->GetFieldSignature()],
|
||||
field_rank_map[field->GetFieldSignature()],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -2508,6 +2508,11 @@ void AutofillMetrics::FormInteractionsUkmLogger::
|
||||
// TODO(crbug.com/1325851): Add a metric in |FieldInfo| UKM event to indicate
|
||||
// whether the user had any data available for the respective field type.
|
||||
|
||||
// If multiple fields have the same signature, this indicates the position
|
||||
// within this set of fields. This allows us to understand problems related
|
||||
// to duplicated field signatures.
|
||||
size_t rank_in_field_signature_group = 0;
|
||||
|
||||
// Field types from local heuristics prediction.
|
||||
// The field type from the active local heuristic pattern.
|
||||
ServerFieldType heuristic_type = UNKNOWN_TYPE;
|
||||
@ -2530,16 +2535,24 @@ void AutofillMetrics::FormInteractionsUkmLogger::
|
||||
HtmlFieldMode html_mode = HtmlFieldMode::kNone;
|
||||
HtmlFieldType html_type = HtmlFieldType::kUnrecognized;
|
||||
|
||||
// If multiple fields have the same signature, this indicates the position
|
||||
// within this set of fields. This allows us to understand problems related
|
||||
// to duplicated field signatures.
|
||||
size_t rank_in_field_signature_group = 0;
|
||||
// The field type predicted by the Autofill crowdsourced server from
|
||||
// majority voting.
|
||||
ServerFieldType server_type1 = NO_SERVER_DATA;
|
||||
FieldPrediction::Source prediction_source1 =
|
||||
FieldPrediction::SOURCE_UNSPECIFIED;
|
||||
ServerFieldType server_type2 = NO_SERVER_DATA;
|
||||
FieldPrediction::Source prediction_source2 =
|
||||
FieldPrediction::SOURCE_UNSPECIFIED;
|
||||
// This is an annotation for server predicted field types which indicates
|
||||
// that a manual override defines the server type.
|
||||
bool server_type_is_override = false;
|
||||
|
||||
bool had_heuristic_type = false;
|
||||
bool had_html_type = false;
|
||||
bool had_server_type = false;
|
||||
|
||||
for (const auto& log_event : field_log_events) {
|
||||
static_assert(absl::variant_size<AutofillField::FieldLogEventType>() == 7,
|
||||
static_assert(absl::variant_size<AutofillField::FieldLogEventType>() == 8,
|
||||
"When adding new variants check that this function does not "
|
||||
"need to be updated.");
|
||||
if (auto* event =
|
||||
@ -2611,6 +2624,16 @@ void AutofillMetrics::FormInteractionsUkmLogger::
|
||||
rank_in_field_signature_group = event->rank_in_field_signature_group;
|
||||
had_html_type = true;
|
||||
}
|
||||
|
||||
if (auto* event = absl::get_if<ServerPredictionFieldLogEvent>(&log_event)) {
|
||||
server_type1 = event->server_type1;
|
||||
prediction_source1 = event->prediction_source1;
|
||||
server_type2 = event->server_type2;
|
||||
prediction_source2 = event->prediction_source2;
|
||||
server_type_is_override = event->server_type_prediction_is_override;
|
||||
rank_in_field_signature_group = event->rank_in_field_signature_group;
|
||||
had_server_type = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (had_value_after_filling != OptionalBoolean::kUndefined ||
|
||||
@ -2674,6 +2697,14 @@ void AutofillMetrics::FormInteractionsUkmLogger::
|
||||
.SetHtmlFieldMode(static_cast<int>(html_mode));
|
||||
}
|
||||
|
||||
if (had_server_type) {
|
||||
builder.SetServerType1(server_type1)
|
||||
.SetServerPredictionSource1(prediction_source1)
|
||||
.SetServerType2(server_type2)
|
||||
.SetServerPredictionSource2(prediction_source2)
|
||||
.SetServerTypeIsOverride(server_type_is_override);
|
||||
}
|
||||
|
||||
if (rank_in_field_signature_group) {
|
||||
builder.SetRankInFieldSignatureGroup(rank_in_field_signature_group);
|
||||
}
|
||||
|
@ -10590,14 +10590,20 @@ TEST_F(AutofillMetricsFromLogEventsTest, AutofillFieldInfoMetrics_FieldType) {
|
||||
|
||||
AutofillQueryResponse response;
|
||||
auto* form_suggestion = response.add_form_suggestions();
|
||||
// Server response will match with autocomplete.
|
||||
AddFieldPredictionToForm(form.fields[0], NAME_LAST, form_suggestion);
|
||||
// Server response will NOT match with autocomplete.
|
||||
AddFieldPredictionToForm(form.fields[1], NAME_FIRST, form_suggestion);
|
||||
// Not logged.
|
||||
AddFieldPredictionToForm(form.fields[2], NAME_MIDDLE, form_suggestion);
|
||||
// Server response will have no data.
|
||||
AddFieldPredictionToForm(form.fields[3], NO_SERVER_DATA, form_suggestion);
|
||||
// The server type of each field predicted from autofill crowdsourced server.
|
||||
std::vector<ServerFieldType> server_types{
|
||||
// Server response will match with autocomplete.
|
||||
NAME_LAST,
|
||||
// Server response will NOT match with autocomplete.
|
||||
NAME_FIRST,
|
||||
// No autocomplete, server predicts a type from majority voting.
|
||||
NAME_MIDDLE,
|
||||
// Server response will have no data.
|
||||
NO_SERVER_DATA};
|
||||
// Set suggestions from server for the form.
|
||||
for (size_t i = 0; i < server_types.size(); ++i) {
|
||||
AddFieldPredictionToForm(form.fields[i], server_types[i], form_suggestion);
|
||||
}
|
||||
|
||||
std::string response_string = SerializeAndEncode(response);
|
||||
autofill_manager().OnLoadedServerPredictionsForTest(
|
||||
@ -10623,6 +10629,10 @@ TEST_F(AutofillMetricsFromLogEventsTest, AutofillFieldInfoMetrics_FieldType) {
|
||||
SCOPED_TRACE(testing::Message() << i);
|
||||
using UFIT = UkmFieldInfoType;
|
||||
const auto* const entry = entries[i];
|
||||
FieldPrediction::Source prediction_source =
|
||||
server_types[i] != NO_SERVER_DATA
|
||||
? FieldPrediction::SOURCE_AUTOFILL_DEFAULT
|
||||
: FieldPrediction::SOURCE_UNSPECIFIED;
|
||||
std::map<std::string, int64_t> expected = {
|
||||
{UFIT::kFormSessionIdentifierName,
|
||||
AutofillMetrics::FormGlobalIdToHash64Bit(form.global_id())},
|
||||
@ -10630,6 +10640,12 @@ TEST_F(AutofillMetricsFromLogEventsTest, AutofillFieldInfoMetrics_FieldType) {
|
||||
AutofillMetrics::FieldGlobalIdToHash64Bit(form.fields[i].global_id())},
|
||||
{UFIT::kFieldSignatureName,
|
||||
Collapse(CalculateFieldSignatureForField(form.fields[i])).value()},
|
||||
{UFIT::kServerType1Name, server_types[i]},
|
||||
{UFIT::kServerPredictionSource1Name, prediction_source},
|
||||
{UFIT::kServerType2Name, NO_SERVER_DATA},
|
||||
{UFIT::kServerPredictionSource2Name,
|
||||
FieldPrediction::SOURCE_UNSPECIFIED},
|
||||
{UFIT::kServerTypeIsOverrideName, false},
|
||||
{UFIT::kIsFocusableName, true},
|
||||
{UFIT::kRankInFieldSignatureGroupName, 1},
|
||||
{UFIT::kWasFocusedName, false},
|
||||
|
@ -87,4 +87,16 @@ bool AreCollapsible(const AutocompleteAttributeFieldLogEvent& event1,
|
||||
event2.rank_in_field_signature_group;
|
||||
}
|
||||
|
||||
bool AreCollapsible(const ServerPredictionFieldLogEvent& event1,
|
||||
const ServerPredictionFieldLogEvent& event2) {
|
||||
return event1.server_type1 == event2.server_type1 &&
|
||||
event1.prediction_source1 == event2.prediction_source1 &&
|
||||
event1.server_type2 == event2.server_type2 &&
|
||||
event1.prediction_source2 == event2.prediction_source2 &&
|
||||
event1.server_type_prediction_is_override ==
|
||||
event2.server_type_prediction_is_override &&
|
||||
event1.rank_in_field_signature_group ==
|
||||
event2.rank_in_field_signature_group;
|
||||
}
|
||||
|
||||
} // namespace autofill
|
||||
|
@ -14,6 +14,9 @@
|
||||
|
||||
namespace autofill {
|
||||
|
||||
using FieldPrediction =
|
||||
AutofillQueryResponse::FormSuggestion::FieldSuggestion::FieldPrediction;
|
||||
|
||||
// An identifier to connect the various sub-events of filling together.
|
||||
using FillEventId = base::IdTypeU32<class FillEventIdClass>;
|
||||
FillEventId GetNextFillEventId();
|
||||
@ -135,6 +138,22 @@ using AutocompleteAttributeFieldLogEvent =
|
||||
bool AreCollapsible(const AutocompleteAttributeFieldLogEvent& event1,
|
||||
const AutocompleteAttributeFieldLogEvent& event2);
|
||||
|
||||
// Predict the field type from Autofill server.
|
||||
template <typename IsRequired = void>
|
||||
struct ServerPredictionFieldLogEventImpl {
|
||||
ServerFieldType server_type1 = IsRequired();
|
||||
FieldPrediction::Source prediction_source1 = IsRequired();
|
||||
ServerFieldType server_type2 = IsRequired();
|
||||
FieldPrediction::Source prediction_source2 = IsRequired();
|
||||
bool server_type_prediction_is_override = IsRequired();
|
||||
size_t rank_in_field_signature_group = IsRequired();
|
||||
};
|
||||
using ServerPredictionFieldLogEvent = ServerPredictionFieldLogEventImpl<>;
|
||||
|
||||
// Compare two field log events from ServerPredictionFieldLogEvent type.
|
||||
bool AreCollapsible(const ServerPredictionFieldLogEvent& event1,
|
||||
const ServerPredictionFieldLogEvent& event2);
|
||||
|
||||
} // namespace autofill
|
||||
|
||||
#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_METRICS_LOG_EVENT_H_
|
||||
|
@ -9402,6 +9402,15 @@ others/histograms.xml -->
|
||||
<int value="2" label="Available after session start"/>
|
||||
</enum>
|
||||
|
||||
<enum name="AutofillServerPredictionSource">
|
||||
<int value="0" label="SOURCE_UNSPECIFIED"/>
|
||||
<int value="1" label="SOURCE_AUTOFILL_DEFAULT"/>
|
||||
<int value="2" label="SOURCE_PASSWORDS_DEFAULT"/>
|
||||
<int value="3" label="SOURCE_OVERRIDE"/>
|
||||
<int value="4" label="SOURCE_ALL_APPROVED_EXPERIMENTS"/>
|
||||
<int value="5" label="SOURCE_FIELD_RANKS"/>
|
||||
</enum>
|
||||
|
||||
<enum name="AutofillSessionStates">
|
||||
<int value="0" label="Unknown"/>
|
||||
<int value="1" label="No callback from framework"/>
|
||||
|
@ -2198,6 +2198,40 @@ be describing additional metrics about the same event.
|
||||
to duplicated field signatures.
|
||||
</summary>
|
||||
</metric>
|
||||
<metric name="ServerPredictionSource1" enum="AutofillServerPredictionSource">
|
||||
<summary>
|
||||
The major source of predictions from the Autofill crowdsourced server, see
|
||||
AutofillQueryResponse::FormSuggestion::FieldSuggestion::FieldPrediction::Source.
|
||||
</summary>
|
||||
</metric>
|
||||
<metric name="ServerPredictionSource2" enum="AutofillServerPredictionSource">
|
||||
<summary>
|
||||
The additional source of predictions from the Autofill crowdsourced server
|
||||
if there is an additional prediction, see
|
||||
AutofillQueryResponse::FormSuggestion::FieldSuggestion::FieldPrediction::Source.
|
||||
</summary>
|
||||
</metric>
|
||||
<metric name="ServerType1" enum="AutofillServerFieldType">
|
||||
<summary>
|
||||
The type of the field predicted from the Autofill crowdsourced server from
|
||||
majority voting (and some more complex stuff). The types are from
|
||||
|autofill::ServerFieldType|.
|
||||
</summary>
|
||||
</metric>
|
||||
<metric name="ServerType2" enum="AutofillServerFieldType">
|
||||
<summary>
|
||||
The additional type of the field predicted from the Autofill crowdsourced
|
||||
server if there is an additional prediction. The types are from
|
||||
|autofill::ServerFieldType|.
|
||||
</summary>
|
||||
</metric>
|
||||
<metric name="ServerTypeIsOverride" enum="Boolean">
|
||||
<summary>
|
||||
This is an annotation for server predicted field types which indicates
|
||||
that a manual override defines the server type. This allows us to assess
|
||||
the impact of server overrides and detect possible problems with it.
|
||||
</summary>
|
||||
</metric>
|
||||
<metric name="SuggestionWasAccepted" enum="Boolean">
|
||||
<summary>
|
||||
Whether the suggestion was accepted. This is only set for a field where a
|
||||
|
Reference in New Issue
Block a user