Index: chrome/browser/autofill/autofill_manager.cc |
diff --git a/chrome/browser/autofill/autofill_manager.cc b/chrome/browser/autofill/autofill_manager.cc |
index d8c025b4f442595dc76c786c5bc01d825a616a95..e674a9d7a2112a36ed97eb034a393753f53a1956 100644 |
--- a/chrome/browser/autofill/autofill_manager.cc |
+++ b/chrome/browser/autofill/autofill_manager.cc |
@@ -98,124 +98,32 @@ void RemoveDuplicateSuggestions(std::vector<string16>* values, |
unique_ids->swap(unique_ids_copy); |
} |
-// Precondition: |form| should be the cached version of the form that is to be |
-// autofilled, and |field| should be the field in the |form| that corresponds to |
-// the initiating field. |is_filling_credit_card| should be true if filling |
-// credit card data, false otherwise. |
-// Fills |section_start| and |section_end| so that [section_start, section_end) |
-// gives the bounds of logical section within |form| that includes |field|. |
-// Logical sections are identified by two heuristics: |
-// 1. The fields in the section must all be profile or credit card fields, |
-// depending on whether |is_filling_credit_card| is true. |
-// 2. A logical section should not include multiple fields of the same autofill |
-// type (except for adjacent repeated fields and phone/fax numbers, as |
-// described below). |
-void FindSectionBounds(const FormStructure& form, |
- const AutofillField& field, |
- bool is_filling_credit_card, |
- size_t* section_start, |
- size_t* section_end) { |
- DCHECK(section_start); |
- DCHECK(section_end); |
- |
- // By default, the relevant section is the entire form. |
- *section_start = 0; |
- *section_end = form.field_count(); |
- |
- std::set<AutofillFieldType> seen_types; |
- bool initiating_field_is_in_current_section = false; |
- AutofillFieldType previous_type = UNKNOWN_TYPE; |
- for (size_t i = 0; i < form.field_count(); ++i) { |
- const AutofillField* current_field = form.field(i); |
- const AutofillFieldType current_type = |
- AutofillType::GetEquivalentFieldType(current_field->type()); |
- |
- bool already_saw_current_type = seen_types.count(current_type) > 0; |
- // Forms often ask for multiple phone numbers -- e.g. both a daytime and |
- // evening phone number. Our phone and fax number detection is also |
- // generally a little off. Hence, ignore both field types as a signal here. |
- AutofillType::FieldTypeGroup current_type_group = |
- AutofillType(current_type).group(); |
- if (current_type_group == AutofillType::PHONE_HOME || |
- current_type_group == AutofillType::PHONE_FAX) |
- already_saw_current_type = false; |
- |
- // Some forms have adjacent fields of the same type. Two common examples: |
- // * Forms with two email fields, where the second is meant to "confirm" |
- // the first. |
- // * Forms with a <select> menu for states in some countries, and a |
- // freeform <input> field for states in other countries. (Usually, only |
- // one of these two will be visible for any given choice of country.) |
- // Generally, adjacent fields of the same type belong in the same logical |
- // section. |
- if (current_type == previous_type) |
- already_saw_current_type = false; |
- |
- previous_type = current_type; |
- |
- // Fields of unknown type don't help us to distinguish sections. |
- if (current_type == UNKNOWN_TYPE) |
- continue; |
- |
- // If we are filling credit card data, the relevant section should include |
- // only credit card fields; and similarly for profile data. |
- bool is_credit_card_field = current_type_group == AutofillType::CREDIT_CARD; |
- bool is_appropriate_type = is_credit_card_field == is_filling_credit_card; |
- |
- if (already_saw_current_type || !is_appropriate_type) { |
- if (initiating_field_is_in_current_section) { |
- // We reached the end of the section containing the initiating field. |
- *section_end = i; |
- break; |
- } |
- |
- // We reached the end of a section, so start a new section. |
- seen_types.clear(); |
- |
- // Only include the current field in the new section if it matches the |
- // type of data we are filling. |
- if (is_appropriate_type) { |
- *section_start = i; |
- } else { |
- *section_start = i + 1; |
- continue; |
- } |
- } |
- |
- seen_types.insert(current_type); |
- |
- if (current_field == &field) |
- initiating_field_is_in_current_section = true; |
- } |
- |
- // We should have found the initiating field. |
- DCHECK(initiating_field_is_in_current_section); |
-} |
- |
// Precondition: |form_structure| and |form| should correspond to the same |
-// logical form. Returns true if the relevant portion of |form| is auto-filled. |
-// The "relevant" fields in |form| are ones corresponding to fields in |
-// |form_structure| with indices in the range [section_start, section_end). |
+// logical form. Returns true if any relevant field in the given |section| |
+// within |form| is auto-filled. If |is_credit_card_section| is true, only |
+// considers credit card fields; otherwise, only considers non-credit card |
+// fields. |
bool SectionIsAutofilled(const FormStructure* form_structure, |
dhollowa
2011/08/11 01:39:46
This kinda hurts my brains. Seems like intermingl
Ilya Sherman
2011/08/11 03:33:48
Done.
|
const webkit_glue::FormData& form, |
- size_t section_start, |
- size_t section_end) { |
+ const string16& section, |
+ bool is_credit_card_section) { |
// TODO(isherman): It would be nice to share most of this code with the loop |
- // in |FillAutofillFormData()|, but I don't see a particularly clean way to do |
- // that. |
+ // in |OnFillAutofillFormData()|, but I don't see a particularly clean way to |
+ // do that. |
// The list of fields in |form_structure| and |form.fields| often match |
// directly and we can fill these corresponding fields; however, when the |
// |form_structure| and |form.fields| do not match directly we search |
// ahead in the |form_structure| for the matching field. |
- for (size_t i = section_start, j = 0; |
- i < section_end && j < form.fields.size(); |
+ for (size_t i = 0, j = 0; |
+ i < form_structure->field_count() && j < form.fields.size(); |
j++) { |
size_t k = i; |
// Search forward in the |form_structure| for a corresponding field. |
while (k < form_structure->field_count() && |
- *form_structure->field(k) != form.fields[j]) { |
+ (form_structure->field(k)->section() != section || |
+ *form_structure->field(k) != form.fields[j])) { |
k++; |
} |
@@ -223,13 +131,24 @@ bool SectionIsAutofilled(const FormStructure* form_structure, |
if (k >= form_structure->field_count()) |
continue; |
- AutofillType autofill_type(form_structure->field(k)->type()); |
+ // We found a matching field in the |form_structure|, so on the next |
+ // iteration we should proceed to the next |form_structure| field. |
+ ++i; |
+ |
+ AutofillFieldType field_type = form_structure->field(k)->type(); |
+ |
+ // Fields of unknown type should never be autofilled. |
+ if (field_type == UNKNOWN_TYPE) |
+ continue; |
+ |
+ // Only consider fields of the relevant type. |
+ bool is_credit_card_field = |
+ (AutofillType(field_type).group() == AutofillType::CREDIT_CARD); |
+ if (is_credit_card_field != is_credit_card_section) |
+ continue; |
+ |
if (form.fields[j].is_autofilled) |
return true; |
- |
- // We found a matching field in the |form_structure| so we |
- // proceed to the next |form| field, and the next |form_structure|. |
- ++i; |
} |
return false; |
@@ -495,14 +414,12 @@ void AutofillManager::OnQueryFormFieldAutofill( |
icons.assign(1, string16()); |
unique_ids.assign(1, -1); |
} else { |
- size_t section_start, section_end; |
- FindSectionBounds(*form_structure, *autofill_field, |
- is_filling_credit_card, §ion_start, §ion_end); |
- |
- bool section_is_autofilled = SectionIsAutofilled(form_structure, |
- form, |
- section_start, |
- section_end); |
+ AutofillType::FieldTypeGroup field_type_group = |
+ AutofillType(autofill_field->type()).group(); |
+ bool section_is_autofilled = |
+ SectionIsAutofilled(form_structure, form, |
+ autofill_field->section(), |
+ field_type_group == AutofillType::CREDIT_CARD); |
if (section_is_autofilled) { |
// If the relevant section is auto-filled and the renderer is querying |
// for suggestions, then the user is editing the value of a field. |
@@ -590,16 +507,14 @@ void AutofillManager::OnFillAutofillFormData(int query_id, |
if (!profile && !credit_card) |
return; |
- // Find the section of the form that we are autofilling. |
- size_t section_start, section_end; |
- FindSectionBounds(*form_structure, *autofill_field, (credit_card != NULL), |
- §ion_start, §ion_end); |
- |
FormData result = form; |
// If the relevant section is auto-filled, we should fill |field| but not the |
// rest of the form. |
- if (SectionIsAutofilled(form_structure, form, section_start, section_end)) { |
+ bool is_credit_card_section = |
+ AutofillType(autofill_field->type()).group() == AutofillType::CREDIT_CARD; |
+ if (SectionIsAutofilled(form_structure, form, autofill_field->section(), |
+ is_credit_card_section)) { |
for (std::vector<FormField>::iterator iter = result.fields.begin(); |
iter != result.fields.end(); ++iter) { |
if ((*iter) == field) { |
@@ -628,26 +543,27 @@ void AutofillManager::OnFillAutofillFormData(int query_id, |
// ahead in the |form_structure| for the matching field. |
// See unit tests: AutofillManagerTest.FormChangesRemoveField and |
// AutofillManagerTest.FormChangesAddField for usage. |
- for (size_t i = section_start, j = 0; |
- i < section_end && j < result.fields.size(); |
+ for (size_t i = 0, j = 0; |
+ i < form_structure->field_count() && j < result.fields.size(); |
j++) { |
size_t k = i; |
// Search forward in the |form_structure| for a corresponding field. |
- while (k < section_end && *form_structure->field(k) != result.fields[j]) { |
+ while (k < form_structure->field_count() && |
+ (form_structure->field(k)->section() != autofill_field->section() || |
+ *form_structure->field(k) != result.fields[j])) { |
k++; |
} |
// If we've found a match then fill the |result| field with the found |
// field in the |form_structure|. |
- if (k >= section_end) |
+ if (k >= form_structure->field_count()) |
continue; |
AutofillFieldType field_type = form_structure->field(k)->type(); |
FieldTypeGroup field_group_type = AutofillType(field_type).group(); |
if (field_group_type != AutofillType::NO_GROUP) { |
- if (profile) { |
- DCHECK_NE(AutofillType::CREDIT_CARD, field_group_type); |
+ if (profile && field_group_type != AutofillType::CREDIT_CARD) { |
// If the field being filled is the field that the user initiated the |
// fill from, then take the multi-profile "variant" into account. |
// Otherwise fill with the default (zeroth) variant. |
@@ -657,8 +573,7 @@ void AutofillManager::OnFillAutofillFormData(int query_id, |
} else { |
FillFormField(profile, field_type, 0, &result.fields[j]); |
} |
- } else { |
- DCHECK_EQ(AutofillType::CREDIT_CARD, field_group_type); |
+ } else if (credit_card && field_group_type == AutofillType::CREDIT_CARD) { |
FillCreditCardFormField(credit_card, field_type, &result.fields[j]); |
} |
} |