| OLD | NEW |
| (Empty) |
| 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 | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "components/autofill/browser/personal_data_manager.h" | |
| 6 | |
| 7 #include <algorithm> | |
| 8 #include <functional> | |
| 9 #include <iterator> | |
| 10 | |
| 11 #include "base/logging.h" | |
| 12 #include "base/memory/ref_counted.h" | |
| 13 #include "base/prefs/pref_service.h" | |
| 14 #include "base/strings/string_number_conversions.h" | |
| 15 #include "base/strings/string_util.h" | |
| 16 #include "base/strings/utf_string_conversions.h" | |
| 17 #include "components/autofill/browser/autofill-inl.h" | |
| 18 #include "components/autofill/browser/autofill_country.h" | |
| 19 #include "components/autofill/browser/autofill_field.h" | |
| 20 #include "components/autofill/browser/autofill_metrics.h" | |
| 21 #include "components/autofill/browser/form_structure.h" | |
| 22 #include "components/autofill/browser/personal_data_manager_observer.h" | |
| 23 #include "components/autofill/browser/phone_number.h" | |
| 24 #include "components/autofill/browser/phone_number_i18n.h" | |
| 25 #include "components/autofill/browser/validation.h" | |
| 26 #include "components/autofill/browser/webdata/autofill_webdata_service.h" | |
| 27 #include "components/autofill/core/common/autofill_pref_names.h" | |
| 28 #include "components/user_prefs/user_prefs.h" | |
| 29 #include "content/public/browser/browser_context.h" | |
| 30 | |
| 31 using content::BrowserContext; | |
| 32 | |
| 33 namespace autofill { | |
| 34 namespace { | |
| 35 | |
| 36 const base::string16::value_type kCreditCardPrefix[] = {'*', 0}; | |
| 37 | |
| 38 template<typename T> | |
| 39 class FormGroupMatchesByGUIDFunctor { | |
| 40 public: | |
| 41 explicit FormGroupMatchesByGUIDFunctor(const std::string& guid) | |
| 42 : guid_(guid) { | |
| 43 } | |
| 44 | |
| 45 bool operator()(const T& form_group) { | |
| 46 return form_group.guid() == guid_; | |
| 47 } | |
| 48 | |
| 49 bool operator()(const T* form_group) { | |
| 50 return form_group->guid() == guid_; | |
| 51 } | |
| 52 | |
| 53 private: | |
| 54 std::string guid_; | |
| 55 }; | |
| 56 | |
| 57 template<typename T, typename C> | |
| 58 bool FindByGUID(const C& container, const std::string& guid) { | |
| 59 return std::find_if( | |
| 60 container.begin(), | |
| 61 container.end(), | |
| 62 FormGroupMatchesByGUIDFunctor<T>(guid)) != container.end(); | |
| 63 } | |
| 64 | |
| 65 template<typename T> | |
| 66 class DereferenceFunctor { | |
| 67 public: | |
| 68 template<typename T_Iterator> | |
| 69 const T& operator()(const T_Iterator& iterator) { | |
| 70 return *iterator; | |
| 71 } | |
| 72 }; | |
| 73 | |
| 74 template<typename T> | |
| 75 T* address_of(T& v) { | |
| 76 return &v; | |
| 77 } | |
| 78 | |
| 79 // Returns true if minimum requirements for import of a given |profile| have | |
| 80 // been met. An address submitted via a form must have at least the fields | |
| 81 // required as determined by its country code. | |
| 82 // No verification of validity of the contents is preformed. This is an | |
| 83 // existence check only. | |
| 84 bool IsMinimumAddress(const AutofillProfile& profile, | |
| 85 const std::string& app_locale) { | |
| 86 // All countries require at least one address line. | |
| 87 if (profile.GetRawInfo(ADDRESS_HOME_LINE1).empty()) | |
| 88 return false; | |
| 89 std::string country_code = | |
| 90 UTF16ToASCII(profile.GetRawInfo(ADDRESS_HOME_COUNTRY)); | |
| 91 | |
| 92 if (country_code.empty()) | |
| 93 country_code = AutofillCountry::CountryCodeForLocale(app_locale); | |
| 94 | |
| 95 AutofillCountry country(country_code, app_locale); | |
| 96 | |
| 97 if (country.requires_city() && profile.GetRawInfo(ADDRESS_HOME_CITY).empty()) | |
| 98 return false; | |
| 99 | |
| 100 if (country.requires_state() && | |
| 101 profile.GetRawInfo(ADDRESS_HOME_STATE).empty()) | |
| 102 return false; | |
| 103 | |
| 104 if (country.requires_zip() && profile.GetRawInfo(ADDRESS_HOME_ZIP).empty()) | |
| 105 return false; | |
| 106 | |
| 107 return true; | |
| 108 } | |
| 109 | |
| 110 // Return true if the |field_type| and |value| are valid within the context | |
| 111 // of importing a form. | |
| 112 bool IsValidFieldTypeAndValue(const std::set<AutofillFieldType>& types_seen, | |
| 113 AutofillFieldType field_type, | |
| 114 const base::string16& value) { | |
| 115 // Abandon the import if two fields of the same type are encountered. | |
| 116 // This indicates ambiguous data or miscategorization of types. | |
| 117 // Make an exception for PHONE_HOME_NUMBER however as both prefix and | |
| 118 // suffix are stored against this type, and for EMAIL_ADDRESS because it is | |
| 119 // common to see second 'confirm email address' fields on forms. | |
| 120 if (types_seen.count(field_type) && field_type != PHONE_HOME_NUMBER && | |
| 121 field_type != EMAIL_ADDRESS) | |
| 122 return false; | |
| 123 | |
| 124 // Abandon the import if an email address value shows up in a field that is | |
| 125 // not an email address. | |
| 126 if (field_type != EMAIL_ADDRESS && autofill::IsValidEmailAddress(value)) | |
| 127 return false; | |
| 128 | |
| 129 return true; | |
| 130 } | |
| 131 | |
| 132 } // namespace | |
| 133 | |
| 134 PersonalDataManager::PersonalDataManager(const std::string& app_locale) | |
| 135 : browser_context_(NULL), | |
| 136 is_data_loaded_(false), | |
| 137 pending_profiles_query_(0), | |
| 138 pending_creditcards_query_(0), | |
| 139 app_locale_(app_locale), | |
| 140 metric_logger_(new AutofillMetrics), | |
| 141 has_logged_profile_count_(false) {} | |
| 142 | |
| 143 void PersonalDataManager::Init(BrowserContext* browser_context) { | |
| 144 browser_context_ = browser_context; | |
| 145 | |
| 146 if (!browser_context_->IsOffTheRecord()) | |
| 147 metric_logger_->LogIsAutofillEnabledAtStartup(IsAutofillEnabled()); | |
| 148 | |
| 149 scoped_refptr<AutofillWebDataService> autofill_data( | |
| 150 AutofillWebDataService::FromBrowserContext(browser_context_)); | |
| 151 | |
| 152 // WebDataService may not be available in tests. | |
| 153 if (!autofill_data.get()) | |
| 154 return; | |
| 155 | |
| 156 LoadProfiles(); | |
| 157 LoadCreditCards(); | |
| 158 | |
| 159 autofill_data->AddObserver(this); | |
| 160 } | |
| 161 | |
| 162 PersonalDataManager::~PersonalDataManager() { | |
| 163 CancelPendingQuery(&pending_profiles_query_); | |
| 164 CancelPendingQuery(&pending_creditcards_query_); | |
| 165 | |
| 166 if (!browser_context_) | |
| 167 return; | |
| 168 | |
| 169 scoped_refptr<AutofillWebDataService> autofill_data( | |
| 170 AutofillWebDataService::FromBrowserContext(browser_context_)); | |
| 171 if (autofill_data.get()) | |
| 172 autofill_data->RemoveObserver(this); | |
| 173 } | |
| 174 | |
| 175 void PersonalDataManager::OnWebDataServiceRequestDone( | |
| 176 WebDataServiceBase::Handle h, | |
| 177 const WDTypedResult* result) { | |
| 178 DCHECK(pending_profiles_query_ || pending_creditcards_query_); | |
| 179 | |
| 180 if (!result) { | |
| 181 // Error from the web database. | |
| 182 if (h == pending_creditcards_query_) | |
| 183 pending_creditcards_query_ = 0; | |
| 184 else if (h == pending_profiles_query_) | |
| 185 pending_profiles_query_ = 0; | |
| 186 return; | |
| 187 } | |
| 188 | |
| 189 DCHECK(result->GetType() == AUTOFILL_PROFILES_RESULT || | |
| 190 result->GetType() == AUTOFILL_CREDITCARDS_RESULT); | |
| 191 | |
| 192 switch (result->GetType()) { | |
| 193 case AUTOFILL_PROFILES_RESULT: | |
| 194 ReceiveLoadedProfiles(h, result); | |
| 195 break; | |
| 196 case AUTOFILL_CREDITCARDS_RESULT: | |
| 197 ReceiveLoadedCreditCards(h, result); | |
| 198 break; | |
| 199 default: | |
| 200 NOTREACHED(); | |
| 201 } | |
| 202 | |
| 203 // If both requests have responded, then all personal data is loaded. | |
| 204 if (pending_profiles_query_ == 0 && pending_creditcards_query_ == 0) { | |
| 205 is_data_loaded_ = true; | |
| 206 std::vector<AutofillProfile*> profile_pointers(web_profiles_.size()); | |
| 207 std::copy(web_profiles_.begin(), web_profiles_.end(), | |
| 208 profile_pointers.begin()); | |
| 209 AutofillProfile::AdjustInferredLabels(&profile_pointers); | |
| 210 FOR_EACH_OBSERVER(PersonalDataManagerObserver, observers_, | |
| 211 OnPersonalDataChanged()); | |
| 212 } | |
| 213 } | |
| 214 | |
| 215 void PersonalDataManager::AutofillMultipleChanged() { | |
| 216 Refresh(); | |
| 217 } | |
| 218 | |
| 219 void PersonalDataManager::AddObserver(PersonalDataManagerObserver* observer) { | |
| 220 observers_.AddObserver(observer); | |
| 221 } | |
| 222 | |
| 223 void PersonalDataManager::RemoveObserver( | |
| 224 PersonalDataManagerObserver* observer) { | |
| 225 observers_.RemoveObserver(observer); | |
| 226 } | |
| 227 | |
| 228 bool PersonalDataManager::ImportFormData( | |
| 229 const FormStructure& form, | |
| 230 const CreditCard** imported_credit_card) { | |
| 231 scoped_ptr<AutofillProfile> imported_profile(new AutofillProfile); | |
| 232 scoped_ptr<CreditCard> local_imported_credit_card(new CreditCard); | |
| 233 | |
| 234 const std::string origin = form.source_url().spec(); | |
| 235 imported_profile->set_origin(origin); | |
| 236 local_imported_credit_card->set_origin(origin); | |
| 237 | |
| 238 // Parse the form and construct a profile based on the information that is | |
| 239 // possible to import. | |
| 240 int importable_credit_card_fields = 0; | |
| 241 | |
| 242 // Detect and discard forms with multiple fields of the same type. | |
| 243 std::set<AutofillFieldType> types_seen; | |
| 244 | |
| 245 // We only set complete phone, so aggregate phone parts in these vars and set | |
| 246 // complete at the end. | |
| 247 PhoneNumber::PhoneCombineHelper home; | |
| 248 | |
| 249 for (size_t i = 0; i < form.field_count(); ++i) { | |
| 250 const AutofillField* field = form.field(i); | |
| 251 base::string16 value = CollapseWhitespace(field->value, false); | |
| 252 | |
| 253 // If we don't know the type of the field, or the user hasn't entered any | |
| 254 // information into the field, then skip it. | |
| 255 if (!field->IsFieldFillable() || value.empty()) | |
| 256 continue; | |
| 257 | |
| 258 AutofillFieldType field_type = field->type(); | |
| 259 FieldTypeGroup group(AutofillType(field_type).group()); | |
| 260 | |
| 261 // There can be multiple email fields (e.g. in the case of 'confirm email' | |
| 262 // fields) but they must all contain the same value, else the profile is | |
| 263 // invalid. | |
| 264 if (field_type == EMAIL_ADDRESS) { | |
| 265 if (types_seen.count(field_type) && | |
| 266 imported_profile->GetRawInfo(field_type) != value) { | |
| 267 imported_profile.reset(); | |
| 268 break; | |
| 269 } | |
| 270 } | |
| 271 | |
| 272 // If the |field_type| and |value| don't pass basic validity checks then | |
| 273 // abandon the import. | |
| 274 if (!IsValidFieldTypeAndValue(types_seen, field_type, value)) { | |
| 275 imported_profile.reset(); | |
| 276 local_imported_credit_card.reset(); | |
| 277 break; | |
| 278 } | |
| 279 | |
| 280 types_seen.insert(field_type); | |
| 281 | |
| 282 if (group == AutofillType::CREDIT_CARD) { | |
| 283 if (LowerCaseEqualsASCII(field->form_control_type, "month")) { | |
| 284 DCHECK_EQ(CREDIT_CARD_EXP_MONTH, field_type); | |
| 285 local_imported_credit_card->SetInfoForMonthInputType(value); | |
| 286 } else { | |
| 287 local_imported_credit_card->SetInfo(field_type, value, app_locale_); | |
| 288 } | |
| 289 ++importable_credit_card_fields; | |
| 290 } else { | |
| 291 // We need to store phone data in the variables, before building the whole | |
| 292 // number at the end. The rest of the fields are set "as is". | |
| 293 // If the fields are not the phone fields in question home.SetInfo() is | |
| 294 // going to return false. | |
| 295 if (!home.SetInfo(field_type, value)) | |
| 296 imported_profile->SetInfo(field_type, value, app_locale_); | |
| 297 | |
| 298 // Reject profiles with invalid country information. | |
| 299 if (field_type == ADDRESS_HOME_COUNTRY && | |
| 300 !value.empty() && | |
| 301 imported_profile->GetRawInfo(ADDRESS_HOME_COUNTRY).empty()) { | |
| 302 imported_profile.reset(); | |
| 303 break; | |
| 304 } | |
| 305 } | |
| 306 } | |
| 307 | |
| 308 // Construct the phone number. Reject the profile if the number is invalid. | |
| 309 if (imported_profile.get() && !home.IsEmpty()) { | |
| 310 base::string16 constructed_number; | |
| 311 if (!home.ParseNumber(*imported_profile, app_locale_, | |
| 312 &constructed_number) || | |
| 313 !imported_profile->SetInfo(PHONE_HOME_WHOLE_NUMBER, constructed_number, | |
| 314 app_locale_)) { | |
| 315 imported_profile.reset(); | |
| 316 } | |
| 317 } | |
| 318 | |
| 319 // Reject the profile if minimum address and validation requirements are not | |
| 320 // met. | |
| 321 if (imported_profile.get() && | |
| 322 !IsValidLearnableProfile(*imported_profile, app_locale_)) | |
| 323 imported_profile.reset(); | |
| 324 | |
| 325 // Reject the credit card if we did not detect enough filled credit card | |
| 326 // fields or if the credit card number does not seem to be valid. | |
| 327 if (local_imported_credit_card.get() && | |
| 328 !local_imported_credit_card->IsComplete()) { | |
| 329 local_imported_credit_card.reset(); | |
| 330 } | |
| 331 | |
| 332 // Don't import if we already have this info. | |
| 333 // Don't present an infobar if we have already saved this card number. | |
| 334 bool merged_credit_card = false; | |
| 335 if (local_imported_credit_card.get()) { | |
| 336 for (std::vector<CreditCard*>::const_iterator iter = credit_cards_.begin(); | |
| 337 iter != credit_cards_.end(); | |
| 338 ++iter) { | |
| 339 // Make a local copy so that the data in |credit_cards_| isn't modified | |
| 340 // directly by the UpdateFromImportedCard() call. | |
| 341 CreditCard card = **iter; | |
| 342 if (card.UpdateFromImportedCard(*local_imported_credit_card.get(), | |
| 343 app_locale_)) { | |
| 344 merged_credit_card = true; | |
| 345 UpdateCreditCard(card); | |
| 346 local_imported_credit_card.reset(); | |
| 347 break; | |
| 348 } | |
| 349 } | |
| 350 } | |
| 351 | |
| 352 if (imported_profile.get()) { | |
| 353 // We always save imported profiles. | |
| 354 SaveImportedProfile(*imported_profile); | |
| 355 } | |
| 356 *imported_credit_card = local_imported_credit_card.release(); | |
| 357 | |
| 358 if (imported_profile.get() || *imported_credit_card || merged_credit_card) { | |
| 359 return true; | |
| 360 } else { | |
| 361 FOR_EACH_OBSERVER(PersonalDataManagerObserver, observers_, | |
| 362 OnInsufficientFormData()); | |
| 363 return false; | |
| 364 } | |
| 365 } | |
| 366 | |
| 367 void PersonalDataManager::AddProfile(const AutofillProfile& profile) { | |
| 368 if (browser_context_->IsOffTheRecord()) | |
| 369 return; | |
| 370 | |
| 371 if (profile.IsEmpty(app_locale_)) | |
| 372 return; | |
| 373 | |
| 374 // Don't add an existing profile. | |
| 375 if (FindByGUID<AutofillProfile>(web_profiles_, profile.guid())) | |
| 376 return; | |
| 377 | |
| 378 scoped_refptr<AutofillWebDataService> autofill_data( | |
| 379 AutofillWebDataService::FromBrowserContext(browser_context_)); | |
| 380 if (!autofill_data.get()) | |
| 381 return; | |
| 382 | |
| 383 // Don't add a duplicate. | |
| 384 if (FindByContents(web_profiles_, profile)) | |
| 385 return; | |
| 386 | |
| 387 // Add the new profile to the web database. | |
| 388 autofill_data->AddAutofillProfile(profile); | |
| 389 | |
| 390 // Refresh our local cache and send notifications to observers. | |
| 391 Refresh(); | |
| 392 } | |
| 393 | |
| 394 void PersonalDataManager::UpdateProfile(const AutofillProfile& profile) { | |
| 395 if (browser_context_->IsOffTheRecord()) | |
| 396 return; | |
| 397 | |
| 398 AutofillProfile* existing_profile = GetProfileByGUID(profile.guid()); | |
| 399 if (!existing_profile) | |
| 400 return; | |
| 401 | |
| 402 // Don't overwrite the origin for a profile that is already stored. | |
| 403 if (existing_profile->Compare(profile) == 0) | |
| 404 return; | |
| 405 | |
| 406 if (profile.IsEmpty(app_locale_)) { | |
| 407 RemoveByGUID(profile.guid()); | |
| 408 return; | |
| 409 } | |
| 410 | |
| 411 scoped_refptr<AutofillWebDataService> autofill_data( | |
| 412 AutofillWebDataService::FromBrowserContext(browser_context_)); | |
| 413 if (!autofill_data.get()) | |
| 414 return; | |
| 415 | |
| 416 // Make the update. | |
| 417 autofill_data->UpdateAutofillProfile(profile); | |
| 418 | |
| 419 // Refresh our local cache and send notifications to observers. | |
| 420 Refresh(); | |
| 421 } | |
| 422 | |
| 423 AutofillProfile* PersonalDataManager::GetProfileByGUID( | |
| 424 const std::string& guid) { | |
| 425 const std::vector<AutofillProfile*>& profiles = GetProfiles(); | |
| 426 for (std::vector<AutofillProfile*>::const_iterator iter = profiles.begin(); | |
| 427 iter != profiles.end(); ++iter) { | |
| 428 if ((*iter)->guid() == guid) | |
| 429 return *iter; | |
| 430 } | |
| 431 return NULL; | |
| 432 } | |
| 433 | |
| 434 void PersonalDataManager::AddCreditCard(const CreditCard& credit_card) { | |
| 435 if (browser_context_->IsOffTheRecord()) | |
| 436 return; | |
| 437 | |
| 438 if (credit_card.IsEmpty(app_locale_)) | |
| 439 return; | |
| 440 | |
| 441 if (FindByGUID<CreditCard>(credit_cards_, credit_card.guid())) | |
| 442 return; | |
| 443 | |
| 444 scoped_refptr<AutofillWebDataService> autofill_data( | |
| 445 AutofillWebDataService::FromBrowserContext(browser_context_)); | |
| 446 if (!autofill_data.get()) | |
| 447 return; | |
| 448 | |
| 449 // Don't add a duplicate. | |
| 450 if (FindByContents(credit_cards_, credit_card)) | |
| 451 return; | |
| 452 | |
| 453 // Add the new credit card to the web database. | |
| 454 autofill_data->AddCreditCard(credit_card); | |
| 455 | |
| 456 // Refresh our local cache and send notifications to observers. | |
| 457 Refresh(); | |
| 458 } | |
| 459 | |
| 460 void PersonalDataManager::UpdateCreditCard(const CreditCard& credit_card) { | |
| 461 if (browser_context_->IsOffTheRecord()) | |
| 462 return; | |
| 463 | |
| 464 CreditCard* existing_credit_card = GetCreditCardByGUID(credit_card.guid()); | |
| 465 if (!existing_credit_card) | |
| 466 return; | |
| 467 | |
| 468 // Don't overwrite the origin for a credit card that is already stored. | |
| 469 if (existing_credit_card->Compare(credit_card) == 0) | |
| 470 return; | |
| 471 | |
| 472 if (credit_card.IsEmpty(app_locale_)) { | |
| 473 RemoveByGUID(credit_card.guid()); | |
| 474 return; | |
| 475 } | |
| 476 | |
| 477 scoped_refptr<AutofillWebDataService> autofill_data( | |
| 478 AutofillWebDataService::FromBrowserContext(browser_context_)); | |
| 479 if (!autofill_data.get()) | |
| 480 return; | |
| 481 | |
| 482 // Make the update. | |
| 483 autofill_data->UpdateCreditCard(credit_card); | |
| 484 | |
| 485 // Refresh our local cache and send notifications to observers. | |
| 486 Refresh(); | |
| 487 } | |
| 488 | |
| 489 void PersonalDataManager::RemoveByGUID(const std::string& guid) { | |
| 490 if (browser_context_->IsOffTheRecord()) | |
| 491 return; | |
| 492 | |
| 493 bool is_credit_card = FindByGUID<CreditCard>(credit_cards_, guid); | |
| 494 bool is_profile = !is_credit_card && | |
| 495 FindByGUID<AutofillProfile>(web_profiles_, guid); | |
| 496 if (!is_credit_card && !is_profile) | |
| 497 return; | |
| 498 | |
| 499 scoped_refptr<AutofillWebDataService> autofill_data( | |
| 500 AutofillWebDataService::FromBrowserContext(browser_context_)); | |
| 501 if (!autofill_data.get()) | |
| 502 return; | |
| 503 | |
| 504 if (is_credit_card) | |
| 505 autofill_data->RemoveCreditCard(guid); | |
| 506 else | |
| 507 autofill_data->RemoveAutofillProfile(guid); | |
| 508 | |
| 509 // Refresh our local cache and send notifications to observers. | |
| 510 Refresh(); | |
| 511 } | |
| 512 | |
| 513 CreditCard* PersonalDataManager::GetCreditCardByGUID(const std::string& guid) { | |
| 514 const std::vector<CreditCard*>& credit_cards = GetCreditCards(); | |
| 515 for (std::vector<CreditCard*>::const_iterator iter = credit_cards.begin(); | |
| 516 iter != credit_cards.end(); ++iter) { | |
| 517 if ((*iter)->guid() == guid) | |
| 518 return *iter; | |
| 519 } | |
| 520 return NULL; | |
| 521 } | |
| 522 | |
| 523 void PersonalDataManager::GetNonEmptyTypes( | |
| 524 FieldTypeSet* non_empty_types) { | |
| 525 const std::vector<AutofillProfile*>& profiles = GetProfiles(); | |
| 526 for (std::vector<AutofillProfile*>::const_iterator iter = profiles.begin(); | |
| 527 iter != profiles.end(); ++iter) { | |
| 528 (*iter)->GetNonEmptyTypes(app_locale_, non_empty_types); | |
| 529 } | |
| 530 | |
| 531 for (ScopedVector<CreditCard>::const_iterator iter = credit_cards_.begin(); | |
| 532 iter != credit_cards_.end(); ++iter) { | |
| 533 (*iter)->GetNonEmptyTypes(app_locale_, non_empty_types); | |
| 534 } | |
| 535 } | |
| 536 | |
| 537 bool PersonalDataManager::IsDataLoaded() const { | |
| 538 return is_data_loaded_; | |
| 539 } | |
| 540 | |
| 541 const std::vector<AutofillProfile*>& PersonalDataManager::GetProfiles() { | |
| 542 if (!user_prefs::UserPrefs::Get(browser_context_)->GetBoolean( | |
| 543 prefs::kAutofillAuxiliaryProfilesEnabled)) { | |
| 544 return web_profiles(); | |
| 545 } | |
| 546 | |
| 547 profiles_.clear(); | |
| 548 | |
| 549 // Populates |auxiliary_profiles_|. | |
| 550 LoadAuxiliaryProfiles(); | |
| 551 | |
| 552 profiles_.insert(profiles_.end(), web_profiles_.begin(), web_profiles_.end()); | |
| 553 profiles_.insert(profiles_.end(), | |
| 554 auxiliary_profiles_.begin(), auxiliary_profiles_.end()); | |
| 555 return profiles_; | |
| 556 } | |
| 557 | |
| 558 const std::vector<AutofillProfile*>& PersonalDataManager::web_profiles() const { | |
| 559 return web_profiles_.get(); | |
| 560 } | |
| 561 | |
| 562 const std::vector<CreditCard*>& PersonalDataManager::GetCreditCards() const { | |
| 563 return credit_cards_.get(); | |
| 564 } | |
| 565 | |
| 566 void PersonalDataManager::Refresh() { | |
| 567 LoadProfiles(); | |
| 568 LoadCreditCards(); | |
| 569 } | |
| 570 | |
| 571 void PersonalDataManager::GetProfileSuggestions( | |
| 572 AutofillFieldType type, | |
| 573 const base::string16& field_contents, | |
| 574 bool field_is_autofilled, | |
| 575 std::vector<AutofillFieldType> other_field_types, | |
| 576 std::vector<base::string16>* values, | |
| 577 std::vector<base::string16>* labels, | |
| 578 std::vector<base::string16>* icons, | |
| 579 std::vector<GUIDPair>* guid_pairs) { | |
| 580 values->clear(); | |
| 581 labels->clear(); | |
| 582 icons->clear(); | |
| 583 guid_pairs->clear(); | |
| 584 | |
| 585 const std::vector<AutofillProfile*>& profiles = GetProfiles(); | |
| 586 std::vector<AutofillProfile*> matched_profiles; | |
| 587 for (std::vector<AutofillProfile*>::const_iterator iter = profiles.begin(); | |
| 588 iter != profiles.end(); ++iter) { | |
| 589 AutofillProfile* profile = *iter; | |
| 590 | |
| 591 // The value of the stored data for this field type in the |profile|. | |
| 592 std::vector<base::string16> multi_values; | |
| 593 profile->GetMultiInfo(type, app_locale_, &multi_values); | |
| 594 | |
| 595 for (size_t i = 0; i < multi_values.size(); ++i) { | |
| 596 if (!field_is_autofilled) { | |
| 597 // Suggest data that starts with what the user has typed. | |
| 598 if (!multi_values[i].empty() && | |
| 599 StartsWith(multi_values[i], field_contents, false)) { | |
| 600 matched_profiles.push_back(profile); | |
| 601 values->push_back(multi_values[i]); | |
| 602 guid_pairs->push_back(GUIDPair(profile->guid(), i)); | |
| 603 } | |
| 604 } else { | |
| 605 if (multi_values[i].empty()) | |
| 606 continue; | |
| 607 | |
| 608 base::string16 profile_value_lower_case( | |
| 609 StringToLowerASCII(multi_values[i])); | |
| 610 base::string16 field_value_lower_case( | |
| 611 StringToLowerASCII(field_contents)); | |
| 612 // Phone numbers could be split in US forms, so field value could be | |
| 613 // either prefix or suffix of the phone. | |
| 614 bool matched_phones = false; | |
| 615 if (type == PHONE_HOME_NUMBER && !field_value_lower_case.empty() && | |
| 616 (profile_value_lower_case.find(field_value_lower_case) != | |
| 617 base::string16::npos)) { | |
| 618 matched_phones = true; | |
| 619 } | |
| 620 | |
| 621 // Suggest variants of the profile that's already been filled in. | |
| 622 if (matched_phones || | |
| 623 profile_value_lower_case == field_value_lower_case) { | |
| 624 for (size_t j = 0; j < multi_values.size(); ++j) { | |
| 625 if (!multi_values[j].empty()) { | |
| 626 values->push_back(multi_values[j]); | |
| 627 guid_pairs->push_back(GUIDPair(profile->guid(), j)); | |
| 628 } | |
| 629 } | |
| 630 | |
| 631 // We've added all the values for this profile so move on to the | |
| 632 // next. | |
| 633 break; | |
| 634 } | |
| 635 } | |
| 636 } | |
| 637 } | |
| 638 | |
| 639 if (!field_is_autofilled) { | |
| 640 AutofillProfile::CreateInferredLabels( | |
| 641 &matched_profiles, &other_field_types, | |
| 642 type, 1, labels); | |
| 643 } else { | |
| 644 // No sub-labels for previously filled fields. | |
| 645 labels->resize(values->size()); | |
| 646 } | |
| 647 | |
| 648 // No icons for profile suggestions. | |
| 649 icons->resize(values->size()); | |
| 650 } | |
| 651 | |
| 652 void PersonalDataManager::GetCreditCardSuggestions( | |
| 653 AutofillFieldType type, | |
| 654 const base::string16& field_contents, | |
| 655 std::vector<base::string16>* values, | |
| 656 std::vector<base::string16>* labels, | |
| 657 std::vector<base::string16>* icons, | |
| 658 std::vector<GUIDPair>* guid_pairs) { | |
| 659 values->clear(); | |
| 660 labels->clear(); | |
| 661 icons->clear(); | |
| 662 guid_pairs->clear(); | |
| 663 | |
| 664 const std::vector<CreditCard*>& credit_cards = GetCreditCards(); | |
| 665 for (std::vector<CreditCard*>::const_iterator iter = credit_cards.begin(); | |
| 666 iter != credit_cards.end(); ++iter) { | |
| 667 CreditCard* credit_card = *iter; | |
| 668 | |
| 669 // The value of the stored data for this field type in the |credit_card|. | |
| 670 base::string16 creditcard_field_value = | |
| 671 credit_card->GetInfo(type, app_locale_); | |
| 672 if (!creditcard_field_value.empty() && | |
| 673 StartsWith(creditcard_field_value, field_contents, false)) { | |
| 674 if (type == CREDIT_CARD_NUMBER) | |
| 675 creditcard_field_value = credit_card->ObfuscatedNumber(); | |
| 676 | |
| 677 base::string16 label; | |
| 678 if (credit_card->number().empty()) { | |
| 679 // If there is no CC number, return name to show something. | |
| 680 label = credit_card->GetInfo(CREDIT_CARD_NAME, app_locale_); | |
| 681 } else { | |
| 682 label = kCreditCardPrefix; | |
| 683 label.append(credit_card->LastFourDigits()); | |
| 684 } | |
| 685 | |
| 686 values->push_back(creditcard_field_value); | |
| 687 labels->push_back(label); | |
| 688 icons->push_back(UTF8ToUTF16(credit_card->type())); | |
| 689 guid_pairs->push_back(GUIDPair(credit_card->guid(), 0)); | |
| 690 } | |
| 691 } | |
| 692 } | |
| 693 | |
| 694 bool PersonalDataManager::IsAutofillEnabled() const { | |
| 695 return user_prefs::UserPrefs::Get(browser_context_)->GetBoolean( | |
| 696 prefs::kAutofillEnabled); | |
| 697 } | |
| 698 | |
| 699 // static | |
| 700 bool PersonalDataManager::IsValidLearnableProfile( | |
| 701 const AutofillProfile& profile, | |
| 702 const std::string& app_locale) { | |
| 703 if (!IsMinimumAddress(profile, app_locale)) | |
| 704 return false; | |
| 705 | |
| 706 base::string16 email = profile.GetRawInfo(EMAIL_ADDRESS); | |
| 707 if (!email.empty() && !autofill::IsValidEmailAddress(email)) | |
| 708 return false; | |
| 709 | |
| 710 // Reject profiles with invalid US state information. | |
| 711 base::string16 state = profile.GetRawInfo(ADDRESS_HOME_STATE); | |
| 712 if (profile.GetRawInfo(ADDRESS_HOME_COUNTRY) == ASCIIToUTF16("US") && | |
| 713 !state.empty() && !IsValidState(state)) { | |
| 714 return false; | |
| 715 } | |
| 716 | |
| 717 // Reject profiles with invalid US zip information. | |
| 718 base::string16 zip = profile.GetRawInfo(ADDRESS_HOME_ZIP); | |
| 719 if (profile.GetRawInfo(ADDRESS_HOME_COUNTRY) == ASCIIToUTF16("US") && | |
| 720 !zip.empty() && !autofill::IsValidZip(zip)) | |
| 721 return false; | |
| 722 | |
| 723 return true; | |
| 724 } | |
| 725 | |
| 726 // static | |
| 727 bool PersonalDataManager::MergeProfile( | |
| 728 const AutofillProfile& new_profile, | |
| 729 const std::vector<AutofillProfile*>& existing_profiles, | |
| 730 const std::string& app_locale, | |
| 731 std::vector<AutofillProfile>* merged_profiles) { | |
| 732 merged_profiles->clear(); | |
| 733 | |
| 734 // Set to true if |existing_profiles| already contains an equivalent profile. | |
| 735 bool matching_profile_found = false; | |
| 736 | |
| 737 // If we have already saved this address, merge in any missing values. | |
| 738 // Only merge with the first match. | |
| 739 for (std::vector<AutofillProfile*>::const_iterator iter = | |
| 740 existing_profiles.begin(); | |
| 741 iter != existing_profiles.end(); ++iter) { | |
| 742 AutofillProfile* existing_profile = *iter; | |
| 743 if (!matching_profile_found && | |
| 744 !new_profile.PrimaryValue().empty() && | |
| 745 StringToLowerASCII(existing_profile->PrimaryValue()) == | |
| 746 StringToLowerASCII(new_profile.PrimaryValue())) { | |
| 747 // Unverified profiles should always be updated with the newer data, | |
| 748 // whereas verified profiles should only ever be overwritten by verified | |
| 749 // data. If an automatically aggregated profile would overwrite a | |
| 750 // verified profile, just drop it. | |
| 751 matching_profile_found = true; | |
| 752 if (!existing_profile->IsVerified() || new_profile.IsVerified()) | |
| 753 existing_profile->OverwriteWithOrAddTo(new_profile, app_locale); | |
| 754 } | |
| 755 merged_profiles->push_back(*existing_profile); | |
| 756 } | |
| 757 | |
| 758 // If the new profile was not merged with an existing one, add it to the list. | |
| 759 if (!matching_profile_found) | |
| 760 merged_profiles->push_back(new_profile); | |
| 761 | |
| 762 return matching_profile_found; | |
| 763 } | |
| 764 | |
| 765 void PersonalDataManager::SetProfiles(std::vector<AutofillProfile>* profiles) { | |
| 766 if (browser_context_->IsOffTheRecord()) | |
| 767 return; | |
| 768 | |
| 769 // Remove empty profiles from input. | |
| 770 for (std::vector<AutofillProfile>::iterator it = profiles->begin(); | |
| 771 it != profiles->end();) { | |
| 772 if (it->IsEmpty(app_locale_)) | |
| 773 profiles->erase(it); | |
| 774 else | |
| 775 it++; | |
| 776 } | |
| 777 | |
| 778 // Ensure that profile labels are up to date. Currently, sync relies on | |
| 779 // labels to identify a profile. | |
| 780 // TODO(dhollowa): We need to deprecate labels and update the way sync | |
| 781 // identifies profiles. | |
| 782 std::vector<AutofillProfile*> profile_pointers(profiles->size()); | |
| 783 std::transform(profiles->begin(), profiles->end(), profile_pointers.begin(), | |
| 784 address_of<AutofillProfile>); | |
| 785 AutofillProfile::AdjustInferredLabels(&profile_pointers); | |
| 786 | |
| 787 scoped_refptr<AutofillWebDataService> autofill_data( | |
| 788 AutofillWebDataService::FromBrowserContext(browser_context_)); | |
| 789 if (!autofill_data.get()) | |
| 790 return; | |
| 791 | |
| 792 // Any profiles that are not in the new profile list should be removed from | |
| 793 // the web database. | |
| 794 for (std::vector<AutofillProfile*>::const_iterator iter = | |
| 795 web_profiles_.begin(); | |
| 796 iter != web_profiles_.end(); ++iter) { | |
| 797 if (!FindByGUID<AutofillProfile>(*profiles, (*iter)->guid())) | |
| 798 autofill_data->RemoveAutofillProfile((*iter)->guid()); | |
| 799 } | |
| 800 | |
| 801 // Update the web database with the existing profiles. | |
| 802 for (std::vector<AutofillProfile>::iterator iter = profiles->begin(); | |
| 803 iter != profiles->end(); ++iter) { | |
| 804 if (FindByGUID<AutofillProfile>(web_profiles_, iter->guid())) | |
| 805 autofill_data->UpdateAutofillProfile(*iter); | |
| 806 } | |
| 807 | |
| 808 // Add the new profiles to the web database. Don't add a duplicate. | |
| 809 for (std::vector<AutofillProfile>::iterator iter = profiles->begin(); | |
| 810 iter != profiles->end(); ++iter) { | |
| 811 if (!FindByGUID<AutofillProfile>(web_profiles_, iter->guid()) && | |
| 812 !FindByContents(web_profiles_, *iter)) | |
| 813 autofill_data->AddAutofillProfile(*iter); | |
| 814 } | |
| 815 | |
| 816 // Copy in the new profiles. | |
| 817 web_profiles_.clear(); | |
| 818 for (std::vector<AutofillProfile>::iterator iter = profiles->begin(); | |
| 819 iter != profiles->end(); ++iter) { | |
| 820 web_profiles_.push_back(new AutofillProfile(*iter)); | |
| 821 } | |
| 822 | |
| 823 // Refresh our local cache and send notifications to observers. | |
| 824 Refresh(); | |
| 825 } | |
| 826 | |
| 827 void PersonalDataManager::SetCreditCards( | |
| 828 std::vector<CreditCard>* credit_cards) { | |
| 829 if (browser_context_->IsOffTheRecord()) | |
| 830 return; | |
| 831 | |
| 832 // Remove empty credit cards from input. | |
| 833 for (std::vector<CreditCard>::iterator it = credit_cards->begin(); | |
| 834 it != credit_cards->end();) { | |
| 835 if (it->IsEmpty(app_locale_)) | |
| 836 credit_cards->erase(it); | |
| 837 else | |
| 838 it++; | |
| 839 } | |
| 840 | |
| 841 scoped_refptr<AutofillWebDataService> autofill_data( | |
| 842 AutofillWebDataService::FromBrowserContext(browser_context_)); | |
| 843 if (!autofill_data.get()) | |
| 844 return; | |
| 845 | |
| 846 // Any credit cards that are not in the new credit card list should be | |
| 847 // removed. | |
| 848 for (std::vector<CreditCard*>::const_iterator iter = credit_cards_.begin(); | |
| 849 iter != credit_cards_.end(); ++iter) { | |
| 850 if (!FindByGUID<CreditCard>(*credit_cards, (*iter)->guid())) | |
| 851 autofill_data->RemoveCreditCard((*iter)->guid()); | |
| 852 } | |
| 853 | |
| 854 // Update the web database with the existing credit cards. | |
| 855 for (std::vector<CreditCard>::iterator iter = credit_cards->begin(); | |
| 856 iter != credit_cards->end(); ++iter) { | |
| 857 if (FindByGUID<CreditCard>(credit_cards_, iter->guid())) | |
| 858 autofill_data->UpdateCreditCard(*iter); | |
| 859 } | |
| 860 | |
| 861 // Add the new credit cards to the web database. Don't add a duplicate. | |
| 862 for (std::vector<CreditCard>::iterator iter = credit_cards->begin(); | |
| 863 iter != credit_cards->end(); ++iter) { | |
| 864 if (!FindByGUID<CreditCard>(credit_cards_, iter->guid()) && | |
| 865 !FindByContents(credit_cards_, *iter)) | |
| 866 autofill_data->AddCreditCard(*iter); | |
| 867 } | |
| 868 | |
| 869 // Copy in the new credit cards. | |
| 870 credit_cards_.clear(); | |
| 871 for (std::vector<CreditCard>::iterator iter = credit_cards->begin(); | |
| 872 iter != credit_cards->end(); ++iter) { | |
| 873 credit_cards_.push_back(new CreditCard(*iter)); | |
| 874 } | |
| 875 | |
| 876 // Refresh our local cache and send notifications to observers. | |
| 877 Refresh(); | |
| 878 } | |
| 879 | |
| 880 void PersonalDataManager::LoadProfiles() { | |
| 881 scoped_refptr<AutofillWebDataService> autofill_data( | |
| 882 AutofillWebDataService::FromBrowserContext(browser_context_)); | |
| 883 if (!autofill_data.get()) { | |
| 884 NOTREACHED(); | |
| 885 return; | |
| 886 } | |
| 887 | |
| 888 CancelPendingQuery(&pending_profiles_query_); | |
| 889 | |
| 890 pending_profiles_query_ = autofill_data->GetAutofillProfiles(this); | |
| 891 } | |
| 892 | |
| 893 // Win and Linux implementations do nothing. Mac and Android implementations | |
| 894 // fill in the contents of |auxiliary_profiles_|. | |
| 895 #if !defined(OS_MACOSX) && !defined(OS_ANDROID) | |
| 896 void PersonalDataManager::LoadAuxiliaryProfiles() { | |
| 897 } | |
| 898 #endif | |
| 899 | |
| 900 void PersonalDataManager::LoadCreditCards() { | |
| 901 scoped_refptr<AutofillWebDataService> autofill_data( | |
| 902 AutofillWebDataService::FromBrowserContext(browser_context_)); | |
| 903 if (!autofill_data.get()) { | |
| 904 NOTREACHED(); | |
| 905 return; | |
| 906 } | |
| 907 | |
| 908 CancelPendingQuery(&pending_creditcards_query_); | |
| 909 | |
| 910 pending_creditcards_query_ = autofill_data->GetCreditCards(this); | |
| 911 } | |
| 912 | |
| 913 void PersonalDataManager::ReceiveLoadedProfiles(WebDataServiceBase::Handle h, | |
| 914 const WDTypedResult* result) { | |
| 915 DCHECK_EQ(pending_profiles_query_, h); | |
| 916 | |
| 917 pending_profiles_query_ = 0; | |
| 918 web_profiles_.clear(); | |
| 919 | |
| 920 const WDResult<std::vector<AutofillProfile*> >* r = | |
| 921 static_cast<const WDResult<std::vector<AutofillProfile*> >*>(result); | |
| 922 | |
| 923 std::vector<AutofillProfile*> profiles = r->GetValue(); | |
| 924 for (std::vector<AutofillProfile*>::iterator iter = profiles.begin(); | |
| 925 iter != profiles.end(); ++iter) { | |
| 926 web_profiles_.push_back(*iter); | |
| 927 } | |
| 928 | |
| 929 LogProfileCount(); | |
| 930 } | |
| 931 | |
| 932 void PersonalDataManager::ReceiveLoadedCreditCards( | |
| 933 WebDataServiceBase::Handle h, const WDTypedResult* result) { | |
| 934 DCHECK_EQ(pending_creditcards_query_, h); | |
| 935 | |
| 936 pending_creditcards_query_ = 0; | |
| 937 credit_cards_.clear(); | |
| 938 | |
| 939 const WDResult<std::vector<CreditCard*> >* r = | |
| 940 static_cast<const WDResult<std::vector<CreditCard*> >*>(result); | |
| 941 | |
| 942 std::vector<CreditCard*> credit_cards = r->GetValue(); | |
| 943 for (std::vector<CreditCard*>::iterator iter = credit_cards.begin(); | |
| 944 iter != credit_cards.end(); ++iter) { | |
| 945 credit_cards_.push_back(*iter); | |
| 946 } | |
| 947 } | |
| 948 | |
| 949 void PersonalDataManager::CancelPendingQuery( | |
| 950 WebDataServiceBase::Handle* handle) { | |
| 951 if (*handle) { | |
| 952 scoped_refptr<AutofillWebDataService> autofill_data( | |
| 953 AutofillWebDataService::FromBrowserContext(browser_context_)); | |
| 954 if (!autofill_data.get()) { | |
| 955 NOTREACHED(); | |
| 956 return; | |
| 957 } | |
| 958 autofill_data->CancelRequest(*handle); | |
| 959 } | |
| 960 *handle = 0; | |
| 961 } | |
| 962 | |
| 963 void PersonalDataManager::SaveImportedProfile( | |
| 964 const AutofillProfile& imported_profile) { | |
| 965 if (browser_context_->IsOffTheRecord()) | |
| 966 return; | |
| 967 | |
| 968 // Don't save a web profile if the data in the profile is a subset of an | |
| 969 // auxiliary profile. | |
| 970 for (std::vector<AutofillProfile*>::const_iterator iter = | |
| 971 auxiliary_profiles_.begin(); | |
| 972 iter != auxiliary_profiles_.end(); ++iter) { | |
| 973 if (imported_profile.IsSubsetOf(**iter, app_locale_)) | |
| 974 return; | |
| 975 } | |
| 976 | |
| 977 std::vector<AutofillProfile> profiles; | |
| 978 MergeProfile(imported_profile, web_profiles_.get(), app_locale_, &profiles); | |
| 979 SetProfiles(&profiles); | |
| 980 } | |
| 981 | |
| 982 | |
| 983 void PersonalDataManager::SaveImportedCreditCard( | |
| 984 const CreditCard& imported_card) { | |
| 985 DCHECK(!imported_card.number().empty()); | |
| 986 if (browser_context_->IsOffTheRecord()) | |
| 987 return; | |
| 988 | |
| 989 // Set to true if |imported_card| is merged into the credit card list. | |
| 990 bool merged = false; | |
| 991 | |
| 992 std::vector<CreditCard> credit_cards; | |
| 993 for (std::vector<CreditCard*>::const_iterator card = credit_cards_.begin(); | |
| 994 card != credit_cards_.end(); | |
| 995 ++card) { | |
| 996 // If |imported_card| has not yet been merged, check whether it should be | |
| 997 // with the current |card|. | |
| 998 if (!merged && (*card)->UpdateFromImportedCard(imported_card, app_locale_)) | |
| 999 merged = true; | |
| 1000 | |
| 1001 credit_cards.push_back(**card); | |
| 1002 } | |
| 1003 | |
| 1004 if (!merged) | |
| 1005 credit_cards.push_back(imported_card); | |
| 1006 | |
| 1007 SetCreditCards(&credit_cards); | |
| 1008 } | |
| 1009 | |
| 1010 void PersonalDataManager::LogProfileCount() const { | |
| 1011 if (!has_logged_profile_count_) { | |
| 1012 metric_logger_->LogStoredProfileCount(web_profiles_.size()); | |
| 1013 has_logged_profile_count_ = true; | |
| 1014 } | |
| 1015 } | |
| 1016 | |
| 1017 const AutofillMetrics* PersonalDataManager::metric_logger() const { | |
| 1018 return metric_logger_.get(); | |
| 1019 } | |
| 1020 | |
| 1021 void PersonalDataManager::set_metric_logger( | |
| 1022 const AutofillMetrics* metric_logger) { | |
| 1023 metric_logger_.reset(metric_logger); | |
| 1024 } | |
| 1025 | |
| 1026 void PersonalDataManager::set_browser_context( | |
| 1027 content::BrowserContext* context) { | |
| 1028 browser_context_ = context; | |
| 1029 } | |
| 1030 | |
| 1031 } // namespace autofill | |
| OLD | NEW |