| Index: chrome/browser/autofill/form_structure_unittest.cc | 
| diff --git a/chrome/browser/autofill/form_structure_unittest.cc b/chrome/browser/autofill/form_structure_unittest.cc | 
| index 64c8e17c46d07a8480dd903258ae42d320bdc42f..687c82938d0bd3c1679f3db785e3dbd02eadd7fd 100644 | 
| --- a/chrome/browser/autofill/form_structure_unittest.cc | 
| +++ b/chrome/browser/autofill/form_structure_unittest.cc | 
| @@ -52,17 +52,17 @@ TEST(FormStructureTest, FieldCount) { | 
| FormFieldData field; | 
| field.label = ASCIIToUTF16("username"); | 
| field.name = ASCIIToUTF16("username"); | 
| -  field.form_control_type = ASCIIToUTF16("text"); | 
| +  field.form_control_type = "text"; | 
| form.fields.push_back(field); | 
|  | 
| field.label = ASCIIToUTF16("password"); | 
| field.name = ASCIIToUTF16("password"); | 
| -  field.form_control_type = ASCIIToUTF16("password"); | 
| +  field.form_control_type = "password"; | 
| form.fields.push_back(field); | 
|  | 
| field.label = string16(); | 
| field.name = ASCIIToUTF16("Submit"); | 
| -  field.form_control_type = ASCIIToUTF16("submit"); | 
| +  field.form_control_type = "submit"; | 
| form.fields.push_back(field); | 
|  | 
| FormStructure form_structure(form); | 
| @@ -78,22 +78,22 @@ TEST(FormStructureTest, AutofillCount) { | 
| FormFieldData field; | 
| field.label = ASCIIToUTF16("username"); | 
| field.name = ASCIIToUTF16("username"); | 
| -  field.form_control_type = ASCIIToUTF16("text"); | 
| +  field.form_control_type = "text"; | 
| form.fields.push_back(field); | 
|  | 
| field.label = ASCIIToUTF16("password"); | 
| field.name = ASCIIToUTF16("password"); | 
| -  field.form_control_type = ASCIIToUTF16("password"); | 
| +  field.form_control_type = "password"; | 
| form.fields.push_back(field); | 
|  | 
| field.label = ASCIIToUTF16("state"); | 
| field.name = ASCIIToUTF16("state"); | 
| -  field.form_control_type = ASCIIToUTF16("select-one"); | 
| +  field.form_control_type = "select-one"; | 
| form.fields.push_back(field); | 
|  | 
| field.label = string16(); | 
| field.name = ASCIIToUTF16("Submit"); | 
| -  field.form_control_type = ASCIIToUTF16("submit"); | 
| +  field.form_control_type = "submit"; | 
| form.fields.push_back(field); | 
|  | 
| FormStructure form_structure(form); | 
| @@ -122,17 +122,17 @@ TEST(FormStructureTest, IsAutofillable) { | 
| FormFieldData field; | 
| field.label = ASCIIToUTF16("username"); | 
| field.name = ASCIIToUTF16("username"); | 
| -  field.form_control_type = ASCIIToUTF16("text"); | 
| +  field.form_control_type = "text"; | 
| form.fields.push_back(field); | 
|  | 
| field.label = ASCIIToUTF16("password"); | 
| field.name = ASCIIToUTF16("password"); | 
| -  field.form_control_type = ASCIIToUTF16("password"); | 
| +  field.form_control_type = "password"; | 
| form.fields.push_back(field); | 
|  | 
| field.label = string16(); | 
| field.name = ASCIIToUTF16("Submit"); | 
| -  field.form_control_type = ASCIIToUTF16("submit"); | 
| +  field.form_control_type = "submit"; | 
| form.fields.push_back(field); | 
|  | 
| form_structure.reset(new FormStructure(form)); | 
| @@ -142,12 +142,12 @@ TEST(FormStructureTest, IsAutofillable) { | 
| // We now have three text fields, but only two auto-fillable fields. | 
| field.label = ASCIIToUTF16("First Name"); | 
| field.name = ASCIIToUTF16("firstname"); | 
| -  field.form_control_type = ASCIIToUTF16("text"); | 
| +  field.form_control_type = "text"; | 
| form.fields.push_back(field); | 
|  | 
| field.label = ASCIIToUTF16("Last Name"); | 
| field.name = ASCIIToUTF16("lastname"); | 
| -  field.form_control_type = ASCIIToUTF16("text"); | 
| +  field.form_control_type = "text"; | 
| form.fields.push_back(field); | 
|  | 
| form_structure.reset(new FormStructure(form)); | 
| @@ -157,7 +157,7 @@ TEST(FormStructureTest, IsAutofillable) { | 
| // We now have three auto-fillable fields. | 
| field.label = ASCIIToUTF16("Email"); | 
| field.name = ASCIIToUTF16("email"); | 
| -  field.form_control_type = ASCIIToUTF16("email"); | 
| +  field.form_control_type = "email"; | 
| form.fields.push_back(field); | 
|  | 
| form_structure.reset(new FormStructure(form)); | 
| @@ -196,7 +196,7 @@ TEST(FormStructureTest, ShouldBeParsed) { | 
| FormFieldData field; | 
| field.label = ASCIIToUTF16("username"); | 
| field.name = ASCIIToUTF16("username"); | 
| -  field.form_control_type = ASCIIToUTF16("text"); | 
| +  field.form_control_type = "text"; | 
| form.fields.push_back(field); | 
|  | 
| form_structure.reset(new FormStructure(form)); | 
| @@ -205,12 +205,12 @@ TEST(FormStructureTest, ShouldBeParsed) { | 
| // We now have three text fields, though only two are auto-fillable. | 
| field.label = ASCIIToUTF16("First Name"); | 
| field.name = ASCIIToUTF16("firstname"); | 
| -  field.form_control_type = ASCIIToUTF16("text"); | 
| +  field.form_control_type = "text"; | 
| form.fields.push_back(field); | 
|  | 
| field.label = ASCIIToUTF16("Last Name"); | 
| field.name = ASCIIToUTF16("lastname"); | 
| -  field.form_control_type = ASCIIToUTF16("text"); | 
| +  field.form_control_type = "text"; | 
| form.fields.push_back(field); | 
|  | 
| form_structure.reset(new FormStructure(form)); | 
| @@ -240,23 +240,23 @@ TEST(FormStructureTest, ShouldBeParsed) { | 
|  | 
| field.label = ASCIIToUTF16("Email"); | 
| field.name = ASCIIToUTF16("email"); | 
| -  field.form_control_type = ASCIIToUTF16("email"); | 
| +  field.form_control_type = "email"; | 
| form.fields.push_back(field); | 
|  | 
| field.label = ASCIIToUTF16("State"); | 
| field.name = ASCIIToUTF16("state"); | 
| -  field.form_control_type = ASCIIToUTF16("select-one"); | 
| +  field.form_control_type = "select-one"; | 
| form.fields.push_back(field); | 
|  | 
| field.label = ASCIIToUTF16("Country"); | 
| field.name = ASCIIToUTF16("country"); | 
| -  field.form_control_type = ASCIIToUTF16("select-one"); | 
| +  field.form_control_type = "select-one"; | 
| form.fields.push_back(field); | 
|  | 
| form_structure.reset(new FormStructure(form)); | 
| EXPECT_TRUE(form_structure->ShouldBeParsed(true)); | 
|  | 
| -  form.fields[0].form_control_type = ASCIIToUTF16("select-one"); | 
| +  form.fields[0].form_control_type = "select-one"; | 
| form_structure.reset(new FormStructure(form)); | 
| EXPECT_FALSE(form_structure->ShouldBeParsed(true)); | 
| } | 
| @@ -267,7 +267,7 @@ TEST(FormStructureTest, HeuristicsContactInfo) { | 
| form.method = ASCIIToUTF16("post"); | 
|  | 
| FormFieldData field; | 
| -  field.form_control_type = ASCIIToUTF16("text"); | 
| +  field.form_control_type = "text"; | 
|  | 
| field.label = ASCIIToUTF16("First Name"); | 
| field.name = ASCIIToUTF16("firstname"); | 
| @@ -299,7 +299,7 @@ TEST(FormStructureTest, HeuristicsContactInfo) { | 
|  | 
| field.label = string16(); | 
| field.name = ASCIIToUTF16("Submit"); | 
| -  field.form_control_type = ASCIIToUTF16("submit"); | 
| +  field.form_control_type = "submit"; | 
| form.fields.push_back(field); | 
|  | 
| form_structure.reset(new FormStructure(form)); | 
| @@ -329,28 +329,28 @@ TEST(FormStructureTest, HeuristicsContactInfo) { | 
| EXPECT_EQ(UNKNOWN_TYPE, form_structure->field(7)->heuristic_type()); | 
| } | 
|  | 
| -// Verify that we can correctly process the |autocompletetype| attribute. | 
| -TEST(FormStructureTest, HeuristicsAutocompletetype) { | 
| +// Verify that we can correctly process the |autocomplete| attribute. | 
| +TEST(FormStructureTest, HeuristicsAutocompleteAttribute) { | 
| scoped_ptr<FormStructure> form_structure; | 
| FormData form; | 
| form.method = ASCIIToUTF16("post"); | 
|  | 
| FormFieldData field; | 
| -  field.form_control_type = ASCIIToUTF16("text"); | 
| +  field.form_control_type = "text"; | 
|  | 
| field.label = string16(); | 
| field.name = ASCIIToUTF16("field1"); | 
| -  field.autocomplete_type = ASCIIToUTF16("given-name"); | 
| +  field.autocomplete_attribute = "given-name"; | 
| form.fields.push_back(field); | 
|  | 
| field.label = string16(); | 
| field.name = ASCIIToUTF16("field2"); | 
| -  field.autocomplete_type = ASCIIToUTF16("surname"); | 
| +  field.autocomplete_attribute = "family-name"; | 
| form.fields.push_back(field); | 
|  | 
| field.label = string16(); | 
| field.name = ASCIIToUTF16("field3"); | 
| -  field.autocomplete_type = ASCIIToUTF16("email"); | 
| +  field.autocomplete_attribute = "email"; | 
| form.fields.push_back(field); | 
|  | 
| form_structure.reset(new FormStructure(form)); | 
| @@ -366,29 +366,29 @@ TEST(FormStructureTest, HeuristicsAutocompletetype) { | 
| EXPECT_EQ(EMAIL_ADDRESS, form_structure->field(2)->heuristic_type()); | 
| } | 
|  | 
| -// Verify that we can correctly process the |autocompletetype| attribute for | 
| -// phone number types (especially phone prefixes and suffixes). | 
| -TEST(FormStructureTest, HeuristicsAutocompletetypePhones) { | 
| +// Verify that we can correctly process the 'autocomplete' attribute for phone | 
| +// number types (especially phone prefixes and suffixes). | 
| +TEST(FormStructureTest, HeuristicsAutocompleteAttributePhoneTypes) { | 
| scoped_ptr<FormStructure> form_structure; | 
| FormData form; | 
| form.method = ASCIIToUTF16("post"); | 
|  | 
| FormFieldData field; | 
| -  field.form_control_type = ASCIIToUTF16("text"); | 
| +  field.form_control_type = "text"; | 
|  | 
| field.label = string16(); | 
| field.name = ASCIIToUTF16("field1"); | 
| -  field.autocomplete_type = ASCIIToUTF16("phone-local"); | 
| +  field.autocomplete_attribute = "tel-local"; | 
| form.fields.push_back(field); | 
|  | 
| field.label = string16(); | 
| field.name = ASCIIToUTF16("field2"); | 
| -  field.autocomplete_type = ASCIIToUTF16("phone-local-prefix"); | 
| +  field.autocomplete_attribute = "tel-local-prefix"; | 
| form.fields.push_back(field); | 
|  | 
| field.label = string16(); | 
| field.name = ASCIIToUTF16("field3"); | 
| -  field.autocomplete_type = ASCIIToUTF16("phone-local-suffix"); | 
| +  field.autocomplete_attribute = "tel-local-suffix"; | 
| form.fields.push_back(field); | 
|  | 
| form_structure.reset(new FormStructure(form)); | 
| @@ -409,16 +409,16 @@ TEST(FormStructureTest, HeuristicsAutocompletetypePhones) { | 
| form_structure->field(2)->phone_part()); | 
| } | 
|  | 
| -// If at least one field includes the |autocompletetype| attribute, we should | 
| -// not try to apply any other heuristics. | 
| -TEST(FormStructureTest, AutocompletetypeOverridesOtherHeuristics) { | 
| +// If at least one field includes type hints in the 'autocomplete' attribute, we | 
| +// should not try to apply any other heuristics. | 
| +TEST(FormStructureTest, AutocompleteAttributeOverridesOtherHeuristics) { | 
| scoped_ptr<FormStructure> form_structure; | 
| FormData form; | 
| form.method = ASCIIToUTF16("post"); | 
|  | 
| // Start with a regular contact form. | 
| FormFieldData field; | 
| -  field.form_control_type = ASCIIToUTF16("text"); | 
| +  field.form_control_type = "text"; | 
|  | 
| field.label = ASCIIToUTF16("First Name"); | 
| field.name = ASCIIToUTF16("firstname"); | 
| @@ -444,8 +444,8 @@ TEST(FormStructureTest, AutocompletetypeOverridesOtherHeuristics) { | 
| EXPECT_EQ(NAME_LAST, form_structure->field(1)->heuristic_type()); | 
| EXPECT_EQ(EMAIL_ADDRESS, form_structure->field(2)->heuristic_type()); | 
|  | 
| -  // Now update the first form field to include an 'autocompletetype' attribute. | 
| -  form.fields.front().autocomplete_type = ASCIIToUTF16("x-other"); | 
| +  // Now update the first form field to include an 'autocomplete' attribute. | 
| +  form.fields.front().autocomplete_attribute = "x-other"; | 
| form_structure.reset(new FormStructure(form)); | 
| form_structure->DetermineHeuristicTypes(); | 
| EXPECT_FALSE(form_structure->IsAutofillable(true)); | 
| @@ -461,124 +461,178 @@ TEST(FormStructureTest, AutocompletetypeOverridesOtherHeuristics) { | 
|  | 
| // Verify that we can correctly process sections listed in the |autocomplete| | 
| // attribute. | 
| -TEST(FormStructureTest, HeuristicsAutocompletetypeWithSections) { | 
| -  scoped_ptr<FormStructure> form_structure; | 
| +TEST(FormStructureTest, HeuristicsAutocompleteAttributeWithSections) { | 
| FormData form; | 
| form.method = ASCIIToUTF16("post"); | 
|  | 
| FormFieldData field; | 
| -  field.form_control_type = ASCIIToUTF16("text"); | 
| +  field.form_control_type = "text"; | 
|  | 
| -  // We expect "shipping" and "billing" to be the most common sections. | 
| -  field.label = string16(); | 
| -  field.name = ASCIIToUTF16("field1"); | 
| -  field.autocomplete_type = ASCIIToUTF16("section-shipping given-name"); | 
| +  // Some fields will have no section specified.  These fall into the default | 
| +  // section. | 
| +  field.autocomplete_attribute = "email"; | 
| form.fields.push_back(field); | 
|  | 
| -  // Some field will have no section specified.  These fall into the default | 
| -  // section, with an empty name. | 
| -  field.label = string16(); | 
| -  field.name = ASCIIToUTF16("field2"); | 
| -  field.autocomplete_type = ASCIIToUTF16("surname"); | 
| +  // We allow arbitrary section names. | 
| +  field.autocomplete_attribute = "section-foo email"; | 
| form.fields.push_back(field); | 
|  | 
| -  // We allow arbitrary section names. | 
| -  field.label = string16(); | 
| -  field.name = ASCIIToUTF16("field3"); | 
| -  field.autocomplete_type = ASCIIToUTF16("section-foo address-line1"); | 
| +  // "shipping" and "billing" are special section tokens that don't require the | 
| +  // "section-" prefix. | 
| +  field.autocomplete_attribute = "shipping email"; | 
| +  form.fields.push_back(field); | 
| +  field.autocomplete_attribute = "billing email"; | 
| form.fields.push_back(field); | 
|  | 
| -  // Specifying "section-" is equivalent to not specifying a section. | 
| -  field.label = string16(); | 
| -  field.name = ASCIIToUTF16("field4"); | 
| -  field.autocomplete_type = ASCIIToUTF16("section- address-line2"); | 
| +  // "shipping" and "billing" can be combined with other section names. | 
| +  field.autocomplete_attribute = "section-foo shipping email"; | 
| +  form.fields.push_back(field); | 
| +  field.autocomplete_attribute = "section-foo billing email"; | 
| form.fields.push_back(field); | 
|  | 
| // We don't do anything clever to try to coalesce sections; it's up to site | 
| // authors to avoid typos. | 
| -  field.label = string16(); | 
| -  field.name = ASCIIToUTF16("field5"); | 
| -  field.autocomplete_type = ASCIIToUTF16("section--shipping locality"); | 
| +  field.autocomplete_attribute = "section--foo email"; | 
| +  form.fields.push_back(field); | 
| + | 
| +  // "shipping email" and "section--shipping" email should be parsed as | 
| +  // different sections.  This is only an interesting test due to how we | 
| +  // implement implicit section names from attributes like "shipping email"; see | 
| +  // the implementation for more details. | 
| +  field.autocomplete_attribute = "section--shipping email"; | 
| form.fields.push_back(field); | 
|  | 
| // Credit card fields are implicitly in a separate section from other fields. | 
| -  field.label = string16(); | 
| -  field.name = ASCIIToUTF16("field6"); | 
| -  field.autocomplete_type = ASCIIToUTF16("section-shipping cc-number"); | 
| +  field.autocomplete_attribute = "section-foo cc-number"; | 
| form.fields.push_back(field); | 
|  | 
| -  form_structure.reset(new FormStructure(form)); | 
| -  form_structure->DetermineHeuristicTypes(); | 
| -  EXPECT_TRUE(form_structure->IsAutofillable(true)); | 
| +  FormStructure form_structure(form); | 
| +  form_structure.DetermineHeuristicTypes(); | 
| +  EXPECT_TRUE(form_structure.IsAutofillable(true)); | 
|  | 
| // Expect the correct number of fields. | 
| -  ASSERT_EQ(6U, form_structure->field_count()); | 
| -  ASSERT_EQ(6U, form_structure->autofill_count()); | 
| - | 
| -  EXPECT_EQ(NAME_FIRST, form_structure->field(0)->heuristic_type()); | 
| -  EXPECT_EQ(ASCIIToUTF16("shipping-default"), | 
| -            form_structure->field(0)->section()); | 
| -  EXPECT_EQ(NAME_LAST, form_structure->field(1)->heuristic_type()); | 
| -  EXPECT_EQ(ASCIIToUTF16("-default"), form_structure->field(1)->section()); | 
| -  EXPECT_EQ(ADDRESS_HOME_LINE1, form_structure->field(2)->heuristic_type()); | 
| -  EXPECT_EQ(ASCIIToUTF16("foo-default"), form_structure->field(2)->section()); | 
| -  EXPECT_EQ(ADDRESS_HOME_LINE2, form_structure->field(3)->heuristic_type()); | 
| -  EXPECT_EQ(ASCIIToUTF16("-default"), form_structure->field(3)->section()); | 
| -  EXPECT_EQ(ADDRESS_HOME_CITY, form_structure->field(4)->heuristic_type()); | 
| -  EXPECT_EQ(ASCIIToUTF16("-shipping-default"), | 
| -            form_structure->field(4)->section()); | 
| -  EXPECT_EQ(CREDIT_CARD_NUMBER, form_structure->field(5)->heuristic_type()); | 
| -  EXPECT_EQ(ASCIIToUTF16("shipping-cc"), form_structure->field(5)->section()); | 
| +  ASSERT_EQ(9U, form_structure.field_count()); | 
| +  EXPECT_EQ(9U, form_structure.autofill_count()); | 
| + | 
| +  // All of the fields in this form should be parsed as belonging to different | 
| +  // sections. | 
| +  std::set<std::string> section_names; | 
| +  for (size_t i = 0; i < 9; ++i) { | 
| +    section_names.insert(form_structure.field(i)->section()); | 
| +  } | 
| +  EXPECT_EQ(9U, section_names.size()); | 
| } | 
|  | 
| -// Verify that we can correctly process fallback types listed in the | 
| -// |autocompletetype| attribute. | 
| -TEST(FormStructureTest, HeuristicsAutocompletetypeWithFallbacks) { | 
| -  scoped_ptr<FormStructure> form_structure; | 
| +// Verify that we can correctly process a degenerate section listed in the | 
| +// |autocomplete| attribute. | 
| +TEST(FormStructureTest, HeuristicsAutocompleteAttributeWithSectionsDegenerate) { | 
| FormData form; | 
| form.method = ASCIIToUTF16("post"); | 
|  | 
| FormFieldData field; | 
| -  field.form_control_type = ASCIIToUTF16("text"); | 
| +  field.form_control_type = "text"; | 
|  | 
| -  // Skip over any sections and "x"-prefixed types. | 
| -  field.label = string16(); | 
| -  field.name = ASCIIToUTF16("field1"); | 
| -  field.autocomplete_type = | 
| -      ASCIIToUTF16("section-full-name x-given-name-initial given-name"); | 
| +  // Some fields will have no section specified.  These fall into the default | 
| +  // section. | 
| +  field.autocomplete_attribute = "email"; | 
| form.fields.push_back(field); | 
|  | 
| -  // Stop processing once we see a known type. | 
| -  field.label = string16(); | 
| -  field.name = ASCIIToUTF16("field2"); | 
| -  field.autocomplete_type = ASCIIToUTF16("section-full-name surname full-name"); | 
| +  // Specifying "section-" is equivalent to not specifying a section. | 
| +  field.autocomplete_attribute = "section- email"; | 
| form.fields.push_back(field); | 
|  | 
| -  // Skip over unknown types even if they are not prefixed with "x-". | 
| -  field.label = string16(); | 
| -  field.name = ASCIIToUTF16("field3"); | 
| -  field.autocomplete_type = | 
| -      ASCIIToUTF16("section-shipping mobile-phone-full phone-full"); | 
| +  // Invalid tokens should prevent us from setting a section name. | 
| +  field.autocomplete_attribute = "garbage section-foo email"; | 
| +  form.fields.push_back(field); | 
| +  field.autocomplete_attribute = "garbage section-bar email"; | 
| +  form.fields.push_back(field); | 
| +  field.autocomplete_attribute = "garbage shipping email"; | 
| +  form.fields.push_back(field); | 
| +  field.autocomplete_attribute = "garbage billing email"; | 
| form.fields.push_back(field); | 
|  | 
| -  form_structure.reset(new FormStructure(form)); | 
| -  form_structure->DetermineHeuristicTypes(); | 
| -  EXPECT_TRUE(form_structure->IsAutofillable(true)); | 
| +  FormStructure form_structure(form); | 
| +  form_structure.DetermineHeuristicTypes(); | 
|  | 
| // Expect the correct number of fields. | 
| -  ASSERT_EQ(3U, form_structure->field_count()); | 
| -  ASSERT_EQ(3U, form_structure->autofill_count()); | 
| +  ASSERT_EQ(6U, form_structure.field_count()); | 
| +  EXPECT_EQ(2U, form_structure.autofill_count()); | 
| + | 
| +  // All of the fields in this form should be parsed as belonging to the same | 
| +  // section. | 
| +  std::set<std::string> section_names; | 
| +  for (size_t i = 0; i < 6; ++i) { | 
| +    section_names.insert(form_structure.field(i)->section()); | 
| +  } | 
| +  EXPECT_EQ(1U, section_names.size()); | 
| +} | 
|  | 
| -  EXPECT_EQ(NAME_FIRST, form_structure->field(0)->heuristic_type()); | 
| -  EXPECT_EQ(ASCIIToUTF16("full-name-default"), | 
| -            form_structure->field(0)->section()); | 
| -  EXPECT_EQ(NAME_LAST, form_structure->field(1)->heuristic_type()); | 
| -  EXPECT_EQ(ASCIIToUTF16("full-name-default"), | 
| -            form_structure->field(1)->section()); | 
| -  EXPECT_EQ(PHONE_HOME_WHOLE_NUMBER, | 
| -            form_structure->field(2)->heuristic_type()); | 
| -  EXPECT_EQ(ASCIIToUTF16("shipping-default"), | 
| -            form_structure->field(2)->section()); | 
| +// Verify that we can correctly process repeated sections listed in the | 
| +// |autocomplete| attribute. | 
| +TEST(FormStructureTest, HeuristicsAutocompleteAttributeWithSectionsRepeated) { | 
| +  FormData form; | 
| +  form.method = ASCIIToUTF16("post"); | 
| + | 
| +  FormFieldData field; | 
| +  field.form_control_type = "text"; | 
| + | 
| +  field.autocomplete_attribute = "section-foo email"; | 
| +  form.fields.push_back(field); | 
| +  field.autocomplete_attribute = "section-foo street-address"; | 
| +  form.fields.push_back(field); | 
| + | 
| +  FormStructure form_structure(form); | 
| +  form_structure.DetermineHeuristicTypes(); | 
| + | 
| +  // Expect the correct number of fields. | 
| +  ASSERT_EQ(2U, form_structure.field_count()); | 
| +  EXPECT_EQ(2U, form_structure.autofill_count()); | 
| + | 
| +  // All of the fields in this form should be parsed as belonging to the same | 
| +  // section. | 
| +  std::set<std::string> section_names; | 
| +  for (size_t i = 0; i < 2; ++i) { | 
| +    section_names.insert(form_structure.field(i)->section()); | 
| +  } | 
| +  EXPECT_EQ(1U, section_names.size()); | 
| +} | 
| + | 
| +// Verify that we do not override the author-specified sections from a form with | 
| +// local heuristics. | 
| +TEST(FormStructureTest, HeuristicsDontOverrideAutocompleteAttributeSections) { | 
| +  FormData form; | 
| +  form.method = ASCIIToUTF16("post"); | 
| + | 
| +  FormFieldData field; | 
| +  field.form_control_type = "text"; | 
| + | 
| +  field.name = ASCIIToUTF16("one"); | 
| +  field.autocomplete_attribute = "street-address"; | 
| +  form.fields.push_back(field); | 
| +  field.name = string16(); | 
| +  field.autocomplete_attribute = "section-foo email"; | 
| +  form.fields.push_back(field); | 
| +  field.name = string16(); | 
| +  field.autocomplete_attribute = "name"; | 
| +  form.fields.push_back(field); | 
| +  field.name = ASCIIToUTF16("two"); | 
| +  field.autocomplete_attribute = "street-address"; | 
| +  form.fields.push_back(field); | 
| + | 
| +  FormStructure form_structure(form); | 
| +  form_structure.DetermineHeuristicTypes(); | 
| + | 
| +  // Expect the correct number of fields. | 
| +  ASSERT_EQ(4U, form_structure.field_count()); | 
| +  EXPECT_EQ(4U, form_structure.autofill_count()); | 
| + | 
| +  // Normally, the two separate address fields would cause us to detect two | 
| +  // separate sections; but because there is an author-specified section in this | 
| +  // form, we do not apply these usual heuristics. | 
| +  EXPECT_EQ(ASCIIToUTF16("one"), form_structure.field(0)->name); | 
| +  EXPECT_EQ(ASCIIToUTF16("two"), form_structure.field(3)->name); | 
| +  EXPECT_EQ(form_structure.field(0)->section(), | 
| +            form_structure.field(3)->section()); | 
| } | 
|  | 
| TEST(FormStructureTest, HeuristicsSample8) { | 
| @@ -587,7 +641,7 @@ TEST(FormStructureTest, HeuristicsSample8) { | 
| form.method = ASCIIToUTF16("post"); | 
|  | 
| FormFieldData field; | 
| -  field.form_control_type = ASCIIToUTF16("text"); | 
| +  field.form_control_type = "text"; | 
|  | 
| field.label = ASCIIToUTF16("Your First Name:"); | 
| field.name = ASCIIToUTF16("bill.first"); | 
| @@ -627,7 +681,7 @@ TEST(FormStructureTest, HeuristicsSample8) { | 
|  | 
| field.label = string16(); | 
| field.name = ASCIIToUTF16("Submit"); | 
| -  field.form_control_type = ASCIIToUTF16("submit"); | 
| +  field.form_control_type = "submit"; | 
| form.fields.push_back(field); | 
|  | 
| form_structure.reset(new FormStructure(form)); | 
| @@ -666,7 +720,7 @@ TEST(FormStructureTest, HeuristicsSample6) { | 
| form.method = ASCIIToUTF16("post"); | 
|  | 
| FormFieldData field; | 
| -  field.form_control_type = ASCIIToUTF16("text"); | 
| +  field.form_control_type = "text"; | 
|  | 
| field.label = ASCIIToUTF16("E-mail address"); | 
| field.name = ASCIIToUTF16("email"); | 
| @@ -695,7 +749,7 @@ TEST(FormStructureTest, HeuristicsSample6) { | 
| field.label = string16(); | 
| field.name = ASCIIToUTF16("Submit"); | 
| field.value = ASCIIToUTF16("continue"); | 
| -  field.form_control_type = ASCIIToUTF16("submit"); | 
| +  field.form_control_type = "submit"; | 
| form.fields.push_back(field); | 
|  | 
| form_structure.reset(new FormStructure(form)); | 
| @@ -729,7 +783,7 @@ TEST(FormStructureTest, HeuristicsLabelsOnly) { | 
| form.method = ASCIIToUTF16("post"); | 
|  | 
| FormFieldData field; | 
| -  field.form_control_type = ASCIIToUTF16("text"); | 
| +  field.form_control_type = "text"; | 
|  | 
| field.label = ASCIIToUTF16("First Name"); | 
| field.name = string16(); | 
| @@ -761,7 +815,7 @@ TEST(FormStructureTest, HeuristicsLabelsOnly) { | 
|  | 
| field.label = string16(); | 
| field.name = ASCIIToUTF16("Submit"); | 
| -  field.form_control_type = ASCIIToUTF16("submit"); | 
| +  field.form_control_type = "submit"; | 
| form.fields.push_back(field); | 
|  | 
| form_structure.reset(new FormStructure(form)); | 
| @@ -795,7 +849,7 @@ TEST(FormStructureTest, HeuristicsCreditCardInfo) { | 
| form.method = ASCIIToUTF16("post"); | 
|  | 
| FormFieldData field; | 
| -  field.form_control_type = ASCIIToUTF16("text"); | 
| +  field.form_control_type = "text"; | 
|  | 
| field.label = ASCIIToUTF16("Name on Card"); | 
| field.name = ASCIIToUTF16("name_on_card"); | 
| @@ -819,7 +873,7 @@ TEST(FormStructureTest, HeuristicsCreditCardInfo) { | 
|  | 
| field.label = string16(); | 
| field.name = ASCIIToUTF16("Submit"); | 
| -  field.form_control_type = ASCIIToUTF16("submit"); | 
| +  field.form_control_type = "submit"; | 
| form.fields.push_back(field); | 
|  | 
| form_structure.reset(new FormStructure(form)); | 
| @@ -849,7 +903,7 @@ TEST(FormStructureTest, HeuristicsCreditCardInfoWithUnknownCardField) { | 
| form.method = ASCIIToUTF16("post"); | 
|  | 
| FormFieldData field; | 
| -  field.form_control_type = ASCIIToUTF16("text"); | 
| +  field.form_control_type = "text"; | 
|  | 
| field.label = ASCIIToUTF16("Name on Card"); | 
| field.name = ASCIIToUTF16("name_on_card"); | 
| @@ -879,7 +933,7 @@ TEST(FormStructureTest, HeuristicsCreditCardInfoWithUnknownCardField) { | 
|  | 
| field.label = string16(); | 
| field.name = ASCIIToUTF16("Submit"); | 
| -  field.form_control_type = ASCIIToUTF16("submit"); | 
| +  field.form_control_type = "submit"; | 
| form.fields.push_back(field); | 
|  | 
| form_structure.reset(new FormStructure(form)); | 
| @@ -911,7 +965,7 @@ TEST(FormStructureTest, ThreeAddressLines) { | 
| form.method = ASCIIToUTF16("post"); | 
|  | 
| FormFieldData field; | 
| -  field.form_control_type = ASCIIToUTF16("text"); | 
| +  field.form_control_type = "text"; | 
|  | 
| field.label = ASCIIToUTF16("Address Line1"); | 
| field.name = ASCIIToUTF16("Address"); | 
| @@ -953,7 +1007,7 @@ TEST(FormStructureTest, BillingAndShippingAddresses) { | 
| form.method = ASCIIToUTF16("post"); | 
|  | 
| FormFieldData field; | 
| -  field.form_control_type = ASCIIToUTF16("text"); | 
| +  field.form_control_type = "text"; | 
|  | 
| field.label = ASCIIToUTF16("Address Line1"); | 
| field.name = ASCIIToUTF16("shipping.address.addressLine1"); | 
| @@ -999,7 +1053,7 @@ TEST(FormStructureTest, ThreeAddressLinesExpedia) { | 
| form.method = ASCIIToUTF16("post"); | 
|  | 
| FormFieldData field; | 
| -  field.form_control_type = ASCIIToUTF16("text"); | 
| +  field.form_control_type = "text"; | 
|  | 
| field.label = ASCIIToUTF16("Street:"); | 
| field.name = ASCIIToUTF16("FOPIH_RgWebCC_0_IHAddress_ads1"); | 
| @@ -1042,7 +1096,7 @@ TEST(FormStructureTest, TwoAddressLinesEbay) { | 
| form.method = ASCIIToUTF16("post"); | 
|  | 
| FormFieldData field; | 
| -  field.form_control_type = ASCIIToUTF16("text"); | 
| +  field.form_control_type = "text"; | 
|  | 
| field.label = ASCIIToUTF16("Address Line1"); | 
| field.name = ASCIIToUTF16("address1"); | 
| @@ -1076,7 +1130,7 @@ TEST(FormStructureTest, HeuristicsStateWithProvince) { | 
| form.method = ASCIIToUTF16("post"); | 
|  | 
| FormFieldData field; | 
| -  field.form_control_type = ASCIIToUTF16("text"); | 
| +  field.form_control_type = "text"; | 
|  | 
| field.label = ASCIIToUTF16("Address Line1"); | 
| field.name = ASCIIToUTF16("Address"); | 
| @@ -1111,7 +1165,7 @@ TEST(FormStructureTest, HeuristicsWithBilling) { | 
| form.method = ASCIIToUTF16("post"); | 
|  | 
| FormFieldData field; | 
| -  field.form_control_type = ASCIIToUTF16("text"); | 
| +  field.form_control_type = "text"; | 
|  | 
| field.label = ASCIIToUTF16("First Name*:"); | 
| field.name = ASCIIToUTF16("editBillingAddress$firstNameBox"); | 
| @@ -1184,7 +1238,7 @@ TEST(FormStructureTest, ThreePartPhoneNumber) { | 
| form.method = ASCIIToUTF16("post"); | 
|  | 
| FormFieldData field; | 
| -  field.form_control_type = ASCIIToUTF16("text"); | 
| +  field.form_control_type = "text"; | 
|  | 
| field.label = ASCIIToUTF16("Phone:"); | 
| field.name = ASCIIToUTF16("dayphone1"); | 
| @@ -1232,7 +1286,7 @@ TEST(FormStructureTest, HeuristicsInfernoCC) { | 
| form.method = ASCIIToUTF16("post"); | 
|  | 
| FormFieldData field; | 
| -  field.form_control_type = ASCIIToUTF16("text"); | 
| +  field.form_control_type = "text"; | 
|  | 
| field.label = ASCIIToUTF16("Name on Card"); | 
| field.name = ASCIIToUTF16("name_on_card"); | 
| @@ -1281,7 +1335,7 @@ TEST(FormStructureTest, CVCCodeClash) { | 
| form.method = ASCIIToUTF16("post"); | 
|  | 
| FormFieldData field; | 
| -  field.form_control_type = ASCIIToUTF16("text"); | 
| +  field.form_control_type = "text"; | 
|  | 
| field.label = ASCIIToUTF16("Card number"); | 
| field.name = ASCIIToUTF16("ccnumber"); | 
| @@ -1335,7 +1389,7 @@ TEST(FormStructureTest, EncodeQueryRequest) { | 
| form.method = ASCIIToUTF16("post"); | 
|  | 
| FormFieldData field; | 
| -  field.form_control_type = ASCIIToUTF16("text"); | 
| +  field.form_control_type = "text"; | 
|  | 
| field.label = ASCIIToUTF16("Name on Card"); | 
| field.name = ASCIIToUTF16("name_on_card"); | 
| @@ -1450,7 +1504,7 @@ TEST(FormStructureTest, EncodeUploadRequest) { | 
| form_structure->DetermineHeuristicTypes(); | 
|  | 
| FormFieldData field; | 
| -  field.form_control_type = ASCIIToUTF16("text"); | 
| +  field.form_control_type = "text"; | 
|  | 
| field.label = ASCIIToUTF16("First Name"); | 
| field.name = ASCIIToUTF16("firstname"); | 
| @@ -1466,21 +1520,21 @@ TEST(FormStructureTest, EncodeUploadRequest) { | 
|  | 
| field.label = ASCIIToUTF16("Email"); | 
| field.name = ASCIIToUTF16("email"); | 
| -  field.form_control_type = ASCIIToUTF16("email"); | 
| +  field.form_control_type = "email"; | 
| form.fields.push_back(field); | 
| possible_field_types.push_back(FieldTypeSet()); | 
| possible_field_types.back().insert(EMAIL_ADDRESS); | 
|  | 
| field.label = ASCIIToUTF16("Phone"); | 
| field.name = ASCIIToUTF16("phone"); | 
| -  field.form_control_type = ASCIIToUTF16("number"); | 
| +  field.form_control_type = "number"; | 
| form.fields.push_back(field); | 
| possible_field_types.push_back(FieldTypeSet()); | 
| possible_field_types.back().insert(PHONE_HOME_WHOLE_NUMBER); | 
|  | 
| field.label = ASCIIToUTF16("Country"); | 
| field.name = ASCIIToUTF16("country"); | 
| -  field.form_control_type = ASCIIToUTF16("select-one"); | 
| +  field.form_control_type = "select-one"; | 
| form.fields.push_back(field); | 
| possible_field_types.push_back(FieldTypeSet()); | 
| possible_field_types.back().insert(ADDRESS_HOME_COUNTRY); | 
| @@ -1533,7 +1587,7 @@ TEST(FormStructureTest, EncodeUploadRequest) { | 
| for (size_t i = 0; i < 2; ++i) { | 
| field.label = ASCIIToUTF16("Address"); | 
| field.name = ASCIIToUTF16("address"); | 
| -    field.form_control_type = ASCIIToUTF16("text"); | 
| +    field.form_control_type = "text"; | 
| form.fields.push_back(field); | 
| possible_field_types.push_back(FieldTypeSet()); | 
| possible_field_types.back().insert(ADDRESS_HOME_LINE1); | 
| @@ -1573,7 +1627,7 @@ TEST(FormStructureTest, EncodeUploadRequest) { | 
| for (size_t i = 0; i < 50; ++i) { | 
| field.label = ASCIIToUTF16("Address"); | 
| field.name = ASCIIToUTF16("address"); | 
| -    field.form_control_type = ASCIIToUTF16("text"); | 
| +    field.form_control_type = "text"; | 
| form.fields.push_back(field); | 
| possible_field_types.push_back(FieldTypeSet()); | 
| possible_field_types.back().insert(ADDRESS_HOME_LINE1); | 
| @@ -1596,7 +1650,7 @@ TEST(FormStructureTest, CheckDataPresence) { | 
| form.method = ASCIIToUTF16("post"); | 
|  | 
| FormFieldData field; | 
| -  field.form_control_type = ASCIIToUTF16("text"); | 
| +  field.form_control_type = "text"; | 
|  | 
| field.label = ASCIIToUTF16("First Name"); | 
| field.name = ASCIIToUTF16("first"); | 
| @@ -1850,7 +1904,7 @@ TEST(FormStructureTest, CheckMultipleTypes) { | 
| form.method = ASCIIToUTF16("post"); | 
|  | 
| FormFieldData field; | 
| -  field.form_control_type = ASCIIToUTF16("text"); | 
| +  field.form_control_type = "text"; | 
|  | 
| field.label = ASCIIToUTF16("email"); | 
| field.name = ASCIIToUTF16("email"); | 
| @@ -1956,7 +2010,7 @@ TEST(FormStructureTest, CheckFormSignature) { | 
| form.method = ASCIIToUTF16("post"); | 
|  | 
| FormFieldData field; | 
| -  field.form_control_type = ASCIIToUTF16("text"); | 
| +  field.form_control_type = "text"; | 
|  | 
| field.label = ASCIIToUTF16("email"); | 
| field.name = ASCIIToUTF16("email"); | 
|  |