| OLD | NEW |
| (Empty) |
| 1 // Copyright 2013 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 // Populates data fields from Android contacts profile API (i.e. "me" contact). | |
| 6 | |
| 7 package org.chromium.components.browser.autofill; | |
| 8 | |
| 9 import android.content.ContentResolver; | |
| 10 import android.content.Context; | |
| 11 import android.content.pm.PackageManager; | |
| 12 import android.database.Cursor; | |
| 13 import android.net.Uri; | |
| 14 import android.provider.ContactsContract; | |
| 15 | |
| 16 import org.chromium.base.CalledByNative; | |
| 17 import org.chromium.base.JNINamespace; | |
| 18 | |
| 19 /** | |
| 20 * Loads user profile information stored under the "Me" contact. | |
| 21 * Requires permissions: READ_CONTACTS and READ_PROFILE. | |
| 22 */ | |
| 23 @JNINamespace("autofill") | |
| 24 public class PersonalAutofillPopulator { | |
| 25 /** | |
| 26 * SQL query definitions for obtaining specific profile information. | |
| 27 */ | |
| 28 private abstract static class ProfileQuery { | |
| 29 Uri profileDataUri = Uri.withAppendedPath( | |
| 30 ContactsContract.Profile.CONTENT_URI, | |
| 31 ContactsContract.Contacts.Data.CONTENT_DIRECTORY | |
| 32 ); | |
| 33 public abstract String[] projection(); | |
| 34 public abstract String mimeType(); | |
| 35 } | |
| 36 | |
| 37 private static class EmailProfileQuery extends ProfileQuery { | |
| 38 private static final int EMAIL_ADDRESS = 0; | |
| 39 | |
| 40 @Override | |
| 41 public String[] projection() { | |
| 42 return new String[] { | |
| 43 ContactsContract.CommonDataKinds.Email.ADDRESS, | |
| 44 }; | |
| 45 } | |
| 46 | |
| 47 @Override | |
| 48 public String mimeType() { | |
| 49 return ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE; | |
| 50 } | |
| 51 } | |
| 52 | |
| 53 private static class PhoneProfileQuery extends ProfileQuery { | |
| 54 private static final int NUMBER = 0; | |
| 55 | |
| 56 @Override | |
| 57 public String[] projection() { | |
| 58 return new String[] { | |
| 59 ContactsContract.CommonDataKinds.Phone.NUMBER, | |
| 60 }; | |
| 61 } | |
| 62 | |
| 63 @Override | |
| 64 public String mimeType() { | |
| 65 return ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE; | |
| 66 } | |
| 67 } | |
| 68 | |
| 69 private static class AddressProfileQuery extends ProfileQuery { | |
| 70 private static final int STREET = 0; | |
| 71 private static final int POBOX = 1; | |
| 72 private static final int NEIGHBORHOOD = 2; | |
| 73 private static final int CITY = 3; | |
| 74 private static final int REGION = 4; | |
| 75 private static final int POSTALCODE = 5; | |
| 76 private static final int COUNTRY = 6; | |
| 77 | |
| 78 @Override | |
| 79 public String[] projection() { | |
| 80 return new String[] { | |
| 81 ContactsContract.CommonDataKinds.StructuredPostal.STREET, | |
| 82 ContactsContract.CommonDataKinds.StructuredPostal.POBOX, | |
| 83 ContactsContract.CommonDataKinds.StructuredPostal.NEIGHBORHO
OD, | |
| 84 ContactsContract.CommonDataKinds.StructuredPostal.CITY, | |
| 85 ContactsContract.CommonDataKinds.StructuredPostal.REGION, | |
| 86 ContactsContract.CommonDataKinds.StructuredPostal.POSTCODE, | |
| 87 ContactsContract.CommonDataKinds.StructuredPostal.COUNTRY, | |
| 88 }; | |
| 89 } | |
| 90 | |
| 91 @Override | |
| 92 public String mimeType() { | |
| 93 return ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_ITE
M_TYPE; | |
| 94 } | |
| 95 } | |
| 96 | |
| 97 private static class NameProfileQuery extends ProfileQuery { | |
| 98 private static final int GIVEN_NAME = 0; | |
| 99 private static final int MIDDLE_NAME = 1; | |
| 100 private static final int FAMILY_NAME = 2; | |
| 101 private static final int SUFFIX = 3; | |
| 102 | |
| 103 @Override | |
| 104 public String[] projection() { | |
| 105 return new String[] { | |
| 106 ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME, | |
| 107 ContactsContract.CommonDataKinds.StructuredName.MIDDLE_NAME, | |
| 108 ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME, | |
| 109 ContactsContract.CommonDataKinds.StructuredName.SUFFIX | |
| 110 }; | |
| 111 } | |
| 112 | |
| 113 @Override | |
| 114 public String mimeType() { | |
| 115 return ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_
TYPE; | |
| 116 } | |
| 117 } | |
| 118 | |
| 119 /** | |
| 120 * Takes a query object, transforms into actual query and returns cursor. | |
| 121 * Primary contact values will be first. | |
| 122 */ | |
| 123 private Cursor cursorFromProfileQuery(ProfileQuery query, ContentResolver co
ntentResolver) { | |
| 124 String sortDescriptor = ContactsContract.Contacts.Data.IS_PRIMARY + " DE
SC"; | |
| 125 return contentResolver.query( | |
| 126 query.profileDataUri, | |
| 127 query.projection(), | |
| 128 ContactsContract.Contacts.Data.MIMETYPE + " = ?", | |
| 129 new String[]{query.mimeType()}, | |
| 130 sortDescriptor | |
| 131 ); | |
| 132 } | |
| 133 // Extracted data variables. | |
| 134 private String[] mEmailAddresses; | |
| 135 private String mGivenName; | |
| 136 private String mMiddleName; | |
| 137 private String mFamilyName; | |
| 138 private String mSuffix; | |
| 139 private String mPobox; | |
| 140 private String mStreet; | |
| 141 private String mNeighborhood; | |
| 142 private String mCity; | |
| 143 private String mRegion; | |
| 144 private String mCountry; | |
| 145 private String mPostalCode; | |
| 146 private String[] mPhoneNumbers; | |
| 147 private boolean mHasPermissions; | |
| 148 | |
| 149 /** | |
| 150 * Constructor | |
| 151 * @param context a valid android context reference | |
| 152 */ | |
| 153 PersonalAutofillPopulator(Context context) { | |
| 154 mHasPermissions = hasPermissions(context); | |
| 155 if (mHasPermissions) { | |
| 156 ContentResolver contentResolver = context.getContentResolver(); | |
| 157 populateName(contentResolver); | |
| 158 populateEmail(contentResolver); | |
| 159 populateAddress(contentResolver); | |
| 160 populatePhone(contentResolver); | |
| 161 } | |
| 162 } | |
| 163 | |
| 164 // Check if the user has granted permissions. | |
| 165 private boolean hasPermissions(Context context) { | |
| 166 String [] permissions = { | |
| 167 "android.permission.READ_CONTACTS", | |
| 168 "android.permission.READ_PROFILE" | |
| 169 }; | |
| 170 for (String permission : permissions) { | |
| 171 int res = context.checkCallingOrSelfPermission(permission); | |
| 172 if (res != PackageManager.PERMISSION_GRANTED) return false; | |
| 173 } | |
| 174 return true; | |
| 175 } | |
| 176 | |
| 177 // Populating data fields. | |
| 178 private void populateName(ContentResolver contentResolver) { | |
| 179 NameProfileQuery nameProfileQuery = new NameProfileQuery(); | |
| 180 Cursor nameCursor = cursorFromProfileQuery(nameProfileQuery, contentReso
lver); | |
| 181 if (nameCursor.moveToNext()) { | |
| 182 mGivenName = nameCursor.getString(nameProfileQuery.GIVEN_NAME); | |
| 183 mMiddleName = nameCursor.getString(nameProfileQuery.MIDDLE_NAME); | |
| 184 mFamilyName = nameCursor.getString(nameProfileQuery.FAMILY_NAME); | |
| 185 mSuffix = nameCursor.getString(nameProfileQuery.SUFFIX); | |
| 186 } | |
| 187 nameCursor.close(); | |
| 188 } | |
| 189 | |
| 190 private void populateEmail(ContentResolver contentResolver) { | |
| 191 EmailProfileQuery emailProfileQuery = new EmailProfileQuery(); | |
| 192 Cursor emailCursor = cursorFromProfileQuery(emailProfileQuery, contentRe
solver); | |
| 193 mEmailAddresses = new String[emailCursor.getCount()]; | |
| 194 for (int i = 0; emailCursor.moveToNext(); i++) { | |
| 195 mEmailAddresses[i] = emailCursor.getString(emailProfileQuery.EMAIL_A
DDRESS); | |
| 196 } | |
| 197 emailCursor.close(); | |
| 198 } | |
| 199 | |
| 200 private void populateAddress(ContentResolver contentResolver) { | |
| 201 AddressProfileQuery addressProfileQuery = new AddressProfileQuery(); | |
| 202 Cursor addressCursor = cursorFromProfileQuery(addressProfileQuery, conte
ntResolver); | |
| 203 if(addressCursor.moveToNext()) { | |
| 204 mPobox = addressCursor.getString(addressProfileQuery.POBOX); | |
| 205 mStreet = addressCursor.getString(addressProfileQuery.STREET); | |
| 206 mNeighborhood = addressCursor.getString(addressProfileQuery.NEIGHBOR
HOOD); | |
| 207 mCity = addressCursor.getString(addressProfileQuery.CITY); | |
| 208 mRegion = addressCursor.getString(addressProfileQuery.REGION); | |
| 209 mPostalCode = addressCursor.getString(addressProfileQuery.POSTALCODE
); | |
| 210 mCountry = addressCursor.getString(addressProfileQuery.COUNTRY); | |
| 211 } | |
| 212 addressCursor.close(); | |
| 213 } | |
| 214 | |
| 215 private void populatePhone(ContentResolver contentResolver) { | |
| 216 PhoneProfileQuery phoneProfileQuery = new PhoneProfileQuery(); | |
| 217 Cursor phoneCursor = cursorFromProfileQuery(phoneProfileQuery, contentRe
solver); | |
| 218 mPhoneNumbers = new String[phoneCursor.getCount()]; | |
| 219 for (int i = 0; phoneCursor.moveToNext(); i++) { | |
| 220 mPhoneNumbers[i] = phoneCursor.getString(phoneProfileQuery.NUMBER); | |
| 221 } | |
| 222 phoneCursor.close(); | |
| 223 } | |
| 224 | |
| 225 /** | |
| 226 * Static factory method for instance creation. | |
| 227 * @param context valid Android context. | |
| 228 * @return PersonalAutofillPopulator new instance of PersonalAutofillPopulat
or. | |
| 229 */ | |
| 230 @CalledByNative | |
| 231 static PersonalAutofillPopulator create(Context context) { | |
| 232 return new PersonalAutofillPopulator(context); | |
| 233 } | |
| 234 | |
| 235 @CalledByNative | |
| 236 private String getFirstName() { | |
| 237 return mGivenName; | |
| 238 } | |
| 239 | |
| 240 @CalledByNative | |
| 241 private String getLastName() { | |
| 242 return mFamilyName; | |
| 243 } | |
| 244 | |
| 245 @CalledByNative | |
| 246 private String getMiddleName() { | |
| 247 return mMiddleName; | |
| 248 } | |
| 249 | |
| 250 @CalledByNative | |
| 251 private String getSuffix() { | |
| 252 return mSuffix; | |
| 253 } | |
| 254 | |
| 255 @CalledByNative | |
| 256 private String[] getEmailAddresses() { | |
| 257 return mEmailAddresses; | |
| 258 } | |
| 259 | |
| 260 @CalledByNative | |
| 261 private String getStreet() { | |
| 262 return mStreet; | |
| 263 } | |
| 264 | |
| 265 @CalledByNative | |
| 266 private String getPobox() { | |
| 267 return mPobox; | |
| 268 } | |
| 269 | |
| 270 @CalledByNative | |
| 271 private String getNeighborhood() { | |
| 272 return mNeighborhood; | |
| 273 } | |
| 274 | |
| 275 @CalledByNative | |
| 276 private String getCity() { | |
| 277 return mCity; | |
| 278 } | |
| 279 | |
| 280 @CalledByNative | |
| 281 private String getRegion() { | |
| 282 return mRegion; | |
| 283 } | |
| 284 | |
| 285 @CalledByNative | |
| 286 private String getPostalCode() { | |
| 287 return mPostalCode; | |
| 288 } | |
| 289 | |
| 290 @CalledByNative | |
| 291 private String getCountry() { | |
| 292 return mCountry; | |
| 293 } | |
| 294 | |
| 295 @CalledByNative | |
| 296 private String[] getPhoneNumbers() { | |
| 297 return mPhoneNumbers; | |
| 298 } | |
| 299 | |
| 300 @CalledByNative | |
| 301 private boolean getHasPermissions() { | |
| 302 return mHasPermissions; | |
| 303 } | |
| 304 } | |
| OLD | NEW |