| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/autofill/autofill_manager.h" | 5 #include "chrome/browser/autofill/autofill_manager.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include <limits> | 9 #include <limits> |
| 10 #include <map> | 10 #include <map> |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 91 unique_ids_copy.push_back((*unique_ids)[i]); | 91 unique_ids_copy.push_back((*unique_ids)[i]); |
| 92 } | 92 } |
| 93 } | 93 } |
| 94 | 94 |
| 95 values->swap(values_copy); | 95 values->swap(values_copy); |
| 96 labels->swap(labels_copy); | 96 labels->swap(labels_copy); |
| 97 icons->swap(icons_copy); | 97 icons->swap(icons_copy); |
| 98 unique_ids->swap(unique_ids_copy); | 98 unique_ids->swap(unique_ids_copy); |
| 99 } | 99 } |
| 100 | 100 |
| 101 // Precondition: |form| should be the cached version of the form that is to be | |
| 102 // autofilled, and |field| should be the field in the |form| that corresponds to | |
| 103 // the initiating field. |is_filling_credit_card| should be true if filling | |
| 104 // credit card data, false otherwise. | |
| 105 // Fills |section_start| and |section_end| so that [section_start, section_end) | |
| 106 // gives the bounds of logical section within |form| that includes |field|. | |
| 107 // Logical sections are identified by two heuristics: | |
| 108 // 1. The fields in the section must all be profile or credit card fields, | |
| 109 // depending on whether |is_filling_credit_card| is true. | |
| 110 // 2. A logical section should not include multiple fields of the same autofill | |
| 111 // type (except for adjacent repeated fields and phone/fax numbers, as | |
| 112 // described below). | |
| 113 void FindSectionBounds(const FormStructure& form, | |
| 114 const AutofillField& field, | |
| 115 bool is_filling_credit_card, | |
| 116 size_t* section_start, | |
| 117 size_t* section_end) { | |
| 118 DCHECK(section_start); | |
| 119 DCHECK(section_end); | |
| 120 | |
| 121 // By default, the relevant section is the entire form. | |
| 122 *section_start = 0; | |
| 123 *section_end = form.field_count(); | |
| 124 | |
| 125 std::set<AutofillFieldType> seen_types; | |
| 126 bool initiating_field_is_in_current_section = false; | |
| 127 AutofillFieldType previous_type = UNKNOWN_TYPE; | |
| 128 for (size_t i = 0; i < form.field_count(); ++i) { | |
| 129 const AutofillField* current_field = form.field(i); | |
| 130 const AutofillFieldType current_type = | |
| 131 AutofillType::GetEquivalentFieldType(current_field->type()); | |
| 132 | |
| 133 bool already_saw_current_type = seen_types.count(current_type) > 0; | |
| 134 // Forms often ask for multiple phone numbers -- e.g. both a daytime and | |
| 135 // evening phone number. Our phone and fax number detection is also | |
| 136 // generally a little off. Hence, ignore both field types as a signal here. | |
| 137 AutofillType::FieldTypeGroup current_type_group = | |
| 138 AutofillType(current_type).group(); | |
| 139 if (current_type_group == AutofillType::PHONE_HOME || | |
| 140 current_type_group == AutofillType::PHONE_FAX) | |
| 141 already_saw_current_type = false; | |
| 142 | |
| 143 // Some forms have adjacent fields of the same type. Two common examples: | |
| 144 // * Forms with two email fields, where the second is meant to "confirm" | |
| 145 // the first. | |
| 146 // * Forms with a <select> menu for states in some countries, and a | |
| 147 // freeform <input> field for states in other countries. (Usually, only | |
| 148 // one of these two will be visible for any given choice of country.) | |
| 149 // Generally, adjacent fields of the same type belong in the same logical | |
| 150 // section. | |
| 151 if (current_type == previous_type) | |
| 152 already_saw_current_type = false; | |
| 153 | |
| 154 previous_type = current_type; | |
| 155 | |
| 156 // Fields of unknown type don't help us to distinguish sections. | |
| 157 if (current_type == UNKNOWN_TYPE) | |
| 158 continue; | |
| 159 | |
| 160 // If we are filling credit card data, the relevant section should include | |
| 161 // only credit card fields; and similarly for profile data. | |
| 162 bool is_credit_card_field = current_type_group == AutofillType::CREDIT_CARD; | |
| 163 bool is_appropriate_type = is_credit_card_field == is_filling_credit_card; | |
| 164 | |
| 165 if (already_saw_current_type || !is_appropriate_type) { | |
| 166 if (initiating_field_is_in_current_section) { | |
| 167 // We reached the end of the section containing the initiating field. | |
| 168 *section_end = i; | |
| 169 break; | |
| 170 } | |
| 171 | |
| 172 // We reached the end of a section, so start a new section. | |
| 173 seen_types.clear(); | |
| 174 | |
| 175 // Only include the current field in the new section if it matches the | |
| 176 // type of data we are filling. | |
| 177 if (is_appropriate_type) { | |
| 178 *section_start = i; | |
| 179 } else { | |
| 180 *section_start = i + 1; | |
| 181 continue; | |
| 182 } | |
| 183 } | |
| 184 | |
| 185 seen_types.insert(current_type); | |
| 186 | |
| 187 if (current_field == &field) | |
| 188 initiating_field_is_in_current_section = true; | |
| 189 } | |
| 190 | |
| 191 // We should have found the initiating field. | |
| 192 DCHECK(initiating_field_is_in_current_section); | |
| 193 } | |
| 194 | |
| 195 // Precondition: |form_structure| and |form| should correspond to the same | 101 // Precondition: |form_structure| and |form| should correspond to the same |
| 196 // logical form. Returns true if the relevant portion of |form| is auto-filled. | 102 // logical form. Returns true if any field in the given |section| within |form| |
| 197 // The "relevant" fields in |form| are ones corresponding to fields in | 103 // is auto-filled. |
| 198 // |form_structure| with indices in the range [section_start, section_end). | |
| 199 bool SectionIsAutofilled(const FormStructure* form_structure, | 104 bool SectionIsAutofilled(const FormStructure* form_structure, |
| 200 const webkit_glue::FormData& form, | 105 const webkit_glue::FormData& form, |
| 201 size_t section_start, | 106 const string16& section) { |
| 202 size_t section_end) { | |
| 203 // TODO(isherman): It would be nice to share most of this code with the loop | 107 // TODO(isherman): It would be nice to share most of this code with the loop |
| 204 // in |FillAutofillFormData()|, but I don't see a particularly clean way to do | 108 // in |OnFillAutofillFormData()|, but I don't see a particularly clean way to |
| 205 // that. | 109 // do that. |
| 206 | 110 |
| 207 // The list of fields in |form_structure| and |form.fields| often match | 111 // The list of fields in |form_structure| and |form.fields| often match |
| 208 // directly and we can fill these corresponding fields; however, when the | 112 // directly and we can fill these corresponding fields; however, when the |
| 209 // |form_structure| and |form.fields| do not match directly we search | 113 // |form_structure| and |form.fields| do not match directly we search |
| 210 // ahead in the |form_structure| for the matching field. | 114 // ahead in the |form_structure| for the matching field. |
| 211 for (size_t i = section_start, j = 0; | 115 for (size_t i = 0, j = 0; |
| 212 i < section_end && j < form.fields.size(); | 116 i < form_structure->field_count() && j < form.fields.size(); |
| 213 j++) { | 117 j++) { |
| 214 size_t k = i; | 118 size_t k = i; |
| 215 | 119 |
| 216 // Search forward in the |form_structure| for a corresponding field. | 120 // Search forward in the |form_structure| for a corresponding field. |
| 217 while (k < form_structure->field_count() && | 121 while (k < form_structure->field_count() && |
| 218 *form_structure->field(k) != form.fields[j]) { | 122 (form_structure->field(k)->section() != section || |
| 123 *form_structure->field(k) != form.fields[j])) { |
| 219 k++; | 124 k++; |
| 220 } | 125 } |
| 221 | 126 |
| 222 // If we didn't find a match, continue on to the next |form| field. | 127 // If we didn't find a match, continue on to the next |form| field. |
| 223 if (k >= form_structure->field_count()) | 128 if (k >= form_structure->field_count()) |
| 224 continue; | 129 continue; |
| 225 | 130 |
| 226 AutofillType autofill_type(form_structure->field(k)->type()); | |
| 227 if (form.fields[j].is_autofilled) | 131 if (form.fields[j].is_autofilled) |
| 228 return true; | 132 return true; |
| 229 | 133 |
| 230 // We found a matching field in the |form_structure| so we | 134 // We found a matching field in the |form_structure|, so on the next |
| 231 // proceed to the next |form| field, and the next |form_structure|. | 135 // iteration we should proceed to the next |form_structure| field. |
| 232 ++i; | 136 ++i; |
| 233 } | 137 } |
| 234 | 138 |
| 235 return false; | 139 return false; |
| 236 } | 140 } |
| 237 | 141 |
| 238 bool FormIsHTTPS(FormStructure* form) { | 142 bool FormIsHTTPS(FormStructure* form) { |
| 239 return form->source_url().SchemeIs(chrome::kHttpsScheme); | 143 return form->source_url().SchemeIs(chrome::kHttpsScheme); |
| 240 } | 144 } |
| 241 | 145 |
| (...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 488 if (!form_structure->IsAutofillable(true)) | 392 if (!form_structure->IsAutofillable(true)) |
| 489 warning = IDS_AUTOFILL_WARNING_FORM_DISABLED; | 393 warning = IDS_AUTOFILL_WARNING_FORM_DISABLED; |
| 490 else if (is_filling_credit_card && !FormIsHTTPS(form_structure)) | 394 else if (is_filling_credit_card && !FormIsHTTPS(form_structure)) |
| 491 warning = IDS_AUTOFILL_WARNING_INSECURE_CONNECTION; | 395 warning = IDS_AUTOFILL_WARNING_INSECURE_CONNECTION; |
| 492 if (warning) { | 396 if (warning) { |
| 493 values.assign(1, l10n_util::GetStringUTF16(warning)); | 397 values.assign(1, l10n_util::GetStringUTF16(warning)); |
| 494 labels.assign(1, string16()); | 398 labels.assign(1, string16()); |
| 495 icons.assign(1, string16()); | 399 icons.assign(1, string16()); |
| 496 unique_ids.assign(1, -1); | 400 unique_ids.assign(1, -1); |
| 497 } else { | 401 } else { |
| 498 size_t section_start, section_end; | 402 bool section_is_autofilled = |
| 499 FindSectionBounds(*form_structure, *autofill_field, | 403 SectionIsAutofilled(form_structure, form, |
| 500 is_filling_credit_card, §ion_start, §ion_end); | 404 autofill_field->section()); |
| 501 | |
| 502 bool section_is_autofilled = SectionIsAutofilled(form_structure, | |
| 503 form, | |
| 504 section_start, | |
| 505 section_end); | |
| 506 if (section_is_autofilled) { | 405 if (section_is_autofilled) { |
| 507 // If the relevant section is auto-filled and the renderer is querying | 406 // If the relevant section is auto-filled and the renderer is querying |
| 508 // for suggestions, then the user is editing the value of a field. | 407 // for suggestions, then the user is editing the value of a field. |
| 509 // In this case, mimic autocomplete: don't display labels or icons, | 408 // In this case, mimic autocomplete: don't display labels or icons, |
| 510 // as that information is redundant. | 409 // as that information is redundant. |
| 511 labels.assign(labels.size(), string16()); | 410 labels.assign(labels.size(), string16()); |
| 512 icons.assign(icons.size(), string16()); | 411 icons.assign(icons.size(), string16()); |
| 513 } | 412 } |
| 514 | 413 |
| 515 // When filling credit card suggestions, the values and labels are | 414 // When filling credit card suggestions, the values and labels are |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 583 credit_card = *iter; | 482 credit_card = *iter; |
| 584 break; | 483 break; |
| 585 } | 484 } |
| 586 } | 485 } |
| 587 DCHECK(credit_card); | 486 DCHECK(credit_card); |
| 588 } | 487 } |
| 589 | 488 |
| 590 if (!profile && !credit_card) | 489 if (!profile && !credit_card) |
| 591 return; | 490 return; |
| 592 | 491 |
| 593 // Find the section of the form that we are autofilling. | |
| 594 size_t section_start, section_end; | |
| 595 FindSectionBounds(*form_structure, *autofill_field, (credit_card != NULL), | |
| 596 §ion_start, §ion_end); | |
| 597 | |
| 598 FormData result = form; | 492 FormData result = form; |
| 599 | 493 |
| 600 // If the relevant section is auto-filled, we should fill |field| but not the | 494 // If the relevant section is auto-filled, we should fill |field| but not the |
| 601 // rest of the form. | 495 // rest of the form. |
| 602 if (SectionIsAutofilled(form_structure, form, section_start, section_end)) { | 496 if (SectionIsAutofilled(form_structure, form, autofill_field->section())) { |
| 603 for (std::vector<FormField>::iterator iter = result.fields.begin(); | 497 for (std::vector<FormField>::iterator iter = result.fields.begin(); |
| 604 iter != result.fields.end(); ++iter) { | 498 iter != result.fields.end(); ++iter) { |
| 605 if ((*iter) == field) { | 499 if ((*iter) == field) { |
| 606 AutofillFieldType field_type = autofill_field->type(); | 500 AutofillFieldType field_type = autofill_field->type(); |
| 607 if (profile) { | 501 if (profile) { |
| 608 DCHECK_NE(AutofillType::CREDIT_CARD, | 502 DCHECK_NE(AutofillType::CREDIT_CARD, |
| 609 AutofillType(field_type).group()); | 503 AutofillType(field_type).group()); |
| 610 FillFormField(profile, field_type, profile_guid.second, &(*iter)); | 504 FillFormField(profile, field_type, profile_guid.second, &(*iter)); |
| 611 } else { | 505 } else { |
| 612 DCHECK_EQ(AutofillType::CREDIT_CARD, | 506 DCHECK_EQ(AutofillType::CREDIT_CARD, |
| 613 AutofillType(field_type).group()); | 507 AutofillType(field_type).group()); |
| 614 FillCreditCardFormField(credit_card, field_type, &(*iter)); | 508 FillCreditCardFormField(credit_card, field_type, &(*iter)); |
| 615 } | 509 } |
| 616 break; | 510 break; |
| 617 } | 511 } |
| 618 } | 512 } |
| 619 | 513 |
| 620 host->Send(new AutofillMsg_FormDataFilled(host->routing_id(), query_id, | 514 host->Send(new AutofillMsg_FormDataFilled(host->routing_id(), query_id, |
| 621 result)); | 515 result)); |
| 622 return; | 516 return; |
| 623 } | 517 } |
| 624 | 518 |
| 625 // The list of fields in |form_structure| and |result.fields| often match | 519 // The list of fields in |form_structure| and |result.fields| often match |
| 626 // directly and we can fill these corresponding fields; however, when the | 520 // directly and we can fill these corresponding fields; however, when the |
| 627 // |form_structure| and |result.fields| do not match directly we search | 521 // |form_structure| and |result.fields| do not match directly we search |
| 628 // ahead in the |form_structure| for the matching field. | 522 // ahead in the |form_structure| for the matching field. |
| 629 // See unit tests: AutofillManagerTest.FormChangesRemoveField and | 523 // See unit tests: AutofillManagerTest.FormChangesRemoveField and |
| 630 // AutofillManagerTest.FormChangesAddField for usage. | 524 // AutofillManagerTest.FormChangesAddField for usage. |
| 631 for (size_t i = section_start, j = 0; | 525 for (size_t i = 0, j = 0; |
| 632 i < section_end && j < result.fields.size(); | 526 i < form_structure->field_count() && j < result.fields.size(); |
| 633 j++) { | 527 j++) { |
| 634 size_t k = i; | 528 size_t k = i; |
| 635 | 529 |
| 636 // Search forward in the |form_structure| for a corresponding field. | 530 // Search forward in the |form_structure| for a corresponding field. |
| 637 while (k < section_end && *form_structure->field(k) != result.fields[j]) { | 531 while (k < form_structure->field_count() && |
| 532 (form_structure->field(k)->section() != autofill_field->section() || |
| 533 *form_structure->field(k) != result.fields[j])) { |
| 638 k++; | 534 k++; |
| 639 } | 535 } |
| 640 | 536 |
| 641 // If we've found a match then fill the |result| field with the found | 537 // If we've found a match then fill the |result| field with the found |
| 642 // field in the |form_structure|. | 538 // field in the |form_structure|. |
| 643 if (k >= section_end) | 539 if (k >= form_structure->field_count()) |
| 644 continue; | 540 continue; |
| 645 | 541 |
| 646 AutofillFieldType field_type = form_structure->field(k)->type(); | 542 AutofillFieldType field_type = form_structure->field(k)->type(); |
| 647 FieldTypeGroup field_group_type = AutofillType(field_type).group(); | 543 FieldTypeGroup field_group_type = AutofillType(field_type).group(); |
| 648 if (field_group_type != AutofillType::NO_GROUP) { | 544 if (field_group_type != AutofillType::NO_GROUP) { |
| 649 if (profile) { | 545 if (profile) { |
| 650 DCHECK_NE(AutofillType::CREDIT_CARD, field_group_type); | 546 DCHECK_NE(AutofillType::CREDIT_CARD, field_group_type); |
| 651 // If the field being filled is the field that the user initiated the | 547 // If the field being filled is the field that the user initiated the |
| 652 // fill from, then take the multi-profile "variant" into account. | 548 // fill from, then take the multi-profile "variant" into account. |
| 653 // Otherwise fill with the default (zeroth) variant. | 549 // Otherwise fill with the default (zeroth) variant. |
| 654 if (result.fields[j] == field) { | 550 if (result.fields[j] == field) { |
| 655 FillFormField(profile, field_type, profile_guid.second, | 551 FillFormField(profile, field_type, profile_guid.second, |
| 656 &result.fields[j]); | 552 &result.fields[j]); |
| 657 } else { | 553 } else { |
| 658 FillFormField(profile, field_type, 0, &result.fields[j]); | 554 FillFormField(profile, field_type, 0, &result.fields[j]); |
| 659 } | 555 } |
| 660 } else { | 556 } else { |
| 661 DCHECK_EQ(AutofillType::CREDIT_CARD, field_group_type); | 557 DCHECK_EQ(AutofillType::CREDIT_CARD, field_group_type); |
| 662 FillCreditCardFormField(credit_card, field_type, &result.fields[j]); | 558 FillCreditCardFormField(credit_card, field_type, &result.fields[j]); |
| 663 } | 559 } |
| 664 } | 560 } |
| 665 | 561 |
| 666 // We found a matching field in the |form_structure| so we | 562 // We found a matching field in the |form_structure|, so on the next |
| 667 // proceed to the next |result| field, and the next |form_structure|. | 563 // iteration we should proceed to the next |form_structure| field. |
| 668 ++i; | 564 ++i; |
| 669 } | 565 } |
| 670 | 566 |
| 671 autofilled_form_signatures_.push_front(form_structure->FormSignature()); | 567 autofilled_form_signatures_.push_front(form_structure->FormSignature()); |
| 672 // Only remember the last few forms that we've seen, both to avoid false | 568 // Only remember the last few forms that we've seen, both to avoid false |
| 673 // positives and to avoid wasting memory. | 569 // positives and to avoid wasting memory. |
| 674 if (autofilled_form_signatures_.size() > kMaxRecentFormSignaturesToRemember) | 570 if (autofilled_form_signatures_.size() > kMaxRecentFormSignaturesToRemember) |
| 675 autofilled_form_signatures_.pop_back(); | 571 autofilled_form_signatures_.pop_back(); |
| 676 | 572 |
| 677 host->Send(new AutofillMsg_FormDataFilled( | 573 host->Send(new AutofillMsg_FormDataFilled( |
| (...skipping 492 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1170 void AutofillManager::UnpackGUIDs(int id, | 1066 void AutofillManager::UnpackGUIDs(int id, |
| 1171 GUIDPair* cc_guid, | 1067 GUIDPair* cc_guid, |
| 1172 GUIDPair* profile_guid) { | 1068 GUIDPair* profile_guid) { |
| 1173 int cc_id = id >> std::numeric_limits<unsigned short>::digits & | 1069 int cc_id = id >> std::numeric_limits<unsigned short>::digits & |
| 1174 std::numeric_limits<unsigned short>::max(); | 1070 std::numeric_limits<unsigned short>::max(); |
| 1175 int profile_id = id & std::numeric_limits<unsigned short>::max(); | 1071 int profile_id = id & std::numeric_limits<unsigned short>::max(); |
| 1176 | 1072 |
| 1177 *cc_guid = IDToGUID(cc_id); | 1073 *cc_guid = IDToGUID(cc_id); |
| 1178 *profile_guid = IDToGUID(profile_id); | 1074 *profile_guid = IDToGUID(profile_id); |
| 1179 } | 1075 } |
| OLD | NEW |