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
5package org.chromium.chrome.browser.autofill;
6
7import org.chromium.base.CalledByNative;
8import org.chromium.base.JNINamespace;
9import org.chromium.base.ThreadUtils;
10
11import java.util.ArrayList;
12import java.util.List;
13
14/**
15 * Android wrapper of the PersonalDataManager which provides access from the Java
16 * layer.
17 *
18 * Only usable from the UI thread as it's primary purpose is for supporting the Android
19 * preferences UI.
20 *
21 * See chrome/browser/autofill/personal_data_manager.h for more details.
22 */
23@JNINamespace("autofill")
24public class PersonalDataManager {
25
26    /**
27     * Observer of PersonalDataManager events.
28     */
29    public interface PersonalDataManagerObserver {
30        /**
31         * Called when the data is changed.
32         */
33        public abstract void onPersonalDataChanged();
34    }
35
36    /**
37     * Autofill address information.
38     */
39    public static class AutofillProfile {
40        private String mGUID;
41        private String mOrigin;
42        private String mFullName;
43        private String mCompanyName;
44        private String mStreetAddress;
45        private String mRegion;
46        private String mLocality;
47        private String mDependentLocality;
48        private String mPostalCode;
49        private String mSortingCode;
50        private String mCountryCode;
51        private String mPhoneNumber;
52        private String mEmailAddress;
53        private String mLabel;
54        private String mLanguageCode;
55
56        @CalledByNative("AutofillProfile")
57        public static AutofillProfile create(String guid, String origin,
58                String fullName, String companyName,
59                String streetAddress, String region, String locality, String dependentLocality,
60                String postalCode, String sortingCode,
61                String country, String phoneNumber, String emailAddress, String languageCode) {
62            return new AutofillProfile(guid, origin, fullName, companyName,
63                    streetAddress,
64                    region, locality, dependentLocality,
65                    postalCode, sortingCode, country, phoneNumber, emailAddress, languageCode);
66        }
67
68        public AutofillProfile(String guid, String origin, String fullName, String companyName,
69                String streetAddress,
70                String region,
71                String locality, String dependentLocality,
72                String postalCode, String sortingCode,
73                String countryCode, String phoneNumber, String emailAddress, String languageCode) {
74            mGUID = guid;
75            mOrigin = origin;
76            mFullName = fullName;
77            mCompanyName = companyName;
78            mStreetAddress = streetAddress;
79            mRegion = region;
80            mLocality = locality;
81            mDependentLocality = dependentLocality;
82            mPostalCode = postalCode;
83            mSortingCode = sortingCode;
84            mCountryCode = countryCode;
85            mPhoneNumber = phoneNumber;
86            mEmailAddress = emailAddress;
87            mLanguageCode = languageCode;
88        }
89
90        @CalledByNative("AutofillProfile")
91        public String getGUID() {
92            return mGUID;
93        }
94
95        @CalledByNative("AutofillProfile")
96        public String getOrigin() {
97            return mOrigin;
98        }
99
100        @CalledByNative("AutofillProfile")
101        public String getFullName() {
102            return mFullName;
103        }
104
105        @CalledByNative("AutofillProfile")
106        public String getCompanyName() {
107            return mCompanyName;
108        }
109
110        @CalledByNative("AutofillProfile")
111        public String getStreetAddress() {
112            return mStreetAddress;
113        }
114
115        @CalledByNative("AutofillProfile")
116        public String getRegion() {
117            return mRegion;
118        }
119
120        @CalledByNative("AutofillProfile")
121        public String getLocality() {
122            return mLocality;
123        }
124
125        @CalledByNative("AutofillProfile")
126        public String getDependentLocality() {
127            return mDependentLocality;
128        }
129
130        public String getLabel() {
131            return mLabel;
132        }
133
134        @CalledByNative("AutofillProfile")
135        public String getPostalCode() {
136            return mPostalCode;
137        }
138
139        @CalledByNative("AutofillProfile")
140        public String getSortingCode() {
141            return mSortingCode;
142        }
143
144        @CalledByNative("AutofillProfile")
145        public String getCountryCode() {
146            return mCountryCode;
147        }
148
149        @CalledByNative("AutofillProfile")
150        public String getPhoneNumber() {
151            return mPhoneNumber;
152        }
153
154        @CalledByNative("AutofillProfile")
155        public String getEmailAddress() {
156            return mEmailAddress;
157        }
158
159        @CalledByNative("AutofillProfile")
160        public String getLanguageCode() {
161            return mLanguageCode;
162        }
163
164        public void setGUID(String guid) {
165            mGUID = guid;
166        }
167
168        public void setLabel(String label) {
169            mLabel = label;
170        }
171
172        public void setOrigin(String origin) {
173            mOrigin = origin;
174        }
175
176        public void setFullName(String fullName) {
177            mFullName = fullName;
178        }
179
180        public void setCompanyName(String companyName) {
181            mCompanyName = companyName;
182        }
183
184        public void setStreetAddress(String streetAddress) {
185            mStreetAddress = streetAddress;
186        }
187
188        public void setRegion(String region) {
189            mRegion = region;
190        }
191
192        public void setLocality(String locality) {
193            mLocality = locality;
194        }
195
196        public void setDependentLocality(String dependentLocality) {
197            mDependentLocality = dependentLocality;
198        }
199
200        public void setPostalCode(String postalCode) {
201            mPostalCode = postalCode;
202        }
203
204        public void setSortingCode(String sortingCode) {
205            mSortingCode = sortingCode;
206        }
207
208        public void setCountryCode(String countryCode) {
209            mCountryCode = countryCode;
210        }
211
212        public void setPhoneNumber(String phoneNumber) {
213            mPhoneNumber = phoneNumber;
214        }
215
216        public void setEmailAddress(String emailAddress) {
217            mEmailAddress = emailAddress;
218        }
219
220        public void setLanguageCode(String languageCode) {
221            mLanguageCode = languageCode;
222        }
223    }
224
225    /**
226     * Autofill credit card information.
227     */
228    public static class CreditCard {
229        // Note that while some of these fields are numbers, they're predominantly read,
230        // marshaled and compared as strings. To save conversions, we use strings everywhere.
231        private String mGUID;
232        private String mOrigin;
233        private String mName;
234        private String mNumber;
235        private String mObfuscatedNumber;
236        private String mMonth;
237        private String mYear;
238
239        @CalledByNative("CreditCard")
240        public static CreditCard create(String guid, String origin, String name, String number,
241                String obfuscatedNumber, String month, String year) {
242            return new CreditCard(guid, origin, name, number, obfuscatedNumber, month, year);
243        }
244
245        public CreditCard(String guid, String origin, String name, String number,
246                String obfuscatedNumber, String month, String year) {
247            mGUID = guid;
248            mOrigin = origin;
249            mName = name;
250            mNumber = number;
251            mObfuscatedNumber = obfuscatedNumber;
252            mMonth = month;
253            mYear = year;
254        }
255
256        @CalledByNative("CreditCard")
257        public String getGUID() {
258            return mGUID;
259        }
260
261        @CalledByNative("CreditCard")
262        public String getOrigin() {
263            return mOrigin;
264        }
265
266        @CalledByNative("CreditCard")
267        public String getName() {
268            return mName;
269        }
270
271        @CalledByNative("CreditCard")
272        public String getNumber() {
273            return mNumber;
274        }
275
276        public String getObfuscatedNumber() {
277            return mObfuscatedNumber;
278        }
279
280        @CalledByNative("CreditCard")
281        public String getMonth() {
282            return mMonth;
283        }
284
285        @CalledByNative("CreditCard")
286        public String getYear() {
287            return mYear;
288        }
289
290        public void setGUID(String guid) {
291            mGUID = guid;
292        }
293
294        public void setOrigin(String origin) {
295            mOrigin = origin;
296        }
297
298        public void setName(String name) {
299            mName = name;
300        }
301
302        public void setNumber(String number) {
303            mNumber = number;
304        }
305
306        public void setObfuscatedNumber(String obfuscatedNumber) {
307            mObfuscatedNumber = obfuscatedNumber;
308        }
309
310        public void setMonth(String month) {
311            mMonth = month;
312        }
313
314        public void setYear(String year) {
315            mYear = year;
316        }
317    }
318
319    private static PersonalDataManager sManager;
320
321    public static PersonalDataManager getInstance() {
322        ThreadUtils.assertOnUiThread();
323        if (sManager == null) {
324            sManager = new PersonalDataManager();
325        }
326        return sManager;
327    }
328
329    private final long mPersonalDataManagerAndroid;
330    private final List<PersonalDataManagerObserver> mDataObservers =
331            new ArrayList<PersonalDataManagerObserver>();
332
333    private PersonalDataManager() {
334        // Note that this technically leaks the native object, however, PersonalDataManager
335        // is a singleton that lives forever and there's no clean shutdown of Chrome on Android
336        mPersonalDataManagerAndroid = nativeInit();
337    }
338
339    /**
340     * Called from native when template URL service is done loading.
341     */
342    @CalledByNative
343    private void personalDataChanged() {
344        ThreadUtils.assertOnUiThread();
345        for (PersonalDataManagerObserver observer : mDataObservers) {
346            observer.onPersonalDataChanged();
347        }
348    }
349
350    /**
351     * Registers a PersonalDataManagerObserver on the native side.
352     */
353    public void registerDataObserver(PersonalDataManagerObserver observer) {
354        ThreadUtils.assertOnUiThread();
355        assert !mDataObservers.contains(observer);
356        mDataObservers.add(observer);
357    }
358
359    /**
360     * Unregisters the provided observer.
361     */
362    public void unregisterDataObserver(PersonalDataManagerObserver observer) {
363        ThreadUtils.assertOnUiThread();
364        assert (mDataObservers.size() > 0);
365        assert (mDataObservers.contains(observer));
366        mDataObservers.remove(observer);
367    }
368
369    public List<AutofillProfile> getProfiles() {
370        ThreadUtils.assertOnUiThread();
371
372        String[] profileLabels = nativeGetProfileLabels(mPersonalDataManagerAndroid);
373
374        int profileCount = nativeGetProfileCount(mPersonalDataManagerAndroid);
375        List<AutofillProfile> profiles = new ArrayList<AutofillProfile>(profileCount);
376        for (int i = 0; i < profileCount; i++) {
377            AutofillProfile profile = nativeGetProfileByIndex(mPersonalDataManagerAndroid, i);
378            profile.setLabel(profileLabels[i]);
379            profiles.add(profile);
380        }
381
382        return profiles;
383    }
384
385    public AutofillProfile getProfile(String guid) {
386        ThreadUtils.assertOnUiThread();
387        return nativeGetProfileByGUID(mPersonalDataManagerAndroid, guid);
388    }
389
390    public void deleteProfile(String guid) {
391        ThreadUtils.assertOnUiThread();
392        nativeRemoveByGUID(mPersonalDataManagerAndroid, guid);
393    }
394
395    public String setProfile(AutofillProfile profile) {
396        ThreadUtils.assertOnUiThread();
397        return nativeSetProfile(mPersonalDataManagerAndroid, profile);
398    }
399
400    public List<CreditCard> getCreditCards() {
401        ThreadUtils.assertOnUiThread();
402        int count = nativeGetCreditCardCount(mPersonalDataManagerAndroid);
403        List<CreditCard> cards = new ArrayList<CreditCard>(count);
404        for (int i = 0; i < count; i++) {
405            cards.add(nativeGetCreditCardByIndex(mPersonalDataManagerAndroid, i));
406        }
407        return cards;
408    }
409
410    public CreditCard getCreditCard(String guid) {
411        ThreadUtils.assertOnUiThread();
412        return nativeGetCreditCardByGUID(mPersonalDataManagerAndroid, guid);
413    }
414
415    public String setCreditCard(CreditCard card) {
416        ThreadUtils.assertOnUiThread();
417        return nativeSetCreditCard(mPersonalDataManagerAndroid, card);
418    }
419
420    public void deleteCreditCard(String guid) {
421        ThreadUtils.assertOnUiThread();
422        nativeRemoveByGUID(mPersonalDataManagerAndroid, guid);
423    }
424
425    /**
426     * @return Whether the Autofill feature is enabled.
427     */
428    public static boolean isAutofillEnabled() {
429        return nativeIsAutofillEnabled();
430    }
431
432    /**
433     * Enables or disables the Autofill feature.
434     * @param enable True to disable Autofill, false otherwise.
435     */
436    public static void setAutofillEnabled(boolean enable) {
437        nativeSetAutofillEnabled(enable);
438    }
439
440    /**
441     * @return Whether the Autofill feature is managed.
442     */
443    public static boolean isAutofillManaged() {
444        return nativeIsAutofillManaged();
445    }
446
447    private native long nativeInit();
448    private native int nativeGetProfileCount(long nativePersonalDataManagerAndroid);
449    private native String[] nativeGetProfileLabels(long nativePersonalDataManagerAndroid);
450    private native AutofillProfile nativeGetProfileByIndex(long nativePersonalDataManagerAndroid,
451            int index);
452    private native AutofillProfile nativeGetProfileByGUID(long nativePersonalDataManagerAndroid,
453            String guid);
454    private native String nativeSetProfile(long nativePersonalDataManagerAndroid,
455            AutofillProfile profile);
456    private native int nativeGetCreditCardCount(long nativePersonalDataManagerAndroid);
457    private native CreditCard nativeGetCreditCardByIndex(long nativePersonalDataManagerAndroid,
458            int index);
459    private native CreditCard nativeGetCreditCardByGUID(long nativePersonalDataManagerAndroid,
460            String guid);
461    private native String nativeSetCreditCard(long nativePersonalDataManagerAndroid,
462            CreditCard card);
463    private native void nativeRemoveByGUID(long nativePersonalDataManagerAndroid, String guid);
464    private static native boolean nativeIsAutofillEnabled();
465    private static native void nativeSetAutofillEnabled(boolean enable);
466    private static native boolean nativeIsAutofillManaged();
467    private static native String nativeToCountryCode(String countryName);
468}
469