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 |