blob: 34e13ebaec04f2b16170a6034f40245b65aa41e1 [file] [log] [blame]
// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_FIELD_H_
#define COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_FIELD_H_
#include <stddef.h>
#include <array>
#include <map>
#include <optional>
#include <string>
#include <string_view>
#include <utility>
#include <variant>
#include <vector>
#include "base/types/optional_ref.h"
#include "base/types/pass_key.h"
#include "components/autofill/core/browser/autofill_type.h"
#include "components/autofill/core/browser/field_types.h"
#include "components/autofill/core/browser/filling/filling_product.h"
#include "components/autofill/core/browser/form_parsing/regex_patterns.h"
#include "components/autofill/core/browser/heuristic_source.h"
#include "components/autofill/core/browser/metrics/log_event.h"
#include "components/autofill/core/browser/proto/password_requirements.pb.h"
#include "components/autofill/core/common/form_field_data.h"
#include "components/autofill/core/common/signatures.h"
namespace autofill {
class AutofillQueryResponse_FormSuggestion_FieldSuggestion_FieldPrediction;
enum FormatString_Type : int;
using FieldPrediction =
AutofillQueryResponse_FormSuggestion_FieldSuggestion_FieldPrediction;
// Enum representing prediction sources that are recognized.
enum class AutofillPredictionSource {
kServerCrowdsourcing = 0,
kServerOverride = 1,
kHeuristics = 2,
kAutocomplete = 3,
kRationalization = 4,
kMaxValue = kRationalization
};
std::string_view AutofillPredictionSourceToStringView(
AutofillPredictionSource source);
// Stores information about the section of the field.
class Section {
public:
struct Autocomplete {
friend auto operator<=>(const Autocomplete& lhs,
const Autocomplete& rhs) = default;
friend bool operator==(const Autocomplete& lhs,
const Autocomplete& rhs) = default;
std::string section;
HtmlFieldMode mode = HtmlFieldMode::kNone;
};
using Default = std::monostate;
struct FieldIdentifier {
FieldIdentifier() = default;
FieldIdentifier(std::string field_name,
size_t local_frame_id,
FieldRendererId field_renderer_id)
: field_name(std::move(field_name)),
local_frame_id(local_frame_id),
field_renderer_id(field_renderer_id) {}
friend auto operator<=>(const FieldIdentifier& lhs,
const FieldIdentifier& rhs) = default;
friend bool operator==(const FieldIdentifier& lhs,
const FieldIdentifier& rhs) = default;
std::string field_name;
size_t local_frame_id;
FieldRendererId field_renderer_id;
};
static Section FromAutocomplete(Autocomplete autocomplete);
static Section FromFieldIdentifier(
const FormFieldData& field,
base::flat_map<LocalFrameToken, size_t>& frame_token_ids);
Section();
Section(const Section& section);
Section& operator=(const Section& section);
Section(Section&& section);
Section& operator=(Section&& section);
~Section();
friend auto operator<=>(const Section& lhs, const Section& rhs) = default;
friend bool operator==(const Section& lhs, const Section& rhs) = default;
explicit operator bool() const;
bool is_from_autocomplete() const;
bool is_from_fieldidentifier() const;
bool is_default() const;
// Reconstructs `this` to a string. The string representation of the section
// is used in the renderer.
// TODO(crbug.com/40200532): Remove when fixed.
std::string ToString() const;
private:
// Represents the section's origin:
// - `Default` is the empty, initial value before running any sectioning
// algorithm,
// - `Autocomplete` represents a section derived from the autocomplete
// attribute,
// - `FieldIdentifier` represents a section generated based on the first
// field in the section.
using SectionValue = std::variant<Default, Autocomplete, FieldIdentifier>;
SectionValue value_;
};
LogBuffer& operator<<(LogBuffer& buffer, const Section& section);
std::ostream& operator<<(std::ostream& os, const Section& section);
// Describes formatting information for a field. Currently used only for
// filling Autofill AI data.
struct AutofillFormatString final {
AutofillFormatString();
AutofillFormatString(std::u16string value, FormatString_Type type);
AutofillFormatString(const AutofillFormatString&);
AutofillFormatString& operator=(const AutofillFormatString&);
AutofillFormatString(AutofillFormatString&&);
AutofillFormatString& operator=(AutofillFormatString&&);
~AutofillFormatString();
friend bool operator==(const AutofillFormatString&,
const AutofillFormatString&) = default;
// The actual format string.
std::u16string value;
// Format strings can have different types: They can specify a date
// format, an affix format, etc. See `FormatString_Type` for allowed values.
FormatString_Type type{};
};
// The ordering matters: higher values overrule lower values (e.g., kServer
// overrules kHeuristics).
enum class AutofillFormatStringSource {
kUnset = 0, // No format string set.
kHeuristics = 1, // Set by local heuristics.
kModelResult = 2, // Set by a direct model response
kServer = 3, // Set by an (Autofill) server response.
};
class AutofillField : public FormFieldData {
public:
using FieldLogEventType = std::variant<std::monostate,
AskForValuesToFillFieldLogEvent,
TriggerFillFieldLogEvent,
FillFieldLogEvent,
TypingFieldLogEvent,
HeuristicPredictionFieldLogEvent,
AutocompleteAttributeFieldLogEvent,
ServerPredictionFieldLogEvent,
RationalizationFieldLogEvent,
AblationFieldLogEvent>;
AutofillField();
explicit AutofillField(const FormFieldData& field);
AutofillField(const AutofillField&) = delete;
AutofillField& operator=(const AutofillField&) = delete;
AutofillField(AutofillField&&);
AutofillField& operator=(AutofillField&&);
virtual ~AutofillField();
// Creates AutofillField that has bare minimum information for uploading
// votes, namely a field signature. Warning: do not use for Autofill code,
// since it is likely missing some fields.
static std::unique_ptr<AutofillField> CreateForPasswordManagerUpload(
FieldSignature field_signature);
// The unique identifier of the section (e.g. billing vs. shipping address)
// of this field.
const Section& section() const { return section_; }
void set_section(Section section) { section_ = std::move(section); }
FieldType heuristic_type() const;
FieldType heuristic_type(HeuristicSource s) const;
FieldType server_type() const;
bool server_type_prediction_is_override() const;
const std::vector<FieldPrediction>& server_predictions() const {
return server_predictions_;
}
const std::vector<FieldPrediction>& experimental_server_predictions() const {
return experimental_server_predictions_;
}
HtmlFieldType html_type() const { return html_type_; }
HtmlFieldMode html_mode() const { return html_mode_; }
const FieldTypeSet& possible_types() const { return possible_types_; }
bool previously_autofilled() const { return previously_autofilled_; }
bool only_fill_when_focused() const { return only_fill_when_focused_; }
void set_heuristic_type(HeuristicSource s, FieldType t);
// Sets the server predictions to `predictions` after performing some
// filtering. If `predictions` is empty, it creates a `NO_SERVER_DATA`
// prediction.
void set_server_predictions(std::vector<FieldPrediction> predictions);
// Adds `prediction` to the back of the existing `server_predictions_` if
// the prediction's source passes various validity checks. If the only
// existing server prediction is an empty one, it replaces that one.
void MaybeAddServerPrediction(FieldPrediction prediction);
void set_possible_types(const FieldTypeSet& possible_types) {
possible_types_ = possible_types;
}
void SetHtmlType(HtmlFieldType type, HtmlFieldMode mode);
void set_previously_autofilled(bool previously_autofilled) {
previously_autofilled_ = previously_autofilled;
}
void set_only_fill_when_focused(bool fill_when_focused) {
only_fill_when_focused_ = fill_when_focused;
}
// Set the type of the field. This sets the value returned by Type().
// This function can be used to override the value that would be returned by
// ComputedType().
// As the `type` is expected to depend on ComputedType(), the value will be
// reset to ComputedType() if some internal value change (e.g. on call to
// (set_heuristic_type()).
// SetTypeTo() must not be called with `type.GetTypes().empty()`.
void SetTypeTo(const AutofillType& type,
std::optional<AutofillPredictionSource> source);
// The type of `GetOverallPredictionResult()`.
AutofillType Type() const;
// The prediction source of `GetOverallPredictionResult()`.
// Note that if no prediction was made by any source, PredictionSource will be
// std::nullopt. Type() would return UNKNOWN_TYPE in such a case.
std::optional<AutofillPredictionSource> PredictionSource() const;
// The type of `GetComputedPredictionResult()`.
AutofillType ComputedType() const;
// The rank of a field is N iff this field is preceded by N other fields
// in the frame-transcending form.
size_t rank() const { return rank_; }
void set_rank(size_t rank) { rank_ = rank; }
// The rank in the signature group of a field is N in a form iff this field is
// preceded by N other fields whose signature is identical to this field's
// signature in the frame-transcending form.
size_t rank_in_signature_group() const { return rank_in_signature_group_; }
void set_rank_in_signature_group(size_t rank_in_signature_group) {
rank_in_signature_group_ = rank_in_signature_group;
}
// The rank of a field is N iff this field is preceded by N other fields
// in the form in the host frame.
size_t rank_in_host_form() const { return rank_in_host_form_; }
void set_rank_in_host_form(size_t rank_in_host_form) {
rank_in_host_form_ = rank_in_host_form;
}
// The rank in the signature group of a field is N in a form iff this field is
// preceded by N other fields whose signature is identical to this field's
// signature in the form in the host frame.
size_t rank_in_host_form_signature_group() const {
return rank_in_host_form_signature_group_;
}
void set_rank_in_host_form_signature_group(
size_t rank_in_host_form_signature_group) {
rank_in_host_form_signature_group_ = rank_in_host_form_signature_group;
}
// The unique signature of this field, composed of the field name and the html
// input type in a 32-bit hash.
FieldSignature GetFieldSignature() const;
// Returns the field signature as string.
std::string FieldSignatureAsStr() const;
// Returns true if the field type has been determined (without the text in the
// field).
bool IsFieldFillable() const;
// Returns true if the field's type is a credit card expiration type.
bool HasExpirationDateType() const;
// Address Autofill is disabled for fields with unrecognized autocomplete
// attribute - except if the field has a server overwrite.
// Fields with `autocomplete=unrecognized` receive a predictions, but
// suggestions and filling are suppressed on Desktop. This function can be
// used to determine whether suggestions and filling should be suppressed for
// this field (independently of the predicted type).
bool ShouldSuppressSuggestionsAndFillingByDefault() const;
// Returns the current value, formatted as desired for import:
// (1) If the field value hasn't changed since it was seen and the field is a
// non-<select>, returns the empty string.
// (2) If the field has FormControlType::kSelect* and has a selected option,
// returns that option's human-readable text.
// (3) Otherwise returns value().
//
// The motivation behind (1) is that unchanged values usually carry little
// value for importing. <select> fields are exempted because their default
// value is often correct (e.g., in ADDRESS_HOME_COUNTRY fields).
// TODO(crbug.com/40137859): Consider also exempting non-<select>
// ADDRESS_HOME_{STATE,COUNTRY} fields.
//
// The motivation behind (2) is that the human-readable text of an <option> is
// usually better suited for import than the its value. See the documentation
// of FormFieldData::value() and FormFieldData::selected_text() for further
// details.
const std::u16string& value_for_import() const;
// Returns the value the field had when it was first seen by the
// AutofillManager. For fields that exist on page load, this is typically the
// value on page load.
//
// There are some special cases where the above does not apply, such as:
// - When the field has moved to another form.
// - When the form has been extracted without the field. For example, this
// could happen because the field was temporarily removed from the DOM.
//
// For the field's current value, see FormFieldData::value().
const std::u16string& initial_value() const { return initial_value_; }
// Sets the field's current value.
void set_initial_value(std::u16string initial_value,
base::PassKey<FormStructure> pass_key) {
initial_value_ = std::move(initial_value);
}
void set_credit_card_number_offset(size_t position) {
credit_card_number_offset_ = position;
}
size_t credit_card_number_offset() const {
return credit_card_number_offset_;
}
void SetPasswordRequirements(PasswordRequirementsSpec spec);
const std::optional<PasswordRequirementsSpec>& password_requirements() const {
return password_requirements_;
}
// The format of the value expected by the web document. Currently, the
// following kinds of format stings are supported:
// - Affix format strings (see data_util::IsValidAffixFormat()).
// - Date format strings (data_util::IsValidDateFormat()).
// - Flight number format strings (data_util::IsValidFlightNumberFormat()).
//
// Only one format string is stored at a time: the one with the
// highest-ranking `AutofillFormatString::Source`.
base::optional_ref<const AutofillFormatString> format_string() const
LIFETIME_BOUND;
AutofillFormatStringSource format_string_source() const {
return format_string_source_;
}
void set_format_string_unless_overruled(AutofillFormatString format_string,
AutofillFormatStringSource source) {
if (format_string_source_ <= source) {
format_string_ = std::move(format_string);
format_string_source_ = source;
}
}
void set_field_log_events(const std::vector<FieldLogEventType>& events) {
field_log_events_ = events;
}
const std::vector<FieldLogEventType>& field_log_events() const {
static const std::vector<FieldLogEventType> empty_vector{};
return field_log_events_ ? *field_log_events_ : empty_vector;
}
// Avoid holding references to the return value. It is invalidated by
// AppendLogEventIfNotRepeated().
base::optional_ref<FieldLogEventType> last_field_log_event() {
if (field_log_events_ && !field_log_events_->empty()) {
return field_log_events_->back();
}
return std::nullopt;
}
// Add the field log events into the vector |field_log_events_| when it is
// not the same as the last log event in the vector.
void AppendLogEventIfNotRepeated(const FieldLogEventType& log_event);
// Clear all the log events for this field.
void ClearLogEvents() {
if (field_log_events_) {
field_log_events_->clear();
}
}
void set_autofill_source_profile_guid(
std::optional<std::string> autofill_profile_guid) {
autofill_source_profile_guid_ = std::move(autofill_profile_guid);
}
const std::optional<std::string>& autofill_source_profile_guid() const {
return autofill_source_profile_guid_;
}
void set_autofilled_type(std::optional<FieldType> autofilled_type) {
autofilled_type_ = std::move(autofilled_type);
}
std::optional<FieldType> autofilled_type() const { return autofilled_type_; }
void set_filling_product(FillingProduct filling_product) {
filling_product_ = filling_product;
}
FillingProduct filling_product() const { return filling_product_; }
bool WasAutofilledWithFallback() const;
void set_did_trigger_suggestions(bool did_trigger_suggestions) {
did_trigger_suggestions_ = did_trigger_suggestions;
}
bool did_trigger_suggestions() const { return did_trigger_suggestions_; }
void set_was_focused(bool was_focused) { was_focused_ = was_focused; }
bool was_focused() const { return was_focused_; }
void set_ml_supported_types(const FieldTypeSet& s) {
ml_supported_types_ = s;
}
const std::optional<FieldTypeSet>& ml_supported_types() const {
return ml_supported_types_;
}
#if defined(UNIT_TEST)
const std::array<FieldType,
static_cast<size_t>(HeuristicSource::kMaxValue) + 1>&
local_type_predictions() const {
return local_type_predictions_;
}
#endif
private:
struct PredictionResult {
// The type may be a union type, i.e., hold multiple FieldTypes.
AutofillType type;
// The source of the primary FieldType in `type`: If there are multiple
// FieldTypes in `type`, the source only refers to the non-Autofill AI
// types.
// TODO(crbug.com/432645177): Make the FieldType to which the `source`
// applies explicit?
std::optional<AutofillPredictionSource> source;
};
explicit AutofillField(FieldSignature field_signature);
// Whether the heuristics or server predict a credit card field.
bool IsCreditCardPrediction() const;
// Creates a union type that contains
// - the `primary_field_type` and
// - the Autofill AI FieldTypes in the `server_predictions_` (modulo conflict
// resolution).
//
// A union type is an AutofillType that holds multiple FieldType.
// See AutofillType for details.
//
// TODO(crbug.com/436013479): Remove the hack that represents country codes.
AutofillType MakeAutofillType(FieldType primary_field_type,
bool is_country_code = false) const;
// Combines the server, heuristic and HTML type based predictions. Doesn't
// take server overwrites or rationalization into consideration.
PredictionResult GetComputedPredictionResult() const;
// Returns the GetComputedPredictionResult(), unless there is a server
// overwrite or the result was overwritten using `SetTypeTo()`.
PredictionResult GetOverallPredictionResult() const;
Section section_;
std::optional<FieldSignature> field_signature_;
size_t rank_ = 0;
size_t rank_in_signature_group_ = 0;
size_t rank_in_host_form_ = 0;
size_t rank_in_host_form_signature_group_ = 0;
// The possible types of the field, as determined by the Autofill server.
std::vector<FieldPrediction> server_predictions_;
// Predictions from the Autofill server which are not intended for general
// consumption. They are used for metrics and/or finch experiments.
std::vector<FieldPrediction> experimental_server_predictions_;
// Requirements the site imposes to passwords (for password generation).
// Corresponds to the requirements determined by the Autofill server.
std::optional<PasswordRequirementsSpec> password_requirements_;
AutofillFormatString format_string_;
AutofillFormatStringSource format_string_source_ =
AutofillFormatStringSource::kUnset;
// Predictions which where calculated on the client. This is initialized to
// `NO_SERVER_DATA`, which means "NO_DATA", i.e. no classification was
// attempted.
std::array<FieldType, static_cast<size_t>(HeuristicSource::kMaxValue) + 1>
local_type_predictions_;
// The rationalized `GetComputedPredictionResult()`. This is the type used for
// all autofilling operations. It defaults to `GetComputedPredictionResult()`
// and is invalidated when `set_heuristic_type()`, `set_server_predictions()`
// or `SetHtmlType()` are called. Rationalization potentially overwrites it
// using `SetTypeTo()`. The result is cached to prevent frequent re-evaluation
// of `GetComputedPredictionResult()`.
// Nullopt if no result is cached. If it has a value, the type is guaranteed
// to be different from NO_SERVER_DATA.
mutable std::optional<PredictionResult> overall_type_;
// The type of the field, as specified by the site author in HTML.
HtmlFieldType html_type_ = HtmlFieldType::kUnspecified;
// The "mode" of the field, as specified by the site author in HTML.
// Currently this is used to distinguish between billing and shipping fields.
HtmlFieldMode html_mode_ = HtmlFieldMode::kNone;
// The set of possible types for this field. It is normally only populated on
// submission time.
FieldTypeSet possible_types_;
// The field's initial value. By default, it's the same as the field's
// `value()`, but FormStructure::RetrieveFromCache() may override it.
std::u16string initial_value_ = value();
// Used to hold the position of the first digit to be copied as a substring
// from credit card number.
size_t credit_card_number_offset_ = 0;
// Whether the field was autofilled then later edited.
bool previously_autofilled_ = false;
// Whether the field should be filled when it is not the highlighted field.
bool only_fill_when_focused_ = false;
// A list of field log events, which record when user interacts the field
// during autofill or editing, such as user clicks on the field, the
// suggestion list is shown for the field, user accepts one suggestion to
// fill the form and user edits the field.
std::optional<std::vector<FieldLogEventType>> field_log_events_ =
std::vector<FieldLogEventType>{};
// The autofill profile's GUID that was used for field filling. It corresponds
// to the autofill profile's GUID for the last address filling value of the
// field. nullopt means the field was never autofilled with address data.
// Note: `is_autofilled` is true for autocompleted fields. So `is_autofilled`
// is not a sufficient condition for `autofill_source_profile_guid_` to have a
// value. This is not tracked for fields filled with field by field filling.
std::optional<std::string> autofill_source_profile_guid_;
// Denotes the type that was used to fill the field in its last autofill
// operation. This is different from `overall_type_` because in some cases
// Autofill might fallback to filling a classified field with a different type
// than the classified one, based on country-specific rules.
// This is not tracked for fields filled with field by field filling.
std::optional<FieldType> autofilled_type_;
// Denotes the product last responsible for filling the field. If the field is
// autofilled, then it will correspond to the current filler, otherwise it
// would correspond to the last filler of the field before the field became
// not autofilled (due to user or JS edits). Note that this is not necessarily
// tied to the field type, as some filling mechanisms are independent of the
// field type (e.g. Autocomplete).
FillingProduct filling_product_ = FillingProduct::kNone;
// Denotes whether a user triggered suggestions from this field.
bool did_trigger_suggestions_ = false;
// True iff the field was ever focused.
bool was_focused_ = false;
// Field types that the ML model is able to output.
// Assigned by the model when it has classified the field.
std::optional<FieldTypeSet> ml_supported_types_;
};
} // namespace autofill
#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_FIELD_H_