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