Index: components/autofill/core/browser/personal_data_manager_mac.mm |
diff --git a/components/autofill/core/browser/personal_data_manager_mac.mm b/components/autofill/core/browser/personal_data_manager_mac.mm |
index 42e517f38d1bbccad25c584f49d20facde02fd65..1e43a886c474dce47cd8c25c64c2789d032564f1 100644 |
--- a/components/autofill/core/browser/personal_data_manager_mac.mm |
+++ b/components/autofill/core/browser/personal_data_manager_mac.mm |
@@ -18,6 +18,7 @@ |
#include "base/prefs/pref_service.h" |
#include "base/strings/stringprintf.h" |
#include "base/strings/sys_string_conversions.h" |
+#include "base/time/time.h" |
#include "components/autofill/core/browser/autofill_country.h" |
#include "components/autofill/core/browser/autofill_profile.h" |
#include "components/autofill/core/browser/autofill_type.h" |
@@ -76,9 +77,38 @@ void RecordAccessSkipped(bool skipped) { |
UMA_HISTOGRAM_BOOLEAN("Autofill.AddressBook.AccessSkipped", skipped); |
} |
+// Emits a histogram indicating whether the Address Book contained a me-card. |
+void EmitAddressBookContainedMeCard(bool containedMeCard) { |
+ UMA_HISTOGRAM_BOOLEAN("Autofill.MacAddressBook.ContainedMeCard", |
+ containedMeCard); |
+} |
+ |
+// Emits a histogram indicating whether the me-card had a name. |
+void EmitMeCardHadName(bool hadName) { |
+ UMA_HISTOGRAM_BOOLEAN("Autofill.MacAddressBook.MeCard.HadName", hadName); |
+} |
+ |
+// Emits a histogram indicating whether the me-card had an address. |
+void EmitMeCardHadAddress(bool hadAddress) { |
+ UMA_HISTOGRAM_BOOLEAN("Autofill.MacAddressBook.MeCard.HadAddress", |
+ hadAddress); |
+} |
+ |
+// Emits a histogram indicating whether the me-card had an email. |
+void EmitMeCardHadEmail(bool hadEmail) { |
+ UMA_HISTOGRAM_BOOLEAN("Autofill.MacAddressBook.MeCard.HadEmail", hadEmail); |
+} |
+ |
+// Emits a histogram indicating whether the me-card had a phone number. |
+void EmitMeCardHadPhoneNumber(bool hadPhoneNumber) { |
+ UMA_HISTOGRAM_BOOLEAN("Autofill.MacAddressBook.MeCard.HadPhoneNumber", |
+ hadPhoneNumber); |
+} |
+ |
ABAddressBook* GetAddressBook(PrefService* pref_service) { |
bool first_access = !HasQueriedMacAddressBook(pref_service); |
+ base::Time start_time = base::Time::Now(); |
// +[ABAddressBook sharedAddressBook] throws an exception internally in |
// circumstances that aren't clear. The exceptions are only observed in crash |
// reports, so it is unknown whether they would be caught by AppKit and nil |
@@ -88,6 +118,13 @@ ABAddressBook* GetAddressBook(PrefService* pref_service) { |
^{ return [ABAddressBook sharedAddressBook]; }); |
UMA_HISTOGRAM_BOOLEAN("Autofill.AddressBookAvailable", addressBook != nil); |
+ if (!g_accessed_address_book) { |
+ // The amount of time that the access takes gives a good indication as to |
+ // whether the user was shown a prompt. |
+ UMA_HISTOGRAM_TIMES("Autofill.MacAddressBook.AccessTime", |
+ base::Time::Now() - start_time); |
+ } |
+ |
if (first_access) { |
UMA_HISTOGRAM_BOOLEAN("Autofill.AddressBookAvailableOnFirstAttempt", |
addressBook != nil); |
@@ -121,16 +158,16 @@ class AuxiliaryProfilesImpl { |
bool record_metrics); |
private: |
- void GetAddressBookNames(ABPerson* me, |
+ bool GetAddressBookNames(ABPerson* me, |
NSString* addressLabelRaw, |
AutofillProfile* profile); |
- void GetAddressBookAddress(const std::string& app_locale, |
+ bool GetAddressBookAddress(const std::string& app_locale, |
NSDictionary* address, |
AutofillProfile* profile); |
- void GetAddressBookEmail(ABPerson* me, |
+ bool GetAddressBookEmail(ABPerson* me, |
NSString* addressLabelRaw, |
AutofillProfile* profile); |
- void GetAddressBookPhoneNumbers(ABPerson* me, |
+ bool GetAddressBookPhoneNumbers(ABPerson* me, |
NSString* addressLabelRaw, |
AutofillProfile* profile); |
@@ -169,9 +206,12 @@ void AuxiliaryProfilesImpl::GetAddressBookMeCard(const std::string& app_locale, |
ABAddressBook* addressBook = GetAddressBook(pref_service); |
ABPerson* me = [addressBook me]; |
- if (!me) |
+ if (!me) { |
+ EmitAddressBookContainedMeCard(false); |
return; |
+ } |
+ EmitAddressBookContainedMeCard(true); |
ABMultiValue* addresses = [me valueForProperty:kABAddressProperty]; |
// The number of characters at the end of the GUID to reserve for |
@@ -182,6 +222,11 @@ void AuxiliaryProfilesImpl::GetAddressBookMeCard(const std::string& app_locale, |
const size_t kNumHexDigits = 16; |
const size_t kMaxAddressCount = pow(kNumHexDigits, kNumAddressGUIDChars); |
NSUInteger count = MIN([addresses count], kMaxAddressCount); |
+ |
+ bool hasName = false; |
+ bool hasEmail = false; |
+ bool hasAddress = false; |
+ bool hasPhoneNumber = false; |
for (NSUInteger i = 0; i < count; i++) { |
NSDictionary* address = [addresses valueAtIndex:i]; |
NSString* addressLabelRaw = [addresses labelAtIndex:i]; |
@@ -211,28 +256,34 @@ void AuxiliaryProfilesImpl::GetAddressBookMeCard(const std::string& app_locale, |
DCHECK(base::IsValidGUID(profile->guid())); |
// Fill in name and company information. |
- GetAddressBookNames(me, addressLabelRaw, profile.get()); |
+ hasName |= GetAddressBookNames(me, addressLabelRaw, profile.get()); |
// Fill in address information. |
- GetAddressBookAddress(app_locale, address, profile.get()); |
+ hasEmail |= GetAddressBookAddress(app_locale, address, profile.get()); |
// Fill in email information. |
- GetAddressBookEmail(me, addressLabelRaw, profile.get()); |
+ hasAddress |= GetAddressBookEmail(me, addressLabelRaw, profile.get()); |
// Fill in phone number information. |
- GetAddressBookPhoneNumbers(me, addressLabelRaw, profile.get()); |
+ hasPhoneNumber |= |
+ GetAddressBookPhoneNumbers(me, addressLabelRaw, profile.get()); |
profiles_.push_back(profile.release()); |
} |
+ |
+ EmitMeCardHadName(hasName); |
+ EmitMeCardHadEmail(hasEmail); |
+ EmitMeCardHadAddress(hasAddress); |
+ EmitMeCardHadPhoneNumber(hasPhoneNumber); |
} |
// Name and company information is stored once in the Address Book against |
// multiple addresses. We replicate that information for each profile. |
// We only propagate the company name to work profiles. |
-void AuxiliaryProfilesImpl::GetAddressBookNames( |
- ABPerson* me, |
- NSString* addressLabelRaw, |
- AutofillProfile* profile) { |
+// Returns whether |me| contains any name information. |
+bool AuxiliaryProfilesImpl::GetAddressBookNames(ABPerson* me, |
+ NSString* addressLabelRaw, |
+ AutofillProfile* profile) { |
NSString* firstName = [me valueForProperty:kABFirstNameProperty]; |
NSString* middleName = [me valueForProperty:kABMiddleNameProperty]; |
NSString* lastName = [me valueForProperty:kABLastNameProperty]; |
@@ -243,6 +294,9 @@ void AuxiliaryProfilesImpl::GetAddressBookNames( |
profile->SetRawInfo(NAME_LAST, base::SysNSStringToUTF16(lastName)); |
if ([addressLabelRaw isEqualToString:kABAddressWorkLabel]) |
profile->SetRawInfo(COMPANY_NAME, base::SysNSStringToUTF16(companyName)); |
+ |
+ return [firstName length] > 0 || [middleName length] > 0 || |
+ [lastName length] > 0; |
} |
// Addresss information from the Address Book may span multiple lines. |
@@ -250,10 +304,15 @@ void AuxiliaryProfilesImpl::GetAddressBookNames( |
// second line we join with commas. |
// For example: "c/o John Doe\n1122 Other Avenue\nApt #7" translates to |
// line 1: "c/o John Doe", line 2: "1122 Other Avenue, Apt #7". |
-void AuxiliaryProfilesImpl::GetAddressBookAddress(const std::string& app_locale, |
+// Returns whether |address| contains a complete address. |
+bool AuxiliaryProfilesImpl::GetAddressBookAddress(const std::string& app_locale, |
NSDictionary* address, |
AutofillProfile* profile) { |
+ bool hasStreetAddress = false; |
+ bool hasCityOrZip = false; |
if (NSString* addressField = [address objectForKey:kABAddressStreetKey]) { |
+ hasStreetAddress |= [addressField length] > 0; |
+ |
// If there are newlines in the address, split into two lines. |
if ([addressField rangeOfCharacterFromSet: |
[NSCharacterSet newlineCharacterSet]].location != NSNotFound) { |
@@ -278,29 +337,34 @@ void AuxiliaryProfilesImpl::GetAddressBookAddress(const std::string& app_locale, |
} |
} |
- if (NSString* city = [address objectForKey:kABAddressCityKey]) |
+ if (NSString* city = [address objectForKey:kABAddressCityKey]) { |
+ hasCityOrZip |= [city length] > 0; |
profile->SetRawInfo(ADDRESS_HOME_CITY, base::SysNSStringToUTF16(city)); |
+ } |
if (NSString* state = [address objectForKey:kABAddressStateKey]) |
profile->SetRawInfo(ADDRESS_HOME_STATE, base::SysNSStringToUTF16(state)); |
- if (NSString* zip = [address objectForKey:kABAddressZIPKey]) |
+ if (NSString* zip = [address objectForKey:kABAddressZIPKey]) { |
+ hasCityOrZip |= [zip length] > 0; |
profile->SetRawInfo(ADDRESS_HOME_ZIP, base::SysNSStringToUTF16(zip)); |
+ } |
- if (NSString* country = [address objectForKey:kABAddressCountryKey]) { |
+ if (NSString* country = [address objectForKey:kABAddressCountryKey]) |
profile->SetInfo(AutofillType(ADDRESS_HOME_COUNTRY), |
base::SysNSStringToUTF16(country), |
app_locale); |
- } |
+ |
+ return hasStreetAddress && hasCityOrZip; |
} |
// Fills in email address matching current address label. Note that there may |
// be multiple matching email addresses for a given label. We take the |
// first we find (topmost) as preferred. |
-void AuxiliaryProfilesImpl::GetAddressBookEmail( |
- ABPerson* me, |
- NSString* addressLabelRaw, |
- AutofillProfile* profile) { |
+// Returns whether |me| contains an email. |
+bool AuxiliaryProfilesImpl::GetAddressBookEmail(ABPerson* me, |
+ NSString* addressLabelRaw, |
+ AutofillProfile* profile) { |
ABMultiValue* emailAddresses = [me valueForProperty:kABEmailProperty]; |
NSString* emailAddress = nil; |
for (NSUInteger j = 0, emailCount = [emailAddresses count]; |
@@ -312,16 +376,19 @@ void AuxiliaryProfilesImpl::GetAddressBookEmail( |
} |
} |
profile->SetRawInfo(EMAIL_ADDRESS, base::SysNSStringToUTF16(emailAddress)); |
+ return [emailAddress length] > 0; |
} |
// Fills in telephone numbers. Each of these are special cases. |
// We match two cases: home/tel, work/tel. |
// Note, we traverse in reverse order so that top values in address book |
// take priority. |
-void AuxiliaryProfilesImpl::GetAddressBookPhoneNumbers( |
+// Returns whether |me| contains a phone number. |
+bool AuxiliaryProfilesImpl::GetAddressBookPhoneNumbers( |
ABPerson* me, |
NSString* addressLabelRaw, |
AutofillProfile* profile) { |
+ bool hasPhoneNumber = false; |
ABMultiValue* phoneNumbers = [me valueForProperty:kABPhoneProperty]; |
for (NSUInteger k = 0, phoneCount = [phoneNumbers count]; |
k < phoneCount; k++) { |
@@ -332,18 +399,22 @@ void AuxiliaryProfilesImpl::GetAddressBookPhoneNumbers( |
base::string16 homePhone = base::SysNSStringToUTF16( |
[phoneNumbers valueAtIndex:reverseK]); |
profile->SetRawInfo(PHONE_HOME_WHOLE_NUMBER, homePhone); |
+ hasPhoneNumber |= !homePhone.empty(); |
} else if ([addressLabelRaw isEqualToString:kABAddressWorkLabel] && |
[phoneLabelRaw isEqualToString:kABPhoneWorkLabel]) { |
base::string16 workPhone = base::SysNSStringToUTF16( |
[phoneNumbers valueAtIndex:reverseK]); |
profile->SetRawInfo(PHONE_HOME_WHOLE_NUMBER, workPhone); |
+ hasPhoneNumber |= !workPhone.empty(); |
} else if ([phoneLabelRaw isEqualToString:kABPhoneMobileLabel] || |
[phoneLabelRaw isEqualToString:kABPhoneMainLabel]) { |
base::string16 phone = base::SysNSStringToUTF16( |
[phoneNumbers valueAtIndex:reverseK]); |
profile->SetRawInfo(PHONE_HOME_WHOLE_NUMBER, phone); |
+ hasPhoneNumber |= !phone.empty(); |
} |
} |
+ return hasPhoneNumber; |
} |
} // namespace |