Commit fe5e8f32 authored by Vaclav Brozek's avatar Vaclav Brozek Committed by Commit Bot

Teach FormData->PasswordForm parser CVC

The new FormData->PasswordForm parser did not check fields for being
CVC fields (except for autocomplete attributes). Ideally, it would not
need to, because it could rely on server hints, but the hints are not
ready yet, so this CL introduces a short-term ability for the new
parser to understand when a field name sounds like that of a CVC
field.

While in the particular case of the linked bug (on
http://www.shoedazzle.com/), this will break the previously correct
behaviour of the parser, the goal is to minimize the difference in
behaviour against the old parser, so as not to introduce an unknown
amount of new breakages.

Bug: 860700
Change-Id: I4595dbf01142e9f26f7264a1d62cde4cf5e4c0c0
Reviewed-on: https://chromium-review.googlesource.com/1141958Reviewed-by: default avatarVadym Doroshenko <dvadym@chromium.org>
Commit-Queue: Vaclav Brozek <vabr@chromium.org>
Cr-Commit-Position: refs/heads/master@{#576082}
parent f739ba61
......@@ -12,9 +12,14 @@
#include <utility>
#include <vector>
#include "base/no_destructor.h"
#include "base/stl_util.h"
#include "base/strings/string16.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_split.h"
#include "base/strings/utf_string_conversions.h"
#include "components/autofill/core/common/autofill_regex_constants.h"
#include "components/autofill/core/common/autofill_regexes.h"
#include "components/autofill/core/common/form_data.h"
#include "components/autofill/core/common/password_form.h"
#include "components/password_manager/core/common/password_manager_features.h"
......@@ -101,6 +106,21 @@ struct ProcessedField {
Interactability interactability = Interactability::kUnlikely;
};
// Returns true if the |str| contains words related to CVC fields.
bool StringMatchesCVC(const base::string16& str) {
static const base::NoDestructor<base::string16> kCardCvcReCached(
base::UTF8ToUTF16(autofill::kCardCvcRe));
return autofill::MatchesPattern(str, *kCardCvcReCached);
}
// TODO(crbug.com/860700): Remove once server-side provides hints for CVC
// fields.
// Returns true if the |field|'s name or id hint at the field being a CVC field.
bool IsFieldCVC(const FormFieldData& field) {
return StringMatchesCVC(field.name) || StringMatchesCVC(field.id);
}
// Returns true iff |processed_field| matches the |interactability_bar|. That is
// when either:
// (1) |processed_field.interactability| is not less than |interactability_bar|,
......@@ -244,7 +264,8 @@ std::unique_ptr<SignificantFields> ParseUsingAutocomplete(
// Returns only relevant password fields from |processed_fields|. Namely, if
// |mode| == SAVING return only non-empty fields (for saving empty fields are
// useless). This ignores all passwords with Interactability below
// |best_interactability|. Stores the iterator to the first relevant password in
// |best_interactability| and also fields with names which sound like CVC
// fields. Stores the iterator to the first relevant password in
// |first_relevant_password|.
std::vector<const FormFieldData*> GetRelevantPasswords(
const std::vector<ProcessedField>& processed_fields,
......@@ -277,6 +298,8 @@ std::vector<const FormFieldData*> GetRelevantPasswords(
FieldPropertiesFlags::AUTOFILLED))) {
continue;
}
if (IsFieldCVC(*processed_field.field))
continue;
if (*first_relevant_password == processed_fields.end())
*first_relevant_password = it;
result.push_back(processed_field.field);
......@@ -379,6 +402,8 @@ const FormFieldData* FindUsernameFieldBaseHeuristics(
continue;
if (consider_only_non_empty && it->field->value.empty())
continue;
if (IsFieldCVC(*it->field))
continue;
if (!username)
username = it->field;
if (it->field->is_focusable) {
......
......@@ -1254,6 +1254,22 @@ TEST(FormParserTest, ComplementingResults) {
});
}
// Until autofill server learns to provide CVC-related hints, the parser should
// try to get the hint from the field names.
TEST(FormParserTest, CVC) {
CheckTestData({
{
"Name of 'verification_type' matches the CVC pattern.",
{
{.role = ElementRole::USERNAME, .form_control_type = "text"},
{.form_control_type = "text", .name = "verification_type"},
{.role = ElementRole::CURRENT_PASSWORD,
.form_control_type = "password"},
},
},
});
}
} // namespace
} // namespace password_manager
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