EMMA Coverage Report (generated Fri Aug 23 16:39:17 PDT 2013)
[all classes][org.chromium.components.browser.autofill]

COVERAGE SUMMARY FOR SOURCE FILE [PersonalAutofillPopulator.java]

nameclass, %method, %block, %line, %
PersonalAutofillPopulator.java14%  (1/7)10%  (4/40)13%  (52/390)12%  (9.9/80)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class PersonalAutofillPopulator$10%   (0/1)100% (0/0)100% (0/0)100% (0/0)
     
class PersonalAutofillPopulator$AddressProfileQuery0%   (0/1)0%   (0/4)0%   (0/40)0%   (0/3)
PersonalAutofillPopulator$AddressProfileQuery (): void 0%   (0/1)0%   (0/4)0%   (0/1)
PersonalAutofillPopulator$AddressProfileQuery (PersonalAutofillPopulator$1): ... 0%   (0/1)0%   (0/3)0%   (0/1)
mimeType (): String 0%   (0/1)0%   (0/2)0%   (0/1)
projection (): String [] 0%   (0/1)0%   (0/31)0%   (0/1)
     
class PersonalAutofillPopulator$EmailProfileQuery0%   (0/1)0%   (0/4)0%   (0/16)0%   (0/3)
PersonalAutofillPopulator$EmailProfileQuery (): void 0%   (0/1)0%   (0/4)0%   (0/1)
PersonalAutofillPopulator$EmailProfileQuery (PersonalAutofillPopulator$1): void 0%   (0/1)0%   (0/3)0%   (0/1)
mimeType (): String 0%   (0/1)0%   (0/2)0%   (0/1)
projection (): String [] 0%   (0/1)0%   (0/7)0%   (0/1)
     
class PersonalAutofillPopulator$NameProfileQuery0%   (0/1)0%   (0/4)0%   (0/28)0%   (0/3)
PersonalAutofillPopulator$NameProfileQuery (): void 0%   (0/1)0%   (0/4)0%   (0/1)
PersonalAutofillPopulator$NameProfileQuery (PersonalAutofillPopulator$1): void 0%   (0/1)0%   (0/3)0%   (0/1)
mimeType (): String 0%   (0/1)0%   (0/2)0%   (0/1)
projection (): String [] 0%   (0/1)0%   (0/19)0%   (0/1)
     
class PersonalAutofillPopulator$PhoneProfileQuery0%   (0/1)0%   (0/4)0%   (0/16)0%   (0/3)
PersonalAutofillPopulator$PhoneProfileQuery (): void 0%   (0/1)0%   (0/4)0%   (0/1)
PersonalAutofillPopulator$PhoneProfileQuery (PersonalAutofillPopulator$1): void 0%   (0/1)0%   (0/3)0%   (0/1)
mimeType (): String 0%   (0/1)0%   (0/2)0%   (0/1)
projection (): String [] 0%   (0/1)0%   (0/7)0%   (0/1)
     
class PersonalAutofillPopulator$ProfileQuery0%   (0/1)0%   (0/2)0%   (0/11)0%   (0/2)
PersonalAutofillPopulator$ProfileQuery (): void 0%   (0/1)0%   (0/8)0%   (0/2)
PersonalAutofillPopulator$ProfileQuery (PersonalAutofillPopulator$1): void 0%   (0/1)0%   (0/3)0%   (0/1)
     
class PersonalAutofillPopulator100% (1/1)18%  (4/22)19%  (52/279)15%  (9.9/66)
cursorFromProfileQuery (PersonalAutofillPopulator$ProfileQuery, ContentResolv... 0%   (0/1)0%   (0/18)0%   (0/2)
getCity (): String 0%   (0/1)0%   (0/3)0%   (0/1)
getCountry (): String 0%   (0/1)0%   (0/3)0%   (0/1)
getEmailAddresses (): String [] 0%   (0/1)0%   (0/3)0%   (0/1)
getFirstName (): String 0%   (0/1)0%   (0/3)0%   (0/1)
getLastName (): String 0%   (0/1)0%   (0/3)0%   (0/1)
getMiddleName (): String 0%   (0/1)0%   (0/3)0%   (0/1)
getNeighborhood (): String 0%   (0/1)0%   (0/3)0%   (0/1)
getPhoneNumbers (): String [] 0%   (0/1)0%   (0/3)0%   (0/1)
getPobox (): String 0%   (0/1)0%   (0/3)0%   (0/1)
getPostalCode (): String 0%   (0/1)0%   (0/3)0%   (0/1)
getRegion (): String 0%   (0/1)0%   (0/3)0%   (0/1)
getStreet (): String 0%   (0/1)0%   (0/3)0%   (0/1)
getSuffix (): String 0%   (0/1)0%   (0/3)0%   (0/1)
populateAddress (ContentResolver): void 0%   (0/1)0%   (0/51)0%   (0/12)
populateEmail (ContentResolver): void 0%   (0/1)0%   (0/32)0%   (0/7)
populateName (ContentResolver): void 0%   (0/1)0%   (0/36)0%   (0/9)
populatePhone (ContentResolver): void 0%   (0/1)0%   (0/32)0%   (0/7)
PersonalAutofillPopulator (Context): void 100% (1/1)42%  (11/26)44%  (4/9)
hasPermissions (Context): boolean 100% (1/1)89%  (33/37)79%  (3.9/5)
create (Context): PersonalAutofillPopulator 100% (1/1)100% (5/5)100% (1/1)
getHasPermissions (): boolean 100% (1/1)100% (3/3)100% (1/1)

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 
7package org.chromium.components.browser.autofill;
8 
9import android.app.Activity;
10import android.content.ContentProviderOperation;
11import android.content.ContentResolver;
12import android.content.Context;
13import android.content.OperationApplicationException;
14import android.content.pm.PackageManager;
15import android.database.Cursor;
16import android.database.DatabaseUtils;
17import android.net.Uri;
18import android.os.Bundle;
19import android.os.RemoteException;
20import android.provider.ContactsContract.CommonDataKinds.Phone;
21import android.provider.ContactsContract.Profile;
22import android.provider.ContactsContract;
23import android.util.Log;
24import android.view.View.OnClickListener;
25import android.view.View;
26import android.widget.Button;
27import android.widget.Toast;
28 
29import org.chromium.base.CalledByNative;
30import org.chromium.base.JNINamespace;
31 
32import 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")
39public 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.NEIGHBORHOOD,
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_ITEM_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 contentResolver) {
139        String sortDescriptor = ContactsContract.Contacts.Data.IS_PRIMARY + " DESC";
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, contentResolver);
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, contentResolver);
208        mEmailAddresses = new String[emailCursor.getCount()];
209        for (int i = 0; emailCursor.moveToNext(); i++) {
210            mEmailAddresses[i] = emailCursor.getString(emailProfileQuery.EMAIL_ADDRESS);
211        }
212        emailCursor.close();
213    }
214 
215    private void populateAddress(ContentResolver contentResolver) {
216        AddressProfileQuery addressProfileQuery = new AddressProfileQuery();
217        Cursor addressCursor = cursorFromProfileQuery(addressProfileQuery, contentResolver);
218        if(addressCursor.moveToNext()) {
219            mPobox = addressCursor.getString(addressProfileQuery.POBOX);
220            mStreet = addressCursor.getString(addressProfileQuery.STREET);
221            mNeighborhood = addressCursor.getString(addressProfileQuery.NEIGHBORHOOD);
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, contentResolver);
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 PersonalAutofillPopulator.
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}

[all classes][org.chromium.components.browser.autofill]
EMMA 2.0.5312 (C) Vladimir Roubtsov