diff options
6 files changed, 75 insertions, 65 deletions
diff --git a/chrome/test/data/autofill/heuristics/output/24_checkout_harryanddavid.com.out b/chrome/test/data/autofill/heuristics/output/24_checkout_harryanddavid.com.out index e7ab75db..2105db0 100644 --- a/chrome/test/data/autofill/heuristics/output/24_checkout_harryanddavid.com.out +++ b/chrome/test/data/autofill/heuristics/output/24_checkout_harryanddavid.com.out @@ -1,42 +1,42 @@ UNKNOWN_TYPE | typeOfAddress | Business address | H | typeOfAddress_1-default UNKNOWN_TYPE | personTitle | Title | | typeOfAddress_1-default UNKNOWN_TYPE | recipientRelation | Relationship | 0 | typeOfAddress_1-default -COMPANY_NAME | | Company name* | Χ | typeOfAddress_1-default +UNKNOWN_TYPE | | Company name* | Χ | typeOfAddress_1-default UNKNOWN_TYPE | organizationName | Company name* | | typeOfAddress_1-default UNKNOWN_TYPE | | Attn. Line* | Χ | typeOfAddress_1-default -COMPANY_NAME | businessTitle | Attn. Line* | | businessTitle_1-default -UNKNOWN_TYPE | | First Name* | Χ | businessTitle_1-default -NAME_FIRST | firstName | First Name* | | businessTitle_1-default -NAME_LAST | | Last Name* | Χ | businessTitle_1-default -UNKNOWN_TYPE | lastName | Last Name* | | businessTitle_1-default -UNKNOWN_TYPE | | Additional info | Χ | businessTitle_1-default -UNKNOWN_TYPE | middleName | Additional info | | businessTitle_1-default -ADDRESS_HOME_LINE1 | | Street address* | Χ | businessTitle_1-default -ADDRESS_HOME_LINE2 | address1 | Street address* | | businessTitle_1-default -UNKNOWN_TYPE | | Apt.,suite, bldg. | Χ | businessTitle_1-default -UNKNOWN_TYPE | address2 | Apt.,suite, bldg. | | businessTitle_1-default -ADDRESS_HOME_COUNTRY | country | Country* | US | businessTitle_1-default -ADDRESS_HOME_CITY | | City* | Χ | businessTitle_1-default -ADDRESS_HOME_CITY | city | City* | | businessTitle_1-default -ADDRESS_HOME_STATE | state | State* | | businessTitle_1-default -ADDRESS_HOME_ZIP | | ZIP* | Χ | businessTitle_1-default -UNKNOWN_TYPE | zipCode | ZIP* | | businessTitle_1-default -PHONE_HOME_WHOLE_NUMBER | | Phone number | Χ | businessTitle_1-default -PHONE_HOME_WHOLE_NUMBER | phone1 | Phone number | | businessTitle_1-default -UNKNOWN_TYPE | | Ext | Χ | businessTitle_1-default -PHONE_HOME_WHOLE_NUMBER | phone2 | Ext | | businessTitle_1-default -UNKNOWN_TYPE | phone1Type | Cell phone | C | businessTitle_1-default -EMAIL_ADDRESS | | Email address* | Χ | businessTitle_1-default -EMAIL_ADDRESS | email1 | Email address* | | businessTitle_1-default -EMAIL_ADDRESS | | Confirm email address* | Χ | businessTitle_1-default -EMAIL_ADDRESS | logonId | Confirm email address* | | businessTitle_1-default +COMPANY_NAME | businessTitle | Attn. Line* | | typeOfAddress_1-default +UNKNOWN_TYPE | | First Name* | Χ | typeOfAddress_1-default +NAME_FIRST | firstName | First Name* | | typeOfAddress_1-default +UNKNOWN_TYPE | | Last Name* | Χ | typeOfAddress_1-default +NAME_LAST | lastName | Last Name* | | typeOfAddress_1-default +UNKNOWN_TYPE | | Additional info | Χ | typeOfAddress_1-default +NAME_MIDDLE | middleName | Additional info | | typeOfAddress_1-default +UNKNOWN_TYPE | | Street address* | Χ | typeOfAddress_1-default +ADDRESS_HOME_LINE1 | address1 | Street address* | | typeOfAddress_1-default +UNKNOWN_TYPE | | Apt.,suite, bldg. | Χ | typeOfAddress_1-default +ADDRESS_HOME_LINE2 | address2 | Apt.,suite, bldg. | | typeOfAddress_1-default +ADDRESS_HOME_COUNTRY | country | Country* | US | typeOfAddress_1-default +UNKNOWN_TYPE | | City* | Χ | typeOfAddress_1-default +ADDRESS_HOME_CITY | city | City* | | typeOfAddress_1-default +ADDRESS_HOME_STATE | state | State* | | typeOfAddress_1-default +UNKNOWN_TYPE | | ZIP* | Χ | typeOfAddress_1-default +ADDRESS_HOME_ZIP | zipCode | ZIP* | | typeOfAddress_1-default +UNKNOWN_TYPE | | Phone number | Χ | typeOfAddress_1-default +PHONE_HOME_WHOLE_NUMBER | phone1 | Phone number | | typeOfAddress_1-default +UNKNOWN_TYPE | | Ext | Χ | typeOfAddress_1-default +PHONE_HOME_WHOLE_NUMBER | phone2 | Ext | | typeOfAddress_1-default +UNKNOWN_TYPE | phone1Type | Cell phone | C | typeOfAddress_1-default +UNKNOWN_TYPE | | Email address* | Χ | typeOfAddress_1-default +EMAIL_ADDRESS | email1 | Email address* | | typeOfAddress_1-default +UNKNOWN_TYPE | | Confirm email address* | Χ | typeOfAddress_1-default +EMAIL_ADDRESS | logonId | Confirm email address* | | logonId_1-default UNKNOWN_TYPE | | Gift Card Number | Χ | _1-default UNKNOWN_TYPE | GiftCardNumber | Gift Card Number | | _1-default UNKNOWN_TYPE | | PIN* | Χ | _1-default UNKNOWN_TYPE | GiftCardPin | PIN* | | _1-default UNKNOWN_TYPE | paymentType | What is PayPal? | on | _1-default UNKNOWN_TYPE | paymentType | Card Number Expiration Date | on | _1-default -CREDIT_CARD_NUMBER | | Card Number | Χ | _1-cc +UNKNOWN_TYPE | | Card Number | Χ | _1-default CREDIT_CARD_NUMBER | clearTextAccount | Card Number | | _1-cc CREDIT_CARD_EXP_MONTH | expire_month | Expiration Date | | _1-cc CREDIT_CARD_EXP_4_DIGIT_YEAR | expire_year | Expiration Date | | _1-cc diff --git a/components/autofill/content/common/autofill_messages.h b/components/autofill/content/common/autofill_messages.h index 916d99b5..0816819 100644 --- a/components/autofill/content/common/autofill_messages.h +++ b/components/autofill/content/common/autofill_messages.h @@ -28,6 +28,9 @@ #define IPC_MESSAGE_START AutofillMsgStart +IPC_ENUM_TRAITS_MAX_VALUE(autofill::FormFieldData::RoleAttribute, + autofill::FormFieldData::ROLE_ATTRIBUTE_OTHER) + IPC_ENUM_TRAITS_MAX_VALUE(base::i18n::TextDirection, base::i18n::TEXT_DIRECTION_NUM_DIRECTIONS - 1) @@ -45,6 +48,7 @@ IPC_STRUCT_TRAITS_BEGIN(autofill::FormFieldData) IPC_STRUCT_TRAITS_MEMBER(value) IPC_STRUCT_TRAITS_MEMBER(form_control_type) IPC_STRUCT_TRAITS_MEMBER(autocomplete_attribute) + IPC_STRUCT_TRAITS_MEMBER(role) IPC_STRUCT_TRAITS_MEMBER(max_length) IPC_STRUCT_TRAITS_MEMBER(is_autofilled) IPC_STRUCT_TRAITS_MEMBER(is_checked) diff --git a/components/autofill/content/renderer/form_autofill_util.cc b/components/autofill/content/renderer/form_autofill_util.cc index 628711c..679e5eb 100644 --- a/components/autofill/content/renderer/form_autofill_util.cc +++ b/components/autofill/content/renderer/form_autofill_util.cc @@ -956,6 +956,7 @@ void WebFormControlElementToFormField(const WebFormControlElement& element, DCHECK(field); DCHECK(!element.isNull()); CR_DEFINE_STATIC_LOCAL(WebString, kAutocomplete, ("autocomplete")); + CR_DEFINE_STATIC_LOCAL(WebString, kRole, ("role")); // The label is not officially part of a WebFormControlElement; however, the // labels for all form control elements are scraped from the DOM and set in @@ -970,6 +971,8 @@ void WebFormControlElementToFormField(const WebFormControlElement& element, // attribute was present. field->autocomplete_attribute = "x-max-data-length-exceeded"; } + if (LowerCaseEqualsASCII(element.getAttribute(kRole), "presentation")) + field->role = FormFieldData::ROLE_ATTRIBUTE_PRESENTATION; if (!IsAutofillableElement(element)) return; diff --git a/components/autofill/core/browser/form_field.cc b/components/autofill/core/browser/form_field.cc index b25ff2b..d5b4fe6d 100644 --- a/components/autofill/core/browser/form_field.cc +++ b/components/autofill/core/browser/form_field.cc @@ -27,8 +27,14 @@ namespace autofill { namespace { -bool IsCheckable(const AutofillField* field) { - return field->is_checkable; +bool ShouldBeIgnored(const AutofillField* field) { + // Ignore checkable fields as they interfere with parsers assuming context. + // Eg., while parsing address, "Is PO box" checkbox after ADDRESS_LINE1 + // interferes with correctly understanding ADDRESS_LINE2. + // Ignore fields marked as presentational. See + // http://www.w3.org/TR/wai-aria/roles#presentation + return field->is_checkable || + field->role == FormFieldData::ROLE_ATTRIBUTE_PRESENTATION; } } // namespace @@ -40,12 +46,9 @@ void FormField::ParseFormFields(const std::vector<AutofillField*>& fields, std::vector<AutofillField*> remaining_fields(fields.size()); std::copy(fields.begin(), fields.end(), remaining_fields.begin()); - // Ignore checkable fields as they interfere with parsers assuming context. - // Eg., while parsing address, "Is PO box" checkbox after ADDRESS_LINE1 - // interferes with correctly understanding ADDRESS_LINE2. remaining_fields.erase( std::remove_if(remaining_fields.begin(), remaining_fields.end(), - IsCheckable), + ShouldBeIgnored), remaining_fields.end()); // Email pass. diff --git a/components/autofill/core/common/form_field_data.cc b/components/autofill/core/common/form_field_data.cc index cda33d0..3b80be2 100644 --- a/components/autofill/core/common/form_field_data.cc +++ b/components/autofill/core/common/form_field_data.cc @@ -36,13 +36,13 @@ bool ReadStringVector(PickleIterator* iter, return true; } -bool ReadTextDirection(PickleIterator* iter, - base::i18n::TextDirection* direction) { +template <typename T> +bool ReadAsInt(PickleIterator* iter, T* direction) { int pickle_data; if (!iter->ReadInt(&pickle_data)) return false; - *direction = static_cast<base::i18n::TextDirection>(pickle_data); + *direction = static_cast<T>(pickle_data); return true; } @@ -57,6 +57,7 @@ FormFieldData::FormFieldData() is_checkable(false), is_focusable(false), should_autocomplete(true), + role(ROLE_ATTRIBUTE_OTHER), text_direction(base::i18n::UNKNOWN_DIRECTION) { } @@ -66,8 +67,7 @@ FormFieldData::~FormFieldData() { bool FormFieldData::SameFieldAs(const FormFieldData& field) const { // A FormFieldData stores a value, but the value is not part of the identity // of the field, so we don't want to compare the values. - return (label == field.label && - name == field.name && + return (label == field.label && name == field.name && form_control_type == field.form_control_type && autocomplete_attribute == field.autocomplete_attribute && max_length == field.max_length && @@ -76,7 +76,7 @@ bool FormFieldData::SameFieldAs(const FormFieldData& field) const { is_checkable == field.is_checkable && is_focusable == field.is_focusable && should_autocomplete == field.should_autocomplete && - text_direction == field.text_direction); + role == field.role && text_direction == field.text_direction); // The option values/contents whith are the list of items in the list // of a drop-down are currently not considered part of the identity of // a form element. This is debatable, since one might base heuristics @@ -105,6 +105,10 @@ bool FormFieldData::operator<(const FormFieldData& field) const { if (is_focusable > field.is_focusable) return false; if (should_autocomplete < field.should_autocomplete) return true; if (should_autocomplete > field.should_autocomplete) return false; + if (role < field.role) + return true; + if (role > field.role) + return false; if (text_direction < field.text_direction) return true; if (text_direction > field.text_direction) return false; // See operator== above for why we don't check option_values/contents. @@ -125,6 +129,7 @@ void SerializeFormFieldData(const FormFieldData& field_data, pickle->WriteBool(field_data.is_checkable); pickle->WriteBool(field_data.is_focusable); pickle->WriteBool(field_data.should_autocomplete); + pickle->WriteInt(field_data.role); pickle->WriteInt(field_data.text_direction); AddVectorToPickle(field_data.option_values, pickle); AddVectorToPickle(field_data.option_contents, pickle); @@ -151,7 +156,8 @@ bool DeserializeFormFieldData(PickleIterator* iter, !iter->ReadBool(&field_data->is_checkable) || !iter->ReadBool(&field_data->is_focusable) || !iter->ReadBool(&field_data->should_autocomplete) || - !ReadTextDirection(iter, &field_data->text_direction) || + !ReadAsInt(iter, &field_data->role) || + !ReadAsInt(iter, &field_data->text_direction) || !ReadStringVector(iter, &field_data->option_values) || !ReadStringVector(iter, &field_data->option_contents)) { LOG(ERROR) << "Could not deserialize FormFieldData from pickle"; @@ -168,30 +174,16 @@ bool DeserializeFormFieldData(PickleIterator* iter, } std::ostream& operator<<(std::ostream& os, const FormFieldData& field) { - return os - << base::UTF16ToUTF8(field.label) - << " " - << base::UTF16ToUTF8(field.name) - << " " - << base::UTF16ToUTF8(field.value) - << " " - << field.form_control_type - << " " - << field.autocomplete_attribute - << " " - << field.max_length - << " " - << (field.is_autofilled ? "true" : "false") - << " " - << (field.is_checked ? "true" : "false") - << " " - << (field.is_checkable ? "true" : "false") - << " " - << (field.is_focusable ? "true" : "false") - << " " - << (field.should_autocomplete ? "true" : "false") - << " " - << field.text_direction; + return os << base::UTF16ToUTF8(field.label) << " " + << base::UTF16ToUTF8(field.name) << " " + << base::UTF16ToUTF8(field.value) << " " << field.form_control_type + << " " << field.autocomplete_attribute << " " << field.max_length + << " " << (field.is_autofilled ? "true" : "false") << " " + << (field.is_checked ? "true" : "false") << " " + << (field.is_checkable ? "true" : "false") << " " + << (field.is_focusable ? "true" : "false") << " " + << (field.should_autocomplete ? "true" : "false") << " " + << field.role << " " << field.text_direction; } } // namespace autofill diff --git a/components/autofill/core/common/form_field_data.h b/components/autofill/core/common/form_field_data.h index a443665..ef96b73 100644 --- a/components/autofill/core/common/form_field_data.h +++ b/components/autofill/core/common/form_field_data.h @@ -17,6 +17,13 @@ namespace autofill { // Stores information about a field in a form. struct FormFieldData { + enum RoleAttribute { + // "presentation" + ROLE_ATTRIBUTE_PRESENTATION, + // Anything else. + ROLE_ATTRIBUTE_OTHER, + }; + FormFieldData(); ~FormFieldData(); @@ -39,6 +46,7 @@ struct FormFieldData { bool is_checkable; bool is_focusable; bool should_autocomplete; + RoleAttribute role; base::i18n::TextDirection text_direction; // For the HTML snippet |<option value="US">United States</option>|, the |