This source file includes following definitions.
- FindElementByGUID
- FindByGUID
- IsMinimumAddress
- IsValidFieldTypeAndValue
- CompareVotes
- has_logged_profile_count_
- Init
- OnWebDataServiceRequestDone
- AutofillMultipleChanged
- AddObserver
- RemoveObserver
- ImportFormData
- AddProfile
- UpdateProfile
- GetProfileByGUID
- AddCreditCard
- UpdateCreditCard
- RemoveByGUID
- GetCreditCardByGUID
- GetNonEmptyTypes
- IsDataLoaded
- GetProfiles
- web_profiles
- GetCreditCards
- Refresh
- GetProfileSuggestions
- GetCreditCardSuggestions
- IsAutofillEnabled
- CountryCodeForCurrentTimezone
- SetPrefService
- IsValidLearnableProfile
- MergeProfile
- IsCountryOfInterest
- GetDefaultCountryCodeForNewAddress
- SetProfiles
- SetCreditCards
- LoadProfiles
- LoadAuxiliaryProfiles
- LoadCreditCards
- ReceiveLoadedProfiles
- ReceiveLoadedCreditCards
- CancelPendingQuery
- SaveImportedProfile
- NotifyPersonalDataChanged
- SaveImportedCreditCard
- LogProfileCount
- MostCommonCountryCodeFromProfiles
- EnabledPrefChanged
#include "components/autofill/core/browser/personal_data_manager.h"
#include <algorithm>
#include <functional>
#include <iterator>
#include "base/i18n/timezone.h"
#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "base/prefs/pref_service.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "components/autofill/core/browser/autofill-inl.h"
#include "components/autofill/core/browser/autofill_country.h"
#include "components/autofill/core/browser/autofill_field.h"
#include "components/autofill/core/browser/form_structure.h"
#include "components/autofill/core/browser/personal_data_manager_observer.h"
#include "components/autofill/core/browser/phone_number.h"
#include "components/autofill/core/browser/phone_number_i18n.h"
#include "components/autofill/core/browser/validation.h"
#include "components/autofill/core/common/autofill_pref_names.h"
namespace autofill {
namespace {
const base::string16::value_type kCreditCardPrefix[] = {'*', 0};
template<typename T>
class FormGroupMatchesByGUIDFunctor {
public:
explicit FormGroupMatchesByGUIDFunctor(const std::string& guid)
: guid_(guid) {
}
bool operator()(const T& form_group) {
return form_group.guid() == guid_;
}
bool operator()(const T* form_group) {
return form_group->guid() == guid_;
}
private:
const std::string guid_;
};
template<typename T, typename C>
typename C::const_iterator FindElementByGUID(const C& container,
const std::string& guid) {
return std::find_if(container.begin(),
container.end(),
FormGroupMatchesByGUIDFunctor<T>(guid));
}
template<typename T, typename C>
bool FindByGUID(const C& container, const std::string& guid) {
return FindElementByGUID<T>(container, guid) != container.end();
}
template<typename T>
class IsEmptyFunctor {
public:
explicit IsEmptyFunctor(const std::string& app_locale)
: app_locale_(app_locale) {
}
bool operator()(const T& form_group) {
return form_group.IsEmpty(app_locale_);
}
private:
const std::string app_locale_;
};
bool IsMinimumAddress(const AutofillProfile& profile,
const std::string& app_locale) {
if (profile.GetRawInfo(ADDRESS_HOME_LINE1).empty())
return false;
std::string country_code =
base::UTF16ToASCII(profile.GetRawInfo(ADDRESS_HOME_COUNTRY));
if (country_code.empty())
country_code = AutofillCountry::CountryCodeForLocale(app_locale);
AutofillCountry country(country_code, app_locale);
if (country.requires_city() && profile.GetRawInfo(ADDRESS_HOME_CITY).empty())
return false;
if (country.requires_state() &&
profile.GetRawInfo(ADDRESS_HOME_STATE).empty())
return false;
if (country.requires_zip() && profile.GetRawInfo(ADDRESS_HOME_ZIP).empty())
return false;
return true;
}
bool IsValidFieldTypeAndValue(const std::set<ServerFieldType>& types_seen,
ServerFieldType field_type,
const base::string16& value) {
if (types_seen.count(field_type) &&
field_type != PHONE_HOME_NUMBER &&
field_type != EMAIL_ADDRESS)
return false;
if (field_type != EMAIL_ADDRESS && IsValidEmailAddress(value))
return false;
return true;
}
static bool CompareVotes(const std::pair<std::string, int>& a,
const std::pair<std::string, int>& b) {
return a.second < b.second;
}
}
PersonalDataManager::PersonalDataManager(const std::string& app_locale)
: database_(NULL),
is_data_loaded_(false),
pending_profiles_query_(0),
pending_creditcards_query_(0),
app_locale_(app_locale),
metric_logger_(new AutofillMetrics),
pref_service_(NULL),
is_off_the_record_(false),
has_logged_profile_count_(false) {}
void PersonalDataManager::Init(scoped_refptr<AutofillWebDataService> database,
PrefService* pref_service,
bool is_off_the_record) {
database_ = database;
SetPrefService(pref_service);
is_off_the_record_ = is_off_the_record;
if (!is_off_the_record_)
metric_logger_->LogIsAutofillEnabledAtStartup(IsAutofillEnabled());
if (!database_.get())
return;
LoadProfiles();
LoadCreditCards();
database_->AddObserver(this);
}
PersonalDataManager::~PersonalDataManager() {
CancelPendingQuery(&pending_profiles_query_);
CancelPendingQuery(&pending_creditcards_query_);
if (database_.get())
database_->RemoveObserver(this);
}
void PersonalDataManager::OnWebDataServiceRequestDone(
WebDataServiceBase::Handle h,
const WDTypedResult* result) {
DCHECK(pending_profiles_query_ || pending_creditcards_query_);
if (!result) {
if (h == pending_creditcards_query_)
pending_creditcards_query_ = 0;
else if (h == pending_profiles_query_)
pending_profiles_query_ = 0;
return;
}
switch (result->GetType()) {
case AUTOFILL_PROFILES_RESULT:
ReceiveLoadedProfiles(h, result);
break;
case AUTOFILL_CREDITCARDS_RESULT:
ReceiveLoadedCreditCards(h, result);
break;
default:
NOTREACHED();
}
if (pending_profiles_query_ == 0 && pending_creditcards_query_ == 0) {
is_data_loaded_ = true;
NotifyPersonalDataChanged();
}
}
void PersonalDataManager::AutofillMultipleChanged() {
Refresh();
}
void PersonalDataManager::AddObserver(PersonalDataManagerObserver* observer) {
observers_.AddObserver(observer);
}
void PersonalDataManager::RemoveObserver(
PersonalDataManagerObserver* observer) {
observers_.RemoveObserver(observer);
}
bool PersonalDataManager::ImportFormData(
const FormStructure& form,
scoped_ptr<CreditCard>* imported_credit_card) {
scoped_ptr<AutofillProfile> imported_profile(new AutofillProfile);
scoped_ptr<CreditCard> local_imported_credit_card(new CreditCard);
const std::string origin = form.source_url().spec();
imported_profile->set_origin(origin);
local_imported_credit_card->set_origin(origin);
int importable_credit_card_fields = 0;
std::set<ServerFieldType> types_seen;
PhoneNumber::PhoneCombineHelper home;
for (size_t i = 0; i < form.field_count(); ++i) {
const AutofillField* field = form.field(i);
base::string16 value;
base::TrimWhitespace(field->value, base::TRIM_ALL, &value);
if (!field->IsFieldFillable() || value.empty())
continue;
AutofillType field_type = field->Type();
ServerFieldType server_field_type = field_type.GetStorableType();
FieldTypeGroup group(field_type.group());
if (server_field_type == EMAIL_ADDRESS) {
if (types_seen.count(server_field_type) &&
imported_profile->GetRawInfo(EMAIL_ADDRESS) != value) {
imported_profile.reset();
break;
}
}
if (!IsValidFieldTypeAndValue(types_seen, server_field_type, value)) {
imported_profile.reset();
local_imported_credit_card.reset();
break;
}
types_seen.insert(server_field_type);
if (group == CREDIT_CARD) {
if (LowerCaseEqualsASCII(field->form_control_type, "month")) {
DCHECK_EQ(CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR, server_field_type);
local_imported_credit_card->SetInfoForMonthInputType(value);
} else {
local_imported_credit_card->SetInfo(field_type, value, app_locale_);
}
++importable_credit_card_fields;
} else {
if (!home.SetInfo(field_type, value))
imported_profile->SetInfo(field_type, value, app_locale_);
if (server_field_type == ADDRESS_HOME_COUNTRY &&
!value.empty() &&
imported_profile->GetRawInfo(ADDRESS_HOME_COUNTRY).empty()) {
imported_profile.reset();
break;
}
}
}
if (imported_profile.get() && !home.IsEmpty()) {
base::string16 constructed_number;
if (!home.ParseNumber(*imported_profile, app_locale_,
&constructed_number) ||
!imported_profile->SetInfo(AutofillType(PHONE_HOME_WHOLE_NUMBER),
constructed_number,
app_locale_)) {
imported_profile.reset();
}
}
if (imported_profile.get() &&
!IsValidLearnableProfile(*imported_profile, app_locale_))
imported_profile.reset();
if (local_imported_credit_card.get() &&
!local_imported_credit_card->IsComplete()) {
local_imported_credit_card.reset();
}
bool merged_credit_card = false;
if (local_imported_credit_card.get()) {
for (std::vector<CreditCard*>::const_iterator iter = credit_cards_.begin();
iter != credit_cards_.end();
++iter) {
CreditCard card = **iter;
if (card.UpdateFromImportedCard(*local_imported_credit_card.get(),
app_locale_)) {
merged_credit_card = true;
UpdateCreditCard(card);
local_imported_credit_card.reset();
break;
}
}
}
if (imported_profile.get()) {
SaveImportedProfile(*imported_profile);
}
*imported_credit_card = local_imported_credit_card.Pass();
if (imported_profile.get() || *imported_credit_card || merged_credit_card)
return true;
FOR_EACH_OBSERVER(PersonalDataManagerObserver, observers_,
OnInsufficientFormData());
return false;
}
void PersonalDataManager::AddProfile(const AutofillProfile& profile) {
if (is_off_the_record_)
return;
if (profile.IsEmpty(app_locale_))
return;
if (FindByGUID<AutofillProfile>(web_profiles_, profile.guid()))
return;
if (!database_.get())
return;
if (FindByContents(web_profiles_, profile))
return;
database_->AddAutofillProfile(profile);
Refresh();
}
void PersonalDataManager::UpdateProfile(const AutofillProfile& profile) {
if (is_off_the_record_)
return;
AutofillProfile* existing_profile = GetProfileByGUID(profile.guid());
if (!existing_profile)
return;
if (existing_profile->Compare(profile) == 0)
return;
if (profile.IsEmpty(app_locale_)) {
RemoveByGUID(profile.guid());
return;
}
if (!database_.get())
return;
database_->UpdateAutofillProfile(profile);
Refresh();
}
AutofillProfile* PersonalDataManager::GetProfileByGUID(
const std::string& guid) {
const std::vector<AutofillProfile*>& profiles = GetProfiles();
std::vector<AutofillProfile*>::const_iterator iter =
FindElementByGUID<AutofillProfile>(profiles, guid);
return (iter != profiles.end()) ? *iter : NULL;
}
void PersonalDataManager::AddCreditCard(const CreditCard& credit_card) {
if (is_off_the_record_)
return;
if (credit_card.IsEmpty(app_locale_))
return;
if (FindByGUID<CreditCard>(credit_cards_, credit_card.guid()))
return;
if (!database_.get())
return;
if (FindByContents(credit_cards_, credit_card))
return;
database_->AddCreditCard(credit_card);
Refresh();
}
void PersonalDataManager::UpdateCreditCard(const CreditCard& credit_card) {
if (is_off_the_record_)
return;
CreditCard* existing_credit_card = GetCreditCardByGUID(credit_card.guid());
if (!existing_credit_card)
return;
if (existing_credit_card->Compare(credit_card) == 0)
return;
if (credit_card.IsEmpty(app_locale_)) {
RemoveByGUID(credit_card.guid());
return;
}
if (!database_.get())
return;
database_->UpdateCreditCard(credit_card);
Refresh();
}
void PersonalDataManager::RemoveByGUID(const std::string& guid) {
if (is_off_the_record_)
return;
bool is_credit_card = FindByGUID<CreditCard>(credit_cards_, guid);
bool is_profile = !is_credit_card &&
FindByGUID<AutofillProfile>(web_profiles_, guid);
if (!is_credit_card && !is_profile)
return;
if (!database_.get())
return;
if (is_credit_card)
database_->RemoveCreditCard(guid);
else
database_->RemoveAutofillProfile(guid);
Refresh();
}
CreditCard* PersonalDataManager::GetCreditCardByGUID(const std::string& guid) {
const std::vector<CreditCard*>& credit_cards = GetCreditCards();
std::vector<CreditCard*>::const_iterator iter =
FindElementByGUID<CreditCard>(credit_cards, guid);
return (iter != credit_cards.end()) ? *iter : NULL;
}
void PersonalDataManager::GetNonEmptyTypes(
ServerFieldTypeSet* non_empty_types) {
const std::vector<AutofillProfile*>& profiles = GetProfiles();
for (std::vector<AutofillProfile*>::const_iterator iter = profiles.begin();
iter != profiles.end(); ++iter) {
(*iter)->GetNonEmptyTypes(app_locale_, non_empty_types);
}
for (ScopedVector<CreditCard>::const_iterator iter = credit_cards_.begin();
iter != credit_cards_.end(); ++iter) {
(*iter)->GetNonEmptyTypes(app_locale_, non_empty_types);
}
}
bool PersonalDataManager::IsDataLoaded() const {
return is_data_loaded_;
}
const std::vector<AutofillProfile*>& PersonalDataManager::GetProfiles() const {
if (!pref_service_->GetBoolean(prefs::kAutofillAuxiliaryProfilesEnabled)) {
return web_profiles();
}
profiles_.clear();
LoadAuxiliaryProfiles();
profiles_.insert(profiles_.end(), web_profiles_.begin(), web_profiles_.end());
profiles_.insert(profiles_.end(),
auxiliary_profiles_.begin(), auxiliary_profiles_.end());
return profiles_;
}
const std::vector<AutofillProfile*>& PersonalDataManager::web_profiles() const {
return web_profiles_.get();
}
const std::vector<CreditCard*>& PersonalDataManager::GetCreditCards() const {
return credit_cards_.get();
}
void PersonalDataManager::Refresh() {
LoadProfiles();
LoadCreditCards();
}
void PersonalDataManager::GetProfileSuggestions(
const AutofillType& type,
const base::string16& field_contents,
bool field_is_autofilled,
const std::vector<ServerFieldType>& other_field_types,
const base::Callback<bool(const AutofillProfile&)>& filter,
std::vector<base::string16>* values,
std::vector<base::string16>* labels,
std::vector<base::string16>* icons,
std::vector<GUIDPair>* guid_pairs) {
values->clear();
labels->clear();
icons->clear();
guid_pairs->clear();
const std::vector<AutofillProfile*>& profiles = GetProfiles();
std::vector<AutofillProfile*> matched_profiles;
for (std::vector<AutofillProfile*>::const_iterator iter = profiles.begin();
iter != profiles.end(); ++iter) {
AutofillProfile* profile = *iter;
std::vector<base::string16> multi_values;
profile->GetMultiInfo(type, app_locale_, &multi_values);
for (size_t i = 0; i < multi_values.size(); ++i) {
if (!field_is_autofilled) {
if (!multi_values[i].empty() &&
StartsWith(multi_values[i], field_contents, false) &&
(filter.is_null() || filter.Run(*profile))) {
matched_profiles.push_back(profile);
values->push_back(multi_values[i]);
guid_pairs->push_back(GUIDPair(profile->guid(), i));
}
} else {
if (multi_values[i].empty())
continue;
base::string16 profile_value_lower_case(
StringToLowerASCII(multi_values[i]));
base::string16 field_value_lower_case(
StringToLowerASCII(field_contents));
bool matched_phones = false;
if (type.GetStorableType() == PHONE_HOME_NUMBER &&
!field_value_lower_case.empty() &&
profile_value_lower_case.find(field_value_lower_case) !=
base::string16::npos) {
matched_phones = true;
}
if (matched_phones ||
profile_value_lower_case == field_value_lower_case) {
for (size_t j = 0; j < multi_values.size(); ++j) {
if (!multi_values[j].empty()) {
values->push_back(multi_values[j]);
guid_pairs->push_back(GUIDPair(profile->guid(), j));
}
}
break;
}
}
}
}
if (!field_is_autofilled) {
AutofillProfile::CreateInferredLabels(
matched_profiles, &other_field_types,
type.GetStorableType(), 1, labels);
} else {
labels->resize(values->size());
}
icons->resize(values->size());
}
void PersonalDataManager::GetCreditCardSuggestions(
const AutofillType& type,
const base::string16& field_contents,
std::vector<base::string16>* values,
std::vector<base::string16>* labels,
std::vector<base::string16>* icons,
std::vector<GUIDPair>* guid_pairs) {
values->clear();
labels->clear();
icons->clear();
guid_pairs->clear();
const std::vector<CreditCard*>& credit_cards = GetCreditCards();
for (std::vector<CreditCard*>::const_iterator iter = credit_cards.begin();
iter != credit_cards.end(); ++iter) {
CreditCard* credit_card = *iter;
base::string16 creditcard_field_value =
credit_card->GetInfo(type, app_locale_);
if (!creditcard_field_value.empty() &&
StartsWith(creditcard_field_value, field_contents, false)) {
if (type.GetStorableType() == CREDIT_CARD_NUMBER)
creditcard_field_value = credit_card->ObfuscatedNumber();
base::string16 label;
if (credit_card->number().empty()) {
label =
credit_card->GetInfo(AutofillType(CREDIT_CARD_NAME), app_locale_);
} else {
label = kCreditCardPrefix;
label.append(credit_card->LastFourDigits());
}
values->push_back(creditcard_field_value);
labels->push_back(label);
icons->push_back(base::UTF8ToUTF16(credit_card->type()));
guid_pairs->push_back(GUIDPair(credit_card->guid(), 0));
}
}
}
bool PersonalDataManager::IsAutofillEnabled() const {
DCHECK(pref_service_);
return pref_service_->GetBoolean(prefs::kAutofillEnabled);
}
std::string PersonalDataManager::CountryCodeForCurrentTimezone() const {
return base::CountryCodeForCurrentTimezone();
}
void PersonalDataManager::SetPrefService(PrefService* pref_service) {
enabled_pref_.reset(new BooleanPrefMember);
pref_service_ = pref_service;
if (pref_service_) {
enabled_pref_->Init(prefs::kAutofillEnabled, pref_service_,
base::Bind(&PersonalDataManager::EnabledPrefChanged,
base::Unretained(this)));
}
}
bool PersonalDataManager::IsValidLearnableProfile(
const AutofillProfile& profile,
const std::string& app_locale) {
if (!IsMinimumAddress(profile, app_locale))
return false;
base::string16 email = profile.GetRawInfo(EMAIL_ADDRESS);
if (!email.empty() && !IsValidEmailAddress(email))
return false;
if (profile.IsPresentButInvalid(ADDRESS_HOME_STATE))
return false;
if (profile.IsPresentButInvalid(ADDRESS_HOME_ZIP))
return false;
return true;
}
std::string PersonalDataManager::MergeProfile(
const AutofillProfile& new_profile,
const std::vector<AutofillProfile*>& existing_profiles,
const std::string& app_locale,
std::vector<AutofillProfile>* merged_profiles) {
merged_profiles->clear();
bool matching_profile_found = false;
std::string guid = new_profile.guid();
for (std::vector<AutofillProfile*>::const_iterator iter =
existing_profiles.begin();
iter != existing_profiles.end(); ++iter) {
AutofillProfile* existing_profile = *iter;
if (!matching_profile_found &&
!new_profile.PrimaryValue().empty() &&
StringToLowerASCII(existing_profile->PrimaryValue()) ==
StringToLowerASCII(new_profile.PrimaryValue())) {
matching_profile_found = true;
guid = existing_profile->guid();
if (!existing_profile->IsVerified() || new_profile.IsVerified())
existing_profile->OverwriteWithOrAddTo(new_profile, app_locale);
}
merged_profiles->push_back(*existing_profile);
}
if (!matching_profile_found)
merged_profiles->push_back(new_profile);
return guid;
}
bool PersonalDataManager::IsCountryOfInterest(const std::string& country_code)
const {
DCHECK_EQ(2U, country_code.size());
const std::vector<AutofillProfile*>& profiles = web_profiles();
std::list<std::string> country_codes;
for (size_t i = 0; i < profiles.size(); ++i) {
country_codes.push_back(StringToLowerASCII(base::UTF16ToASCII(
profiles[i]->GetRawInfo(ADDRESS_HOME_COUNTRY))));
}
std::string timezone_country = CountryCodeForCurrentTimezone();
if (!timezone_country.empty())
country_codes.push_back(StringToLowerASCII(timezone_country));
if (country_codes.empty()) {
country_codes.push_back(StringToLowerASCII(
AutofillCountry::CountryCodeForLocale(app_locale())));
}
return std::find(country_codes.begin(), country_codes.end(),
StringToLowerASCII(country_code)) != country_codes.end();
}
const std::string& PersonalDataManager::GetDefaultCountryCodeForNewAddress()
const {
if (default_country_code_.empty())
default_country_code_ = MostCommonCountryCodeFromProfiles();
if (default_country_code_.empty())
default_country_code_ = CountryCodeForCurrentTimezone();
if (default_country_code_.empty())
default_country_code_ = AutofillCountry::CountryCodeForLocale(app_locale());
return default_country_code_;
}
void PersonalDataManager::SetProfiles(std::vector<AutofillProfile>* profiles) {
if (is_off_the_record_)
return;
profiles->erase(std::remove_if(profiles->begin(), profiles->end(),
IsEmptyFunctor<AutofillProfile>(app_locale_)),
profiles->end());
if (!database_.get())
return;
for (std::vector<AutofillProfile*>::const_iterator iter =
web_profiles_.begin();
iter != web_profiles_.end(); ++iter) {
if (!FindByGUID<AutofillProfile>(*profiles, (*iter)->guid()))
database_->RemoveAutofillProfile((*iter)->guid());
}
for (std::vector<AutofillProfile>::iterator iter = profiles->begin();
iter != profiles->end(); ++iter) {
if (FindByGUID<AutofillProfile>(web_profiles_, iter->guid()))
database_->UpdateAutofillProfile(*iter);
}
for (std::vector<AutofillProfile>::iterator iter = profiles->begin();
iter != profiles->end(); ++iter) {
if (!FindByGUID<AutofillProfile>(web_profiles_, iter->guid()) &&
!FindByContents(web_profiles_, *iter))
database_->AddAutofillProfile(*iter);
}
web_profiles_.clear();
for (std::vector<AutofillProfile>::iterator iter = profiles->begin();
iter != profiles->end(); ++iter) {
web_profiles_.push_back(new AutofillProfile(*iter));
}
Refresh();
}
void PersonalDataManager::SetCreditCards(
std::vector<CreditCard>* credit_cards) {
if (is_off_the_record_)
return;
credit_cards->erase(std::remove_if(credit_cards->begin(), credit_cards->end(),
IsEmptyFunctor<CreditCard>(app_locale_)),
credit_cards->end());
if (!database_.get())
return;
for (std::vector<CreditCard*>::const_iterator iter = credit_cards_.begin();
iter != credit_cards_.end(); ++iter) {
if (!FindByGUID<CreditCard>(*credit_cards, (*iter)->guid()))
database_->RemoveCreditCard((*iter)->guid());
}
for (std::vector<CreditCard>::iterator iter = credit_cards->begin();
iter != credit_cards->end(); ++iter) {
if (FindByGUID<CreditCard>(credit_cards_, iter->guid()))
database_->UpdateCreditCard(*iter);
}
for (std::vector<CreditCard>::iterator iter = credit_cards->begin();
iter != credit_cards->end(); ++iter) {
if (!FindByGUID<CreditCard>(credit_cards_, iter->guid()) &&
!FindByContents(credit_cards_, *iter))
database_->AddCreditCard(*iter);
}
credit_cards_.clear();
for (std::vector<CreditCard>::iterator iter = credit_cards->begin();
iter != credit_cards->end(); ++iter) {
credit_cards_.push_back(new CreditCard(*iter));
}
Refresh();
}
void PersonalDataManager::LoadProfiles() {
if (!database_.get()) {
NOTREACHED();
return;
}
CancelPendingQuery(&pending_profiles_query_);
pending_profiles_query_ = database_->GetAutofillProfiles(this);
}
#if defined(OS_IOS) || (!defined(OS_MACOSX) && !defined(OS_ANDROID))
void PersonalDataManager::LoadAuxiliaryProfiles() const {
}
#endif
void PersonalDataManager::LoadCreditCards() {
if (!database_.get()) {
NOTREACHED();
return;
}
CancelPendingQuery(&pending_creditcards_query_);
pending_creditcards_query_ = database_->GetCreditCards(this);
}
void PersonalDataManager::ReceiveLoadedProfiles(WebDataServiceBase::Handle h,
const WDTypedResult* result) {
DCHECK_EQ(pending_profiles_query_, h);
pending_profiles_query_ = 0;
web_profiles_.clear();
const WDResult<std::vector<AutofillProfile*> >* r =
static_cast<const WDResult<std::vector<AutofillProfile*> >*>(result);
std::vector<AutofillProfile*> profiles = r->GetValue();
for (std::vector<AutofillProfile*>::iterator iter = profiles.begin();
iter != profiles.end(); ++iter) {
web_profiles_.push_back(*iter);
}
LogProfileCount();
}
void PersonalDataManager::ReceiveLoadedCreditCards(
WebDataServiceBase::Handle h, const WDTypedResult* result) {
DCHECK_EQ(pending_creditcards_query_, h);
pending_creditcards_query_ = 0;
credit_cards_.clear();
const WDResult<std::vector<CreditCard*> >* r =
static_cast<const WDResult<std::vector<CreditCard*> >*>(result);
std::vector<CreditCard*> credit_cards = r->GetValue();
for (std::vector<CreditCard*>::iterator iter = credit_cards.begin();
iter != credit_cards.end(); ++iter) {
credit_cards_.push_back(*iter);
}
}
void PersonalDataManager::CancelPendingQuery(
WebDataServiceBase::Handle* handle) {
if (*handle) {
if (!database_.get()) {
NOTREACHED();
return;
}
database_->CancelRequest(*handle);
}
*handle = 0;
}
std::string PersonalDataManager::SaveImportedProfile(
const AutofillProfile& imported_profile) {
if (is_off_the_record_)
return std::string();
for (std::vector<AutofillProfile*>::const_iterator iter =
auxiliary_profiles_.begin();
iter != auxiliary_profiles_.end(); ++iter) {
if (imported_profile.IsSubsetOf(**iter, app_locale_))
return (*iter)->guid();
}
std::vector<AutofillProfile> profiles;
std::string guid =
MergeProfile(imported_profile, web_profiles_.get(), app_locale_,
&profiles);
SetProfiles(&profiles);
return guid;
}
void PersonalDataManager::NotifyPersonalDataChanged() {
FOR_EACH_OBSERVER(PersonalDataManagerObserver, observers_,
OnPersonalDataChanged());
}
std::string PersonalDataManager::SaveImportedCreditCard(
const CreditCard& imported_card) {
DCHECK(!imported_card.number().empty());
if (is_off_the_record_)
return std::string();
bool merged = false;
std::string guid = imported_card.guid();
std::vector<CreditCard> credit_cards;
for (std::vector<CreditCard*>::const_iterator iter = credit_cards_.begin();
iter != credit_cards_.end();
++iter) {
CreditCard* card = *iter;
if (!merged && card->UpdateFromImportedCard(imported_card, app_locale_)) {
guid = card->guid();
merged = true;
}
credit_cards.push_back(*card);
}
if (!merged)
credit_cards.push_back(imported_card);
SetCreditCards(&credit_cards);
return guid;
}
void PersonalDataManager::LogProfileCount() const {
if (!has_logged_profile_count_) {
metric_logger_->LogStoredProfileCount(web_profiles_.size());
has_logged_profile_count_ = true;
}
}
std::string PersonalDataManager::MostCommonCountryCodeFromProfiles() const {
if (!IsAutofillEnabled())
return std::string();
std::map<std::string, int> votes;
const std::vector<AutofillProfile*>& profiles = web_profiles();
std::vector<std::string> country_codes;
AutofillCountry::GetAvailableCountries(&country_codes);
for (size_t i = 0; i < profiles.size(); ++i) {
std::string country_code = StringToUpperASCII(base::UTF16ToASCII(
profiles[i]->GetRawInfo(ADDRESS_HOME_COUNTRY)));
if (std::find(country_codes.begin(), country_codes.end(), country_code) !=
country_codes.end()) {
votes[country_code] += profiles[i]->IsVerified() ? 100 : 1;
}
}
if (!votes.empty()) {
std::map<std::string, int>::iterator iter =
std::max_element(votes.begin(), votes.end(), CompareVotes);
return iter->first;
}
return std::string();
}
void PersonalDataManager::EnabledPrefChanged() {
default_country_code_.clear();
NotifyPersonalDataChanged();
}
}