OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 <list> |
| 9 #include <map> |
| 10 #include <set> |
8 #include <vector> | 11 #include <vector> |
9 | 12 |
10 #include "app/l10n_util.h" | 13 #include "app/l10n_util.h" |
11 #include "base/stl_util-inl.h" | 14 #include "base/stl_util-inl.h" |
12 #include "base/utf_string_conversions.h" | 15 #include "base/utf_string_conversions.h" |
13 #include "chrome/browser/autofill/address.h" | 16 #include "chrome/browser/autofill/address.h" |
14 #include "chrome/browser/autofill/autofill_manager.h" | 17 #include "chrome/browser/autofill/autofill_manager.h" |
15 #include "chrome/browser/autofill/contact_info.h" | 18 #include "chrome/browser/autofill/contact_info.h" |
16 #include "chrome/browser/autofill/fax_number.h" | 19 #include "chrome/browser/autofill/fax_number.h" |
17 #include "chrome/browser/autofill/home_address.h" | 20 #include "chrome/browser/autofill/home_address.h" |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
163 // may be an empty string. | 166 // may be an empty string. |
164 string16 first_name = GetFieldText(AutoFillType(NAME_FIRST)); | 167 string16 first_name = GetFieldText(AutoFillType(NAME_FIRST)); |
165 string16 last_name = GetFieldText(AutoFillType(NAME_LAST)); | 168 string16 last_name = GetFieldText(AutoFillType(NAME_LAST)); |
166 string16 address = GetFieldText(AutoFillType(ADDRESS_HOME_LINE1)); | 169 string16 address = GetFieldText(AutoFillType(ADDRESS_HOME_LINE1)); |
167 | 170 |
168 // String separators depend (below) on the existence of the various fields. | 171 // String separators depend (below) on the existence of the various fields. |
169 bool have_first_name = first_name.length() > 0; | 172 bool have_first_name = first_name.length() > 0; |
170 bool have_last_name = last_name.length() > 0; | 173 bool have_last_name = last_name.length() > 0; |
171 bool have_address = address.length() > 0; | 174 bool have_address = address.length() > 0; |
172 | 175 |
173 // Name separator defaults to "". Space if we have first and last name. | 176 // Name separator defaults to "". Space if we have first and last name. |
174 string16 name_separator; | 177 string16 name_separator; |
| 178 |
175 if (have_first_name && have_last_name) { | 179 if (have_first_name && have_last_name) { |
176 name_separator = l10n_util::GetStringUTF16( | 180 name_separator = l10n_util::GetStringUTF16( |
177 IDS_AUTOFILL_DIALOG_ADDRESS_NAME_SEPARATOR); | 181 IDS_AUTOFILL_DIALOG_ADDRESS_NAME_SEPARATOR); |
178 } | 182 } |
179 | 183 |
180 // E.g. "John Smith", or "John", or "Smith", or "". | 184 // E.g. "John Smith", or "John", or "Smith", or "". |
181 string16 name_format = l10n_util::GetStringFUTF16( | 185 string16 name_format = l10n_util::GetStringFUTF16( |
182 IDS_AUTOFILL_DIALOG_ADDRESS_SUMMARY_NAME_FORMAT, | 186 IDS_AUTOFILL_DIALOG_ADDRESS_SUMMARY_NAME_FORMAT, |
183 first_name, | 187 first_name, |
184 name_separator, | 188 name_separator, |
185 last_name); | 189 last_name); |
186 | 190 |
187 // Summary separator defaults to "". ", " if we have name and address. | 191 // Summary separator defaults to "". ", " if we have name and address. |
188 string16 summary_separator; | 192 string16 summary_separator; |
189 if ((have_first_name || have_last_name) && have_address) { | 193 if ((have_first_name || have_last_name) && have_address) { |
190 summary_separator = l10n_util::GetStringUTF16( | 194 summary_separator = l10n_util::GetStringUTF16( |
191 IDS_AUTOFILL_DIALOG_ADDRESS_SUMMARY_SEPARATOR); | 195 IDS_AUTOFILL_DIALOG_ADDRESS_SUMMARY_SEPARATOR); |
192 } | 196 } |
193 | 197 |
194 // E.g. "John Smith, 123 Main Street". | 198 // E.g. "John Smith, 123 Main Street". |
195 string16 summary_format = l10n_util::GetStringFUTF16( | 199 string16 summary_format = l10n_util::GetStringFUTF16( |
196 IDS_AUTOFILL_DIALOG_ADDRESS_SUMMARY_FORMAT, | 200 IDS_AUTOFILL_DIALOG_ADDRESS_SUMMARY_FORMAT, |
197 name_format, | 201 name_format, |
198 summary_separator, | 202 summary_separator, |
199 address); | 203 address); |
200 | 204 |
201 return summary_format; | 205 return summary_format; |
202 } | 206 } |
203 | 207 |
| 208 bool AutoFillProfile::AdjustInferredLabels( |
| 209 std::vector<AutoFillProfile*>* profiles) { |
| 210 std::vector<string16> created_labels; |
| 211 const size_t kMinimalFieldsShown = 2; |
| 212 CreateInferredLabels(profiles, &created_labels, kMinimalFieldsShown, |
| 213 UNKNOWN_TYPE); |
| 214 DCHECK(profiles->size() == created_labels.size()); |
| 215 bool updated_labels = false; |
| 216 for (size_t i = 0; i < profiles->size(); ++i) { |
| 217 if (profiles->at(i)->Label() != created_labels[i]) { |
| 218 updated_labels = true; |
| 219 profiles->at(i)->set_label(created_labels[i]); |
| 220 } |
| 221 } |
| 222 return updated_labels; |
| 223 } |
| 224 |
| 225 void AutoFillProfile::CreateInferredLabels( |
| 226 const std::vector<AutoFillProfile*>* profiles, |
| 227 std::vector<string16>* created_labels, |
| 228 size_t minimal_fields_shown, |
| 229 AutoFillFieldType exclude_field) { |
| 230 // These fields are use to distinguish between two profiles in the order of |
| 231 // importance, e. g. if both EMAIL_ADDRESS and COMPANY_NAME are different, |
| 232 // EMAIL_ADDRESS will be used to distinguish them. |
| 233 const AutoFillFieldType distinguishing_fields[] = { |
| 234 // First non empty data are always present in the label, even if it matches. |
| 235 NAME_FULL, |
| 236 ADDRESS_HOME_LINE1, |
| 237 ADDRESS_HOME_CITY, |
| 238 ADDRESS_HOME_STATE, |
| 239 ADDRESS_HOME_ZIP, |
| 240 ADDRESS_HOME_COUNTRY, |
| 241 EMAIL_ADDRESS, |
| 242 PHONE_HOME_WHOLE_NUMBER, |
| 243 PHONE_FAX_WHOLE_NUMBER, |
| 244 COMPANY_NAME, |
| 245 }; |
| 246 if (exclude_field == NAME_FIRST || exclude_field == NAME_LAST) |
| 247 exclude_field = NAME_FULL; |
| 248 DCHECK(profiles); |
| 249 DCHECK(created_labels); |
| 250 created_labels->resize(profiles->size()); |
| 251 std::map<string16, std::list<size_t> > labels; |
| 252 for (size_t it = 0; it < profiles->size(); ++it) { |
| 253 labels[ |
| 254 profiles->at(it)->GetFieldText(AutoFillType(NAME_FULL))].push_back(it); |
| 255 } |
| 256 std::map<string16, std::list<size_t> >::iterator label_iterator; |
| 257 for (label_iterator = labels.begin(); label_iterator != labels.end(); |
| 258 ++label_iterator) { |
| 259 if (label_iterator->second.size() > 1) { |
| 260 // We have more than one item with the same preview, add differentiating |
| 261 // data. |
| 262 std::list<size_t>::iterator similar_profiles; |
| 263 std::map<string16, int> tested_fields[arraysize(distinguishing_fields)]; |
| 264 for (similar_profiles = label_iterator->second.begin(); |
| 265 similar_profiles != label_iterator->second.end(); |
| 266 ++similar_profiles) { |
| 267 for (size_t i = 0; i < arraysize(distinguishing_fields); ++i) { |
| 268 string16 key = profiles->at(*similar_profiles)->GetFieldText( |
| 269 AutoFillType(distinguishing_fields[i])); |
| 270 std::map<string16, int>::iterator tested_field = |
| 271 tested_fields[i].find(key); |
| 272 if (tested_field == tested_fields[i].end()) |
| 273 (tested_fields[i])[key] = 1; |
| 274 else |
| 275 ++(tested_field->second); |
| 276 } |
| 277 } |
| 278 std::vector<AutoFillFieldType> fields; |
| 279 std::vector<AutoFillFieldType> first_non_empty_fields; |
| 280 size_t added_fields = 0; |
| 281 bool matched_necessary = false; |
| 282 // Leave it as a candidate if it is not the same for everybody. |
| 283 for (size_t i = 0; i < arraysize(distinguishing_fields); ++i) { |
| 284 if (tested_fields[i].size() == label_iterator->second.size()) { |
| 285 // This field is different for everybody. |
| 286 if (!matched_necessary) { |
| 287 matched_necessary = true; |
| 288 fields.clear(); |
| 289 added_fields = 1; |
| 290 if (first_non_empty_fields.size()) { |
| 291 added_fields += first_non_empty_fields.size(); |
| 292 fields.resize(added_fields - 1); |
| 293 std::copy(first_non_empty_fields.begin(), |
| 294 first_non_empty_fields.end(), |
| 295 fields.begin()); |
| 296 } |
| 297 } else { |
| 298 ++added_fields; |
| 299 } |
| 300 fields.push_back(distinguishing_fields[i]); |
| 301 if (added_fields >= minimal_fields_shown) |
| 302 break; |
| 303 } else if (tested_fields[i].size() != 1) { |
| 304 // this field is different for some. |
| 305 if (added_fields < minimal_fields_shown) { |
| 306 first_non_empty_fields.push_back(distinguishing_fields[i]); |
| 307 ++added_fields; |
| 308 if (added_fields == minimal_fields_shown && matched_necessary) |
| 309 break; |
| 310 } |
| 311 fields.push_back(distinguishing_fields[i]); |
| 312 } else if (added_fields < minimal_fields_shown && |
| 313 exclude_field != distinguishing_fields[i] && |
| 314 !label_iterator->first.empty()) { |
| 315 fields.push_back(distinguishing_fields[i]); |
| 316 first_non_empty_fields.push_back(distinguishing_fields[i]); |
| 317 ++added_fields; |
| 318 if (added_fields == minimal_fields_shown && matched_necessary) |
| 319 break; |
| 320 } |
| 321 } |
| 322 // Update labels if needed. |
| 323 for (similar_profiles = label_iterator->second.begin(); |
| 324 similar_profiles != label_iterator->second.end(); |
| 325 ++similar_profiles) { |
| 326 size_t field_it = 0; |
| 327 for (size_t field_id = 0; |
| 328 field_id < arraysize(distinguishing_fields) && |
| 329 field_it < fields.size(); ++field_id) { |
| 330 if (fields[field_it] == distinguishing_fields[field_id]) { |
| 331 if ((tested_fields[field_id])[ |
| 332 profiles->at(*similar_profiles)->GetFieldText( |
| 333 AutoFillType(distinguishing_fields[field_id]))] == 1) { |
| 334 // this field is unique among the subset. |
| 335 break; |
| 336 } |
| 337 ++field_it; |
| 338 } |
| 339 } |
| 340 |
| 341 string16 new_label; |
| 342 if (field_it < fields.size() && fields.size() > minimal_fields_shown) { |
| 343 std::vector<AutoFillFieldType> unique_fields; |
| 344 unique_fields.resize(fields.size()); |
| 345 std::copy(fields.begin(), fields.end(), unique_fields.begin()); |
| 346 unique_fields.resize(std::max(field_it + 1, minimal_fields_shown)); |
| 347 new_label = |
| 348 profiles->at(*similar_profiles)->ConstructInferredLabel( |
| 349 &unique_fields); |
| 350 } else { |
| 351 new_label = |
| 352 profiles->at(*similar_profiles)->ConstructInferredLabel(&fields); |
| 353 } |
| 354 (*created_labels)[*similar_profiles] = new_label; |
| 355 } |
| 356 } else { |
| 357 std::vector<AutoFillFieldType> non_empty_fields; |
| 358 size_t include_fields = minimal_fields_shown ? minimal_fields_shown : 1; |
| 359 non_empty_fields.reserve(include_fields); |
| 360 for (size_t i = 0; i < arraysize(distinguishing_fields); ++i) { |
| 361 if (exclude_field == distinguishing_fields[i]) |
| 362 continue; |
| 363 if (!profiles->at(label_iterator->second.front())->GetFieldText( |
| 364 AutoFillType(distinguishing_fields[i])).empty()) { |
| 365 non_empty_fields.push_back(distinguishing_fields[i]); |
| 366 if (non_empty_fields.size() >= include_fields) |
| 367 break; |
| 368 } |
| 369 } |
| 370 |
| 371 (*created_labels)[label_iterator->second.front()] = |
| 372 profiles->at(label_iterator->second.front())->ConstructInferredLabel( |
| 373 &non_empty_fields); |
| 374 } |
| 375 } |
| 376 } |
| 377 |
204 void AutoFillProfile::operator=(const AutoFillProfile& source) { | 378 void AutoFillProfile::operator=(const AutoFillProfile& source) { |
205 label_ = source.label_; | 379 label_ = source.label_; |
206 unique_id_ = source.unique_id_; | 380 unique_id_ = source.unique_id_; |
207 | 381 |
208 STLDeleteContainerPairSecondPointers(personal_info_.begin(), | 382 STLDeleteContainerPairSecondPointers(personal_info_.begin(), |
209 personal_info_.end()); | 383 personal_info_.end()); |
210 personal_info_.clear(); | 384 personal_info_.clear(); |
211 | 385 |
212 FormGroupMap::const_iterator iter; | 386 FormGroupMap::const_iterator iter; |
213 for (iter = source.personal_info_.begin(); | 387 for (iter = source.personal_info_.begin(); |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
249 } | 423 } |
250 | 424 |
251 bool AutoFillProfile::operator!=(const AutoFillProfile& profile) const { | 425 bool AutoFillProfile::operator!=(const AutoFillProfile& profile) const { |
252 return !operator==(profile); | 426 return !operator==(profile); |
253 } | 427 } |
254 | 428 |
255 Address* AutoFillProfile::GetHomeAddress() { | 429 Address* AutoFillProfile::GetHomeAddress() { |
256 return static_cast<Address*>(personal_info_[AutoFillType::ADDRESS_HOME]); | 430 return static_cast<Address*>(personal_info_[AutoFillType::ADDRESS_HOME]); |
257 } | 431 } |
258 | 432 |
| 433 string16 AutoFillProfile::ConstructInferredLabel( |
| 434 const std::vector<AutoFillFieldType>* included_fields) const { |
| 435 DCHECK(included_fields); |
| 436 string16 label; |
| 437 string16 separator = l10n_util::GetStringUTF16( |
| 438 IDS_AUTOFILL_DIALOG_ADDRESS_SUMMARY_SEPARATOR); |
| 439 for (std::vector<AutoFillFieldType>::const_iterator it = |
| 440 included_fields->begin(); it != included_fields->end(); ++it) { |
| 441 string16 field = GetFieldText(AutoFillType(*it)); |
| 442 if (!field.empty()) { |
| 443 if (!label.empty()) { |
| 444 label.append(separator); |
| 445 } |
| 446 // Fax number has special format, to indicate that this is a fax number. |
| 447 if (*it == PHONE_FAX_WHOLE_NUMBER) { |
| 448 field = l10n_util::GetStringFUTF16( |
| 449 IDS_AUTOFILL_DIALOG_ADDRESS_SUMMARY_FAX_FORMAT, field); |
| 450 } |
| 451 label.append(field); |
| 452 } |
| 453 } |
| 454 return label; |
| 455 } |
| 456 |
| 457 |
259 // So we can compare AutoFillProfiles with EXPECT_EQ(). | 458 // So we can compare AutoFillProfiles with EXPECT_EQ(). |
260 std::ostream& operator<<(std::ostream& os, const AutoFillProfile& profile) { | 459 std::ostream& operator<<(std::ostream& os, const AutoFillProfile& profile) { |
261 return os | 460 return os |
262 << UTF16ToUTF8(profile.Label()) | 461 << UTF16ToUTF8(profile.Label()) |
263 << " " | 462 << " " |
264 << profile.unique_id() | 463 << profile.unique_id() |
265 << " " | 464 << " " |
266 << UTF16ToUTF8(profile.GetFieldText(AutoFillType(NAME_FIRST))) | 465 << UTF16ToUTF8(profile.GetFieldText(AutoFillType(NAME_FIRST))) |
267 << " " | 466 << " " |
268 << UTF16ToUTF8(profile.GetFieldText(AutoFillType(NAME_MIDDLE))) | 467 << UTF16ToUTF8(profile.GetFieldText(AutoFillType(NAME_MIDDLE))) |
(...skipping 15 matching lines...) Expand all Loading... |
284 << UTF16ToUTF8(profile.GetFieldText(AutoFillType(ADDRESS_HOME_ZIP))) | 483 << UTF16ToUTF8(profile.GetFieldText(AutoFillType(ADDRESS_HOME_ZIP))) |
285 << " " | 484 << " " |
286 << UTF16ToUTF8(profile.GetFieldText(AutoFillType(ADDRESS_HOME_COUNTRY))) | 485 << UTF16ToUTF8(profile.GetFieldText(AutoFillType(ADDRESS_HOME_COUNTRY))) |
287 << " " | 486 << " " |
288 << UTF16ToUTF8(profile.GetFieldText(AutoFillType( | 487 << UTF16ToUTF8(profile.GetFieldText(AutoFillType( |
289 PHONE_HOME_WHOLE_NUMBER))) | 488 PHONE_HOME_WHOLE_NUMBER))) |
290 << " " | 489 << " " |
291 << UTF16ToUTF8(profile.GetFieldText(AutoFillType( | 490 << UTF16ToUTF8(profile.GetFieldText(AutoFillType( |
292 PHONE_FAX_WHOLE_NUMBER))); | 491 PHONE_FAX_WHOLE_NUMBER))); |
293 } | 492 } |
OLD | NEW |