OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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_profile.h" | 5 #include "chrome/browser/autofill/autofill_profile.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <functional> | 8 #include <functional> |
9 #include <map> | 9 #include <map> |
10 #include <ostream> | 10 #include <ostream> |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
115 } | 115 } |
116 return accumulate; | 116 return accumulate; |
117 } | 117 } |
118 | 118 |
119 template <class T> | 119 template <class T> |
120 void CopyValuesToItems(AutofillFieldType type, | 120 void CopyValuesToItems(AutofillFieldType type, |
121 const std::vector<string16>& values, | 121 const std::vector<string16>& values, |
122 std::vector<T>* form_group_items, | 122 std::vector<T>* form_group_items, |
123 const T& prototype) { | 123 const T& prototype) { |
124 form_group_items->resize(values.size(), prototype); | 124 form_group_items->resize(values.size(), prototype); |
125 for (size_t i = 0; i < form_group_items->size(); ++i) | 125 for (size_t i = 0; i < form_group_items->size(); ++i) { |
126 (*form_group_items)[i].SetInfo(type, CollapseWhitespace(values[i], false)); | 126 (*form_group_items)[i].SetRawInfo(type, |
127 CollapseWhitespace(values[i], false)); | |
128 } | |
127 // Must have at least one (possibly empty) element. | 129 // Must have at least one (possibly empty) element. |
128 if (form_group_items->empty()) | 130 if (form_group_items->empty()) |
129 form_group_items->resize(1, prototype); | 131 form_group_items->resize(1, prototype); |
130 } | 132 } |
131 | 133 |
132 template <class T> | 134 template <class T> |
133 void CopyItemsToValues(AutofillFieldType type, | 135 void CopyItemsToValues(AutofillFieldType type, |
134 const std::vector<T>& form_group_items, | 136 const std::vector<T>& form_group_items, |
135 bool canonicalize, | 137 bool canonicalize, |
136 std::vector<string16>* values) { | 138 std::vector<string16>* values) { |
137 values->resize(form_group_items.size()); | 139 values->resize(form_group_items.size()); |
138 for (size_t i = 0; i < values->size(); ++i) { | 140 for (size_t i = 0; i < values->size(); ++i) { |
139 if (canonicalize) | 141 if (canonicalize) |
140 (*values)[i] = form_group_items[i].GetCanonicalizedInfo(type); | 142 (*values)[i] = form_group_items[i].GetCanonicalizedInfo(type); |
141 else | 143 else |
142 (*values)[i] = form_group_items[i].GetInfo(type); | 144 (*values)[i] = form_group_items[i].GetRawInfo(type); |
143 } | 145 } |
144 } | 146 } |
145 | 147 |
146 // Collapse compound field types to their "full" type. I.e. First name | 148 // Collapse compound field types to their "full" type. I.e. First name |
147 // collapses to full name, area code collapses to full phone, etc. | 149 // collapses to full name, area code collapses to full phone, etc. |
148 void CollapseCompoundFieldTypes(FieldTypeSet* type_set) { | 150 void CollapseCompoundFieldTypes(FieldTypeSet* type_set) { |
149 FieldTypeSet collapsed_set; | 151 FieldTypeSet collapsed_set; |
150 for (FieldTypeSet::iterator iter = type_set->begin(); iter != type_set->end(); | 152 for (FieldTypeSet::iterator iter = type_set->begin(); iter != type_set->end(); |
151 ++iter) { | 153 ++iter) { |
152 switch (*iter) { | 154 switch (*iter) { |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
255 } | 257 } |
256 | 258 |
257 void AutofillProfile::GetMatchingTypes(const string16& text, | 259 void AutofillProfile::GetMatchingTypes(const string16& text, |
258 FieldTypeSet* matching_types) const { | 260 FieldTypeSet* matching_types) const { |
259 FormGroupList info = FormGroups(); | 261 FormGroupList info = FormGroups(); |
260 for (FormGroupList::const_iterator it = info.begin(); it != info.end(); ++it) | 262 for (FormGroupList::const_iterator it = info.begin(); it != info.end(); ++it) |
261 (*it)->GetMatchingTypes(text, matching_types); | 263 (*it)->GetMatchingTypes(text, matching_types); |
262 } | 264 } |
263 | 265 |
264 | 266 |
265 string16 AutofillProfile::GetInfo(AutofillFieldType type) const { | 267 string16 AutofillProfile::GetRawInfo(AutofillFieldType type) const { |
266 AutofillFieldType return_type = AutofillType::GetEquivalentFieldType(type); | 268 AutofillFieldType return_type = AutofillType::GetEquivalentFieldType(type); |
267 const FormGroup* form_group = FormGroupForType(return_type); | 269 const FormGroup* form_group = FormGroupForType(return_type); |
268 if (!form_group) | 270 if (!form_group) |
269 return string16(); | 271 return string16(); |
270 | 272 |
271 return form_group->GetInfo(return_type); | 273 return form_group->GetRawInfo(return_type); |
272 } | 274 } |
273 | 275 |
274 void AutofillProfile::SetInfo(AutofillFieldType type, const string16& value) { | 276 void AutofillProfile::SetRawInfo(AutofillFieldType type, |
277 const string16& value) { | |
275 FormGroup* form_group = MutableFormGroupForType(type); | 278 FormGroup* form_group = MutableFormGroupForType(type); |
276 if (form_group) | 279 if (form_group) |
277 form_group->SetInfo(type, CollapseWhitespace(value, false)); | 280 form_group->SetRawInfo(type, CollapseWhitespace(value, false)); |
278 } | 281 } |
279 | 282 |
280 string16 AutofillProfile::GetCanonicalizedInfo(AutofillFieldType type) const { | 283 string16 AutofillProfile::GetCanonicalizedInfo(AutofillFieldType type) const { |
281 AutofillFieldType return_type = AutofillType::GetEquivalentFieldType(type); | 284 AutofillFieldType return_type = AutofillType::GetEquivalentFieldType(type); |
282 const FormGroup* form_group = FormGroupForType(return_type); | 285 const FormGroup* form_group = FormGroupForType(return_type); |
283 if (!form_group) | 286 if (!form_group) |
284 return string16(); | 287 return string16(); |
285 | 288 |
286 return form_group->GetCanonicalizedInfo(return_type); | 289 return form_group->GetCanonicalizedInfo(return_type); |
287 } | 290 } |
(...skipping 19 matching lines...) Expand all Loading... | |
307 CopyValuesToItems(type, values, &email_, EmailInfo()); | 310 CopyValuesToItems(type, values, &email_, EmailInfo()); |
308 break; | 311 break; |
309 case AutofillType::PHONE: | 312 case AutofillType::PHONE: |
310 CopyValuesToItems(type, | 313 CopyValuesToItems(type, |
311 values, | 314 values, |
312 &home_number_, | 315 &home_number_, |
313 PhoneNumber(this)); | 316 PhoneNumber(this)); |
314 break; | 317 break; |
315 default: | 318 default: |
316 if (values.size() == 1) { | 319 if (values.size() == 1) { |
317 SetInfo(type, values[0]); | 320 SetRawInfo(type, values[0]); |
318 } else if (values.size() == 0) { | 321 } else if (values.size() == 0) { |
319 SetInfo(type, string16()); | 322 SetRawInfo(type, string16()); |
320 } else { | 323 } else { |
321 NOTREACHED() | 324 NOTREACHED() |
322 << "Attempt to set multiple values on single-valued field."; | 325 << "Attempt to set multiple values on single-valued field."; |
Dan Beam
2012/11/09 18:46:30
nit: remove string?
Ilya Sherman
2012/11/10 03:21:33
Done.
| |
323 } | 326 } |
324 break; | 327 break; |
325 } | 328 } |
326 } | 329 } |
327 | 330 |
328 void AutofillProfile::GetMultiInfo(AutofillFieldType type, | 331 void AutofillProfile::GetMultiInfo(AutofillFieldType type, |
329 std::vector<string16>* values) const { | 332 std::vector<string16>* values) const { |
330 GetMultiInfoImpl(type, false, values); | 333 GetMultiInfoImpl(type, false, values); |
331 } | 334 } |
332 | 335 |
(...skipping 10 matching lines...) Expand all Loading... | |
343 CopyItemsToValues(type, name_, canonicalize, values); | 346 CopyItemsToValues(type, name_, canonicalize, values); |
344 break; | 347 break; |
345 case AutofillType::EMAIL: | 348 case AutofillType::EMAIL: |
346 CopyItemsToValues(type, email_, canonicalize, values); | 349 CopyItemsToValues(type, email_, canonicalize, values); |
347 break; | 350 break; |
348 case AutofillType::PHONE: | 351 case AutofillType::PHONE: |
349 CopyItemsToValues(type, home_number_, canonicalize, values); | 352 CopyItemsToValues(type, home_number_, canonicalize, values); |
350 break; | 353 break; |
351 default: | 354 default: |
352 values->resize(1); | 355 values->resize(1); |
353 (*values)[0] = GetInfo(type); | 356 (*values)[0] = GetRawInfo(type); |
354 } | 357 } |
355 } | 358 } |
356 | 359 |
357 // static | 360 // static |
358 bool AutofillProfile::SupportsMultiValue(AutofillFieldType type) { | 361 bool AutofillProfile::SupportsMultiValue(AutofillFieldType type) { |
359 AutofillType::FieldTypeGroup group = AutofillType(type).group(); | 362 AutofillType::FieldTypeGroup group = AutofillType(type).group(); |
360 return group == AutofillType::NAME || | 363 return group == AutofillType::NAME || |
361 group == AutofillType::EMAIL || | 364 group == AutofillType::EMAIL || |
362 group == AutofillType::PHONE; | 365 group == AutofillType::PHONE; |
363 } | 366 } |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
446 int AutofillProfile::Compare(const AutofillProfile& profile) const { | 449 int AutofillProfile::Compare(const AutofillProfile& profile) const { |
447 const AutofillFieldType single_value_types[] = { COMPANY_NAME, | 450 const AutofillFieldType single_value_types[] = { COMPANY_NAME, |
448 ADDRESS_HOME_LINE1, | 451 ADDRESS_HOME_LINE1, |
449 ADDRESS_HOME_LINE2, | 452 ADDRESS_HOME_LINE2, |
450 ADDRESS_HOME_CITY, | 453 ADDRESS_HOME_CITY, |
451 ADDRESS_HOME_STATE, | 454 ADDRESS_HOME_STATE, |
452 ADDRESS_HOME_ZIP, | 455 ADDRESS_HOME_ZIP, |
453 ADDRESS_HOME_COUNTRY }; | 456 ADDRESS_HOME_COUNTRY }; |
454 | 457 |
455 for (size_t i = 0; i < arraysize(single_value_types); ++i) { | 458 for (size_t i = 0; i < arraysize(single_value_types); ++i) { |
456 int comparison = GetInfo(single_value_types[i]).compare( | 459 int comparison = GetRawInfo(single_value_types[i]).compare( |
457 profile.GetInfo(single_value_types[i])); | 460 profile.GetRawInfo(single_value_types[i])); |
458 if (comparison != 0) | 461 if (comparison != 0) |
459 return comparison; | 462 return comparison; |
460 } | 463 } |
461 | 464 |
462 const AutofillFieldType multi_value_types[] = { NAME_FIRST, | 465 const AutofillFieldType multi_value_types[] = { NAME_FIRST, |
463 NAME_MIDDLE, | 466 NAME_MIDDLE, |
464 NAME_LAST, | 467 NAME_LAST, |
465 EMAIL_ADDRESS, | 468 EMAIL_ADDRESS, |
466 PHONE_HOME_NUMBER }; | 469 PHONE_HOME_NUMBER }; |
467 | 470 |
(...skipping 18 matching lines...) Expand all Loading... | |
486 | 489 |
487 bool AutofillProfile::operator==(const AutofillProfile& profile) const { | 490 bool AutofillProfile::operator==(const AutofillProfile& profile) const { |
488 return guid_ == profile.guid_ && Compare(profile) == 0; | 491 return guid_ == profile.guid_ && Compare(profile) == 0; |
489 } | 492 } |
490 | 493 |
491 bool AutofillProfile::operator!=(const AutofillProfile& profile) const { | 494 bool AutofillProfile::operator!=(const AutofillProfile& profile) const { |
492 return !operator==(profile); | 495 return !operator==(profile); |
493 } | 496 } |
494 | 497 |
495 const string16 AutofillProfile::PrimaryValue() const { | 498 const string16 AutofillProfile::PrimaryValue() const { |
496 return GetInfo(ADDRESS_HOME_LINE1) + | 499 return GetRawInfo(ADDRESS_HOME_LINE1) + |
497 GetInfo(ADDRESS_HOME_CITY); | 500 GetRawInfo(ADDRESS_HOME_CITY); |
498 } | 501 } |
499 | 502 |
500 bool AutofillProfile::IsSubsetOf(const AutofillProfile& profile) const { | 503 bool AutofillProfile::IsSubsetOf(const AutofillProfile& profile) const { |
501 FieldTypeSet types; | 504 FieldTypeSet types; |
502 GetNonEmptyTypes(&types); | 505 GetNonEmptyTypes(&types); |
503 | 506 |
504 for (FieldTypeSet::const_iterator iter = types.begin(); iter != types.end(); | 507 for (FieldTypeSet::const_iterator iter = types.begin(); iter != types.end(); |
505 ++iter) { | 508 ++iter) { |
506 if (*iter == NAME_FULL) { | 509 if (*iter == NAME_FULL) { |
507 // Ignore the compound "full name" field type. We are only interested in | 510 // Ignore the compound "full name" field type. We are only interested in |
508 // comparing the constituent parts. For example, if |this| has a middle | 511 // comparing the constituent parts. For example, if |this| has a middle |
509 // name saved, but |profile| lacks one, |profile| could still be a subset | 512 // name saved, but |profile| lacks one, |profile| could still be a subset |
510 // of |this|. | 513 // of |this|. |
511 continue; | 514 continue; |
512 } else if (AutofillType(*iter).group() == AutofillType::PHONE) { | 515 } else if (AutofillType(*iter).group() == AutofillType::PHONE) { |
513 // Phone numbers should be canonicalized prior to being compared. | 516 // Phone numbers should be canonicalized prior to being compared. |
514 if (*iter != PHONE_HOME_WHOLE_NUMBER) { | 517 if (*iter != PHONE_HOME_WHOLE_NUMBER) { |
515 continue; | 518 continue; |
516 } else if (!autofill_i18n::PhoneNumbersMatch(GetInfo(*iter), | 519 } else if (!autofill_i18n::PhoneNumbersMatch(GetRawInfo(*iter), |
517 profile.GetInfo(*iter), | 520 profile.GetRawInfo(*iter), |
518 CountryCode())) { | 521 CountryCode())) { |
519 return false; | 522 return false; |
520 } | 523 } |
521 } else if (StringToLowerASCII(GetInfo(*iter)) != | 524 } else if (StringToLowerASCII(GetRawInfo(*iter)) != |
522 StringToLowerASCII(profile.GetInfo(*iter))) { | 525 StringToLowerASCII(profile.GetRawInfo(*iter))) { |
523 return false; | 526 return false; |
524 } | 527 } |
525 } | 528 } |
526 | 529 |
527 return true; | 530 return true; |
528 } | 531 } |
529 | 532 |
530 void AutofillProfile::OverwriteWithOrAddTo(const AutofillProfile& profile) { | 533 void AutofillProfile::OverwriteWithOrAddTo(const AutofillProfile& profile) { |
531 FieldTypeSet field_types; | 534 FieldTypeSet field_types; |
532 profile.GetNonEmptyTypes(&field_types); | 535 profile.GetNonEmptyTypes(&field_types); |
(...skipping 24 matching lines...) Expand all Loading... | |
557 } else { | 560 } else { |
558 std::vector<string16>::const_iterator existing_iter = std::find_if( | 561 std::vector<string16>::const_iterator existing_iter = std::find_if( |
559 existing_values.begin(), existing_values.end(), | 562 existing_values.begin(), existing_values.end(), |
560 std::bind1st(CaseInsensitiveStringEquals(), *value_iter)); | 563 std::bind1st(CaseInsensitiveStringEquals(), *value_iter)); |
561 if (existing_iter == existing_values.end()) | 564 if (existing_iter == existing_values.end()) |
562 existing_values.insert(existing_values.end(), *value_iter); | 565 existing_values.insert(existing_values.end(), *value_iter); |
563 } | 566 } |
564 } | 567 } |
565 SetMultiInfo(*iter, existing_values); | 568 SetMultiInfo(*iter, existing_values); |
566 } else { | 569 } else { |
567 string16 new_value = profile.GetInfo(*iter); | 570 string16 new_value = profile.GetRawInfo(*iter); |
568 if (StringToLowerASCII(GetInfo(*iter)) != StringToLowerASCII(new_value)) | 571 if (StringToLowerASCII(GetRawInfo(*iter)) != |
569 SetInfo(*iter, new_value); | 572 StringToLowerASCII(new_value)) |
Dan Beam
2012/11/09 18:46:30
nit: curlies
Ilya Sherman
2012/11/10 03:21:33
Done.
| |
573 SetRawInfo(*iter, new_value); | |
570 } | 574 } |
571 } | 575 } |
572 } | 576 } |
573 | 577 |
574 void AutofillProfile::AddPhoneIfUnique(const string16& phone, | 578 void AutofillProfile::AddPhoneIfUnique(const string16& phone, |
575 std::vector<string16>* existing_phones) { | 579 std::vector<string16>* existing_phones) { |
576 DCHECK(existing_phones); | 580 DCHECK(existing_phones); |
577 // Phones allow "fuzzy" matching, so "1-800-FLOWERS", "18003569377", | 581 // Phones allow "fuzzy" matching, so "1-800-FLOWERS", "18003569377", |
578 // "(800)356-9377" and "356-9377" are considered the same. | 582 // "(800)356-9377" and "356-9377" are considered the same. |
579 if (std::find_if(existing_phones->begin(), existing_phones->end(), | 583 if (std::find_if(existing_phones->begin(), existing_phones->end(), |
580 FindByPhone(phone, CountryCode())) == | 584 FindByPhone(phone, CountryCode())) == |
581 existing_phones->end()) { | 585 existing_phones->end()) { |
582 existing_phones->push_back(phone); | 586 existing_phones->push_back(phone); |
583 } | 587 } |
584 } | 588 } |
585 | 589 |
586 string16 AutofillProfile::ConstructInferredLabel( | 590 string16 AutofillProfile::ConstructInferredLabel( |
587 const std::vector<AutofillFieldType>& included_fields, | 591 const std::vector<AutofillFieldType>& included_fields, |
588 size_t num_fields_to_use) const { | 592 size_t num_fields_to_use) const { |
589 const string16 separator = | 593 const string16 separator = |
590 l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_ADDRESS_SUMMARY_SEPARATOR); | 594 l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_ADDRESS_SUMMARY_SEPARATOR); |
591 | 595 |
592 string16 label; | 596 string16 label; |
593 size_t num_fields_used = 0; | 597 size_t num_fields_used = 0; |
594 for (std::vector<AutofillFieldType>::const_iterator it = | 598 for (std::vector<AutofillFieldType>::const_iterator it = |
595 included_fields.begin(); | 599 included_fields.begin(); |
596 it != included_fields.end() && num_fields_used < num_fields_to_use; | 600 it != included_fields.end() && num_fields_used < num_fields_to_use; |
597 ++it) { | 601 ++it) { |
598 string16 field = GetInfo(*it); | 602 string16 field = GetRawInfo(*it); |
599 if (field.empty()) | 603 if (field.empty()) |
600 continue; | 604 continue; |
601 | 605 |
602 if (!label.empty()) | 606 if (!label.empty()) |
603 label.append(separator); | 607 label.append(separator); |
604 | 608 |
605 label.append(field); | 609 label.append(field); |
606 ++num_fields_used; | 610 ++num_fields_used; |
607 } | 611 } |
608 return label; | 612 return label; |
(...skipping 11 matching lines...) Expand all Loading... | |
620 std::map<AutofillFieldType, | 624 std::map<AutofillFieldType, |
621 std::map<string16, size_t> > field_text_frequencies_by_field; | 625 std::map<string16, size_t> > field_text_frequencies_by_field; |
622 for (std::vector<AutofillFieldType>::const_iterator field = fields.begin(); | 626 for (std::vector<AutofillFieldType>::const_iterator field = fields.begin(); |
623 field != fields.end(); ++field) { | 627 field != fields.end(); ++field) { |
624 std::map<string16, size_t>& field_text_frequencies = | 628 std::map<string16, size_t>& field_text_frequencies = |
625 field_text_frequencies_by_field[*field]; | 629 field_text_frequencies_by_field[*field]; |
626 | 630 |
627 for (std::list<size_t>::const_iterator it = indices.begin(); | 631 for (std::list<size_t>::const_iterator it = indices.begin(); |
628 it != indices.end(); ++it) { | 632 it != indices.end(); ++it) { |
629 const AutofillProfile* profile = profiles[*it]; | 633 const AutofillProfile* profile = profiles[*it]; |
630 string16 field_text = profile->GetInfo(*field); | 634 string16 field_text = profile->GetRawInfo(*field); |
631 | 635 |
632 // If this label is not already in the map, add it with frequency 0. | 636 // If this label is not already in the map, add it with frequency 0. |
633 if (!field_text_frequencies.count(field_text)) | 637 if (!field_text_frequencies.count(field_text)) |
634 field_text_frequencies[field_text] = 0; | 638 field_text_frequencies[field_text] = 0; |
635 | 639 |
636 // Now, increment the frequency for this label. | 640 // Now, increment the frequency for this label. |
637 ++field_text_frequencies[field_text]; | 641 ++field_text_frequencies[field_text]; |
638 } | 642 } |
639 } | 643 } |
640 | 644 |
641 // Now comes the meat of the algorithm. For each profile, we scan the list of | 645 // Now comes the meat of the algorithm. For each profile, we scan the list of |
642 // fields to use, looking for two things: | 646 // fields to use, looking for two things: |
643 // 1. A (non-empty) field that differentiates the profile from all others | 647 // 1. A (non-empty) field that differentiates the profile from all others |
644 // 2. At least |num_fields_to_include| non-empty fields | 648 // 2. At least |num_fields_to_include| non-empty fields |
645 // Before we've satisfied condition (2), we include all fields, even ones that | 649 // Before we've satisfied condition (2), we include all fields, even ones that |
646 // are identical across all the profiles. Once we've satisfied condition (2), | 650 // are identical across all the profiles. Once we've satisfied condition (2), |
647 // we only include fields that that have at last two distinct values. | 651 // we only include fields that that have at last two distinct values. |
648 for (std::list<size_t>::const_iterator it = indices.begin(); | 652 for (std::list<size_t>::const_iterator it = indices.begin(); |
649 it != indices.end(); ++it) { | 653 it != indices.end(); ++it) { |
650 const AutofillProfile* profile = profiles[*it]; | 654 const AutofillProfile* profile = profiles[*it]; |
651 | 655 |
652 std::vector<AutofillFieldType> label_fields; | 656 std::vector<AutofillFieldType> label_fields; |
653 bool found_differentiating_field = false; | 657 bool found_differentiating_field = false; |
654 for (std::vector<AutofillFieldType>::const_iterator field = fields.begin(); | 658 for (std::vector<AutofillFieldType>::const_iterator field = fields.begin(); |
655 field != fields.end(); ++field) { | 659 field != fields.end(); ++field) { |
656 // Skip over empty fields. | 660 // Skip over empty fields. |
657 string16 field_text = profile->GetInfo(*field); | 661 string16 field_text = profile->GetRawInfo(*field); |
658 if (field_text.empty()) | 662 if (field_text.empty()) |
659 continue; | 663 continue; |
660 | 664 |
661 std::map<string16, size_t>& field_text_frequencies = | 665 std::map<string16, size_t>& field_text_frequencies = |
662 field_text_frequencies_by_field[*field]; | 666 field_text_frequencies_by_field[*field]; |
663 found_differentiating_field |= | 667 found_differentiating_field |= |
664 !field_text_frequencies.count(string16()) && | 668 !field_text_frequencies.count(string16()) && |
665 (field_text_frequencies[field_text] == 1); | 669 (field_text_frequencies[field_text] == 1); |
666 | 670 |
667 // Once we've found enough non-empty fields, skip over any remaining | 671 // Once we've found enough non-empty fields, skip over any remaining |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
732 << profile.guid() | 736 << profile.guid() |
733 << " " | 737 << " " |
734 << UTF16ToUTF8(MultiString(profile, NAME_FIRST)) | 738 << UTF16ToUTF8(MultiString(profile, NAME_FIRST)) |
735 << " " | 739 << " " |
736 << UTF16ToUTF8(MultiString(profile, NAME_MIDDLE)) | 740 << UTF16ToUTF8(MultiString(profile, NAME_MIDDLE)) |
737 << " " | 741 << " " |
738 << UTF16ToUTF8(MultiString(profile, NAME_LAST)) | 742 << UTF16ToUTF8(MultiString(profile, NAME_LAST)) |
739 << " " | 743 << " " |
740 << UTF16ToUTF8(MultiString(profile, EMAIL_ADDRESS)) | 744 << UTF16ToUTF8(MultiString(profile, EMAIL_ADDRESS)) |
741 << " " | 745 << " " |
742 << UTF16ToUTF8(profile.GetInfo(COMPANY_NAME)) | 746 << UTF16ToUTF8(profile.GetRawInfo(COMPANY_NAME)) |
743 << " " | 747 << " " |
744 << UTF16ToUTF8(profile.GetInfo(ADDRESS_HOME_LINE1)) | 748 << UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_LINE1)) |
745 << " " | 749 << " " |
746 << UTF16ToUTF8(profile.GetInfo(ADDRESS_HOME_LINE2)) | 750 << UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_LINE2)) |
747 << " " | 751 << " " |
748 << UTF16ToUTF8(profile.GetInfo(ADDRESS_HOME_CITY)) | 752 << UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_CITY)) |
749 << " " | 753 << " " |
750 << UTF16ToUTF8(profile.GetInfo(ADDRESS_HOME_STATE)) | 754 << UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_STATE)) |
751 << " " | 755 << " " |
752 << UTF16ToUTF8(profile.GetInfo(ADDRESS_HOME_ZIP)) | 756 << UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_ZIP)) |
753 << " " | 757 << " " |
754 << UTF16ToUTF8(profile.GetInfo(ADDRESS_HOME_COUNTRY)) | 758 << UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_COUNTRY)) |
755 << " " | 759 << " " |
756 << UTF16ToUTF8(MultiString(profile, PHONE_HOME_WHOLE_NUMBER)); | 760 << UTF16ToUTF8(MultiString(profile, PHONE_HOME_WHOLE_NUMBER)); |
757 } | 761 } |
OLD | NEW |