blob: e0eb40ca514a4a40fdde92e53dfbcf66659bb255 [file] [log] [blame]
// Copyright 2013 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/core/browser/autofill_field.h"
#include <stdint.h>
#include <utility>
#include "base/feature_list.h"
#include "base/strings/string_number_conversions.h"
#include "components/autofill/core/browser/field_types.h"
#include "components/autofill/core/browser/proto/server.pb.h"
#include "components/autofill/core/common/autofill_features.h"
namespace autofill {
AutofillField::AutofillField()
: server_type_(NO_SERVER_DATA),
heuristic_type_(UNKNOWN_TYPE),
overall_type_(AutofillType(NO_SERVER_DATA)),
html_type_(HTML_TYPE_UNSPECIFIED),
html_mode_(HTML_MODE_NONE),
phone_part_(IGNORED),
credit_card_number_offset_(0),
previously_autofilled_(false),
only_fill_when_focused_(false),
generation_type_(AutofillUploadContents::Field::NO_GENERATION),
generated_password_changed_(false),
vote_type_(AutofillUploadContents::Field::NO_INFORMATION) {}
AutofillField::AutofillField(const FormFieldData& field,
const base::string16& unique_name)
: FormFieldData(field),
unique_name_(unique_name),
server_type_(NO_SERVER_DATA),
heuristic_type_(UNKNOWN_TYPE),
overall_type_(AutofillType(NO_SERVER_DATA)),
html_type_(HTML_TYPE_UNSPECIFIED),
html_mode_(HTML_MODE_NONE),
phone_part_(IGNORED),
credit_card_number_offset_(0),
previously_autofilled_(false),
only_fill_when_focused_(false),
parseable_name_(field.name),
generation_type_(AutofillUploadContents::Field::NO_GENERATION),
generated_password_changed_(false),
vote_type_(AutofillUploadContents::Field::NO_INFORMATION) {}
AutofillField::~AutofillField() {}
void AutofillField::set_heuristic_type(ServerFieldType type) {
if (type >= 0 && type < MAX_VALID_FIELD_TYPE &&
type != FIELD_WITH_DEFAULT_VALUE) {
heuristic_type_ = type;
} else {
NOTREACHED();
// This case should not be reachable; but since this has potential
// implications on data uploaded to the server, better safe than sorry.
heuristic_type_ = UNKNOWN_TYPE;
}
overall_type_ = AutofillType(NO_SERVER_DATA);
}
void AutofillField::set_server_type(ServerFieldType type) {
// Chrome no longer supports fax numbers, but the server still does.
if (type >= PHONE_FAX_NUMBER && type <= PHONE_FAX_WHOLE_NUMBER)
return;
server_type_ = type;
overall_type_ = AutofillType(NO_SERVER_DATA);
}
void AutofillField::add_possible_types_validities(
const std::map<ServerFieldType, AutofillProfile::ValidityState>&
possible_types_validities) {
for (const auto& possible_type_validity : possible_types_validities) {
possible_types_validities_[possible_type_validity.first].push_back(
possible_type_validity.second);
}
}
std::vector<AutofillProfile::ValidityState>
AutofillField::get_validities_for_possible_type(ServerFieldType type) {
if (possible_types_validities_.find(type) == possible_types_validities_.end())
return {AutofillProfile::UNVALIDATED};
return possible_types_validities_[type];
}
void AutofillField::SetHtmlType(HtmlFieldType type, HtmlFieldMode mode) {
html_type_ = type;
html_mode_ = mode;
overall_type_ = AutofillType(NO_SERVER_DATA);
if (type == HTML_TYPE_TEL_LOCAL_PREFIX)
phone_part_ = PHONE_PREFIX;
else if (type == HTML_TYPE_TEL_LOCAL_SUFFIX)
phone_part_ = PHONE_SUFFIX;
else
phone_part_ = IGNORED;
}
void AutofillField::SetTypeTo(const AutofillType& type) {
DCHECK(type.GetStorableType() != NO_SERVER_DATA);
overall_type_ = type;
}
AutofillType AutofillField::ComputedType() const {
// If autocomplete=tel/tel-* and server confirms it really is a phone field,
// we always user the server prediction as html types are not very reliable.
if ((GroupTypeOfHtmlFieldType(html_type_, html_mode_) == PHONE_BILLING ||
GroupTypeOfHtmlFieldType(html_type_, html_mode_) == PHONE_HOME) &&
(GroupTypeOfServerFieldType(server_type_) == PHONE_BILLING ||
GroupTypeOfServerFieldType(server_type_) == PHONE_HOME)) {
return AutofillType(server_type_);
}
// Use the html type specified by the website unless it is unrecognized and
// autofill predicts a credit card type.
if (html_type_ != HTML_TYPE_UNSPECIFIED &&
!(html_type_ == HTML_TYPE_UNRECOGNIZED && IsCreditCardPrediction())) {
return AutofillType(html_type_, html_mode_);
}
if (server_type_ != NO_SERVER_DATA) {
// Sometimes the server and heuristics disagree on whether a name field
// should be associated with an address or a credit card. There was a
// decision to prefer the heuristics in these cases, but it looks like
// it might be better to fix this server-side.
// See http://crbug.com/429236 for background.
bool believe_server;
if (base::FeatureList::IsEnabled(
features::kAutofillPreferServerNamePredictions)) {
believe_server = true;
} else {
believe_server = !(server_type_ == NAME_FULL &&
heuristic_type_ == CREDIT_CARD_NAME_FULL) &&
!(server_type_ == CREDIT_CARD_NAME_FULL &&
heuristic_type_ == NAME_FULL) &&
!(server_type_ == NAME_FIRST &&
heuristic_type_ == CREDIT_CARD_NAME_FIRST) &&
!(server_type_ == NAME_LAST &&
heuristic_type_ == CREDIT_CARD_NAME_LAST);
}
// Either way, retain a preference for the the CVC heuristic over the
// server's password predictions (http://crbug.com/469007)
believe_server = believe_server &&
!(AutofillType(server_type_).group() == PASSWORD_FIELD &&
heuristic_type_ == CREDIT_CARD_VERIFICATION_CODE);
if (believe_server)
return AutofillType(server_type_);
}
return AutofillType(heuristic_type_);
}
AutofillType AutofillField::Type() const {
if (overall_type_.GetStorableType() != NO_SERVER_DATA) {
return overall_type_;
}
return ComputedType();
}
bool AutofillField::IsEmpty() const {
return value.empty();
}
FieldSignature AutofillField::GetFieldSignature() const {
return CalculateFieldSignatureByNameAndType(name, form_control_type);
}
std::string AutofillField::FieldSignatureAsStr() const {
return base::UintToString(GetFieldSignature());
}
bool AutofillField::IsFieldFillable() const {
return !Type().IsUnknown();
}
void AutofillField::SetPasswordRequirements(PasswordRequirementsSpec spec) {
password_requirements_ = std::move(spec);
}
void AutofillField::NormalizePossibleTypesValidities() {
for (const auto& possible_type : possible_types_) {
if (possible_types_validities_[possible_type].empty()) {
possible_types_validities_[possible_type].push_back(
AutofillProfile::UNVALIDATED);
}
}
}
bool AutofillField::IsCreditCardPrediction() const {
return AutofillType(server_type_).group() == CREDIT_CARD ||
AutofillType(heuristic_type_).group() == CREDIT_CARD;
}
} // namespace autofill