135e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck
235e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck/*
335e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck * Copyright (C) 2011 The Android Open Source Project
435e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck *
535e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck * Licensed under the Apache License, Version 2.0 (the "License");
635e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck * you may not use this file except in compliance with the License.
735e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck * You may obtain a copy of the License at
835e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck *
935e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck *      http://www.apache.org/licenses/LICENSE-2.0
1035e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck *
1135e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck * Unless required by applicable law or agreed to in writing, software
1235e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck * distributed under the License is distributed on an "AS IS" BASIS,
1335e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1435e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck * See the License for the specific language governing permissions and
1535e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck * limitations under the License.
1635e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck */
1735e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck
1835e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reckpackage com.android.browser;
1935e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck
2035e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reckimport android.content.Context;
2135e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reckimport android.content.SharedPreferences;
2235e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reckimport android.content.SharedPreferences.Editor;
2335e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reckimport android.database.Cursor;
243d6c719b6c85d879c1c3fdc6ac902c3c9fa0a5b3Ben Murdochimport android.net.Uri;
2535e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reckimport android.os.AsyncTask;
2635e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reckimport android.os.Message;
2735e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reckimport android.preference.PreferenceManager;
283d6c719b6c85d879c1c3fdc6ac902c3c9fa0a5b3Ben Murdochimport android.provider.ContactsContract;
29234eadcf7d0dbf2d24f92c24f40343d518f6fe3aBen Murdochimport android.util.Log;
304d2fcaba7fb8eb1723943ac9a10e76d509330bd1Jonathan Dixonimport android.webkit.WebSettingsClassic.AutoFillProfile;
3135e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck
327b06c907aa31c38069ec2718bd4a388f1f801e6fJohn Reckimport java.util.concurrent.CountDownLatch;
337b06c907aa31c38069ec2718bd4a388f1f801e6fJohn Reck
3435e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reckpublic class AutofillHandler {
3535e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck
3635e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck    private AutoFillProfile mAutoFillProfile;
3735e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck    // Default to zero. In the case no profile is set up, the initial
3835e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck    // value will come from the AutoFillSettingsFragment when the user
3935e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck    // creates a profile. Otherwise, we'll read the ID of the last used
4035e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck    // profile from the prefs db.
4135e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck    private int mAutoFillActiveProfileId;
4235e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck    private static final int NO_AUTOFILL_PROFILE_SET = 0;
4335e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck
447b06c907aa31c38069ec2718bd4a388f1f801e6fJohn Reck    private CountDownLatch mLoaded = new CountDownLatch(1);
4535e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck    private Context mContext;
4635e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck
47234eadcf7d0dbf2d24f92c24f40343d518f6fe3aBen Murdoch    private static final String LOGTAG = "AutofillHandler";
48234eadcf7d0dbf2d24f92c24f40343d518f6fe3aBen Murdoch
4935e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck    public AutofillHandler(Context context) {
50914c5591baeb86bf30a5bc28930071442a822d60Ben Murdoch        mContext = context.getApplicationContext();
5135e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck    }
5235e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck
5335e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck    /**
5435e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck     * Load settings from the browser app's database. It is performed in
5535e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck     * an AsyncTask as it involves plenty of slow disk IO.
5635e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck     * NOTE: Strings used for the preferences must match those specified
5735e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck     * in the various preference XML files.
5835e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck     */
5935e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck    public void asyncLoadFromDb() {
6035e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck        // Run the initial settings load in an AsyncTask as it hits the
6135e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck        // disk multiple times through SharedPreferences and SQLite. We
6235e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck        // need to be certain though that this has completed before we start
6335e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck        // to load pages though, so in the worst case we will block waiting
6435e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck        // for it to finish in BrowserActivity.onCreate().
657b06c907aa31c38069ec2718bd4a388f1f801e6fJohn Reck         new LoadFromDb().start();
6635e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck    }
6735e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck
68234eadcf7d0dbf2d24f92c24f40343d518f6fe3aBen Murdoch    private void waitForLoad() {
697b06c907aa31c38069ec2718bd4a388f1f801e6fJohn Reck        try {
707b06c907aa31c38069ec2718bd4a388f1f801e6fJohn Reck            mLoaded.await();
71234eadcf7d0dbf2d24f92c24f40343d518f6fe3aBen Murdoch        } catch (InterruptedException e) {
72234eadcf7d0dbf2d24f92c24f40343d518f6fe3aBen Murdoch            Log.w(LOGTAG, "Caught exception while waiting for AutofillProfile to load.");
73234eadcf7d0dbf2d24f92c24f40343d518f6fe3aBen Murdoch        }
7435e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck    }
7535e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck
767b06c907aa31c38069ec2718bd4a388f1f801e6fJohn Reck    private class LoadFromDb extends Thread {
7735e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck
7835e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck        @Override
797b06c907aa31c38069ec2718bd4a388f1f801e6fJohn Reck        public void run() {
80234eadcf7d0dbf2d24f92c24f40343d518f6fe3aBen Murdoch            // Note the lack of synchronization over mAutoFillActiveProfileId and
81234eadcf7d0dbf2d24f92c24f40343d518f6fe3aBen Murdoch            // mAutoFillProfile here. This is because we control all other access
82234eadcf7d0dbf2d24f92c24f40343d518f6fe3aBen Murdoch            // to these members through the public functions of this class, and they
83234eadcf7d0dbf2d24f92c24f40343d518f6fe3aBen Murdoch            // all wait for this thread via the mLoaded CountDownLatch.
84234eadcf7d0dbf2d24f92c24f40343d518f6fe3aBen Murdoch
85234eadcf7d0dbf2d24f92c24f40343d518f6fe3aBen Murdoch            SharedPreferences p = PreferenceManager.getDefaultSharedPreferences(mContext);
8635e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck
8735e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck            // Read the last active AutoFill profile id.
8835e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck            mAutoFillActiveProfileId = p.getInt(
8935e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck                    PreferenceKeys.PREF_AUTOFILL_ACTIVE_PROFILE_ID,
9035e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck                    mAutoFillActiveProfileId);
9135e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck
9235e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck            // Load the autofill profile data from the database. We use a database separate
9335e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck            // to the browser preference DB to make it easier to support multiple profiles
94234eadcf7d0dbf2d24f92c24f40343d518f6fe3aBen Murdoch            // and switching between them. Note that this may block startup if this DB lookup
95234eadcf7d0dbf2d24f92c24f40343d518f6fe3aBen Murdoch            // is extremely slow. We do this to ensure that if there's a profile set, the
96234eadcf7d0dbf2d24f92c24f40343d518f6fe3aBen Murdoch            // user never sees the "setup Autofill" option.
9735e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck            AutoFillProfileDatabase autoFillDb = AutoFillProfileDatabase.getInstance(mContext);
9835e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck            Cursor c = autoFillDb.getProfile(mAutoFillActiveProfileId);
9935e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck
10035e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck            if (c.getCount() > 0) {
10135e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck                c.moveToFirst();
10235e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck
10335e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck                String fullName = c.getString(c.getColumnIndex(
10435e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck                        AutoFillProfileDatabase.Profiles.FULL_NAME));
10535e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck                String email = c.getString(c.getColumnIndex(
10635e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck                        AutoFillProfileDatabase.Profiles.EMAIL_ADDRESS));
10735e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck                String company = c.getString(c.getColumnIndex(
10835e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck                        AutoFillProfileDatabase.Profiles.COMPANY_NAME));
10935e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck                String addressLine1 = c.getString(c.getColumnIndex(
11035e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck                        AutoFillProfileDatabase.Profiles.ADDRESS_LINE_1));
11135e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck                String addressLine2 = c.getString(c.getColumnIndex(
11235e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck                        AutoFillProfileDatabase.Profiles.ADDRESS_LINE_2));
11335e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck                String city = c.getString(c.getColumnIndex(
11435e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck                        AutoFillProfileDatabase.Profiles.CITY));
11535e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck                String state = c.getString(c.getColumnIndex(
11635e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck                        AutoFillProfileDatabase.Profiles.STATE));
11735e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck                String zip = c.getString(c.getColumnIndex(
11835e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck                        AutoFillProfileDatabase.Profiles.ZIP_CODE));
11935e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck                String country = c.getString(c.getColumnIndex(
12035e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck                        AutoFillProfileDatabase.Profiles.COUNTRY));
12135e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck                String phone = c.getString(c.getColumnIndex(
12235e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck                        AutoFillProfileDatabase.Profiles.PHONE_NUMBER));
12335e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck                mAutoFillProfile = new AutoFillProfile(mAutoFillActiveProfileId,
12435e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck                        fullName, email, company, addressLine1, addressLine2, city,
12535e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck                        state, zip, country, phone);
12635e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck            }
12735e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck            c.close();
12835e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck            autoFillDb.close();
12935e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck
130234eadcf7d0dbf2d24f92c24f40343d518f6fe3aBen Murdoch            // At this point we've loaded the profile if there was one, so let any thread
131234eadcf7d0dbf2d24f92c24f40343d518f6fe3aBen Murdoch            // waiting on initialization continue.
132234eadcf7d0dbf2d24f92c24f40343d518f6fe3aBen Murdoch            mLoaded.countDown();
133234eadcf7d0dbf2d24f92c24f40343d518f6fe3aBen Murdoch
134234eadcf7d0dbf2d24f92c24f40343d518f6fe3aBen Murdoch            // Synchronization note: strictly speaking, it's possible that mAutoFillProfile
135234eadcf7d0dbf2d24f92c24f40343d518f6fe3aBen Murdoch            // may get a value after we check below, but that's OK. This check is only an
136234eadcf7d0dbf2d24f92c24f40343d518f6fe3aBen Murdoch            // optimisation, and we do a proper synchronized check further down when it comes
137234eadcf7d0dbf2d24f92c24f40343d518f6fe3aBen Murdoch            // to actually setting the inferred profile.
1383d6c719b6c85d879c1c3fdc6ac902c3c9fa0a5b3Ben Murdoch            if (mAutoFillProfile == null) {
139234eadcf7d0dbf2d24f92c24f40343d518f6fe3aBen Murdoch                // We did not load a profile from disk. Try to infer one from the user's
1403d6c719b6c85d879c1c3fdc6ac902c3c9fa0a5b3Ben Murdoch                // "me" contact.
1413d6c719b6c85d879c1c3fdc6ac902c3c9fa0a5b3Ben Murdoch                final Uri profileUri = Uri.withAppendedPath(ContactsContract.Profile.CONTENT_URI,
1423d6c719b6c85d879c1c3fdc6ac902c3c9fa0a5b3Ben Murdoch                        ContactsContract.Contacts.Data.CONTENT_DIRECTORY);
1433d6c719b6c85d879c1c3fdc6ac902c3c9fa0a5b3Ben Murdoch                String name = getContactField(profileUri,
1443d6c719b6c85d879c1c3fdc6ac902c3c9fa0a5b3Ben Murdoch                        ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME,
1453d6c719b6c85d879c1c3fdc6ac902c3c9fa0a5b3Ben Murdoch                        ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE);
1463d6c719b6c85d879c1c3fdc6ac902c3c9fa0a5b3Ben Murdoch                // Only attempt to read other data and set a profile if we could successfully
1473d6c719b6c85d879c1c3fdc6ac902c3c9fa0a5b3Ben Murdoch                // get a name.
1483d6c719b6c85d879c1c3fdc6ac902c3c9fa0a5b3Ben Murdoch                if (name != null) {
1493d6c719b6c85d879c1c3fdc6ac902c3c9fa0a5b3Ben Murdoch                    String email = getContactField(profileUri,
1503d6c719b6c85d879c1c3fdc6ac902c3c9fa0a5b3Ben Murdoch                            ContactsContract.CommonDataKinds.Email.ADDRESS,
1513d6c719b6c85d879c1c3fdc6ac902c3c9fa0a5b3Ben Murdoch                            ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE);
1523d6c719b6c85d879c1c3fdc6ac902c3c9fa0a5b3Ben Murdoch                    String phone = getContactField(profileUri,
1533d6c719b6c85d879c1c3fdc6ac902c3c9fa0a5b3Ben Murdoch                            ContactsContract.CommonDataKinds.Phone.NUMBER,
1543d6c719b6c85d879c1c3fdc6ac902c3c9fa0a5b3Ben Murdoch                            ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE);
1553d6c719b6c85d879c1c3fdc6ac902c3c9fa0a5b3Ben Murdoch                    String company = getContactField(profileUri,
1563d6c719b6c85d879c1c3fdc6ac902c3c9fa0a5b3Ben Murdoch                            ContactsContract.CommonDataKinds.Organization.COMPANY,
1573d6c719b6c85d879c1c3fdc6ac902c3c9fa0a5b3Ben Murdoch                            ContactsContract.CommonDataKinds.Organization.CONTENT_ITEM_TYPE);
1583d6c719b6c85d879c1c3fdc6ac902c3c9fa0a5b3Ben Murdoch
1593d6c719b6c85d879c1c3fdc6ac902c3c9fa0a5b3Ben Murdoch                    // Can't easily get structured postal address information (even using
1603d6c719b6c85d879c1c3fdc6ac902c3c9fa0a5b3Ben Murdoch                    // CommonDataKinds.StructuredPostal) so omit prepopulating that for now.
1613d6c719b6c85d879c1c3fdc6ac902c3c9fa0a5b3Ben Murdoch                    // When querying structured postal data, it often all comes back as a string
1623d6c719b6c85d879c1c3fdc6ac902c3c9fa0a5b3Ben Murdoch                    // inside the "street" field.
1633d6c719b6c85d879c1c3fdc6ac902c3c9fa0a5b3Ben Murdoch
164234eadcf7d0dbf2d24f92c24f40343d518f6fe3aBen Murdoch                    synchronized(AutofillHandler.this) {
165234eadcf7d0dbf2d24f92c24f40343d518f6fe3aBen Murdoch                        // Only use this profile if one hasn't been set inbetween the
166234eadcf7d0dbf2d24f92c24f40343d518f6fe3aBen Murdoch                        // inital import and this thread getting to this point.
167234eadcf7d0dbf2d24f92c24f40343d518f6fe3aBen Murdoch                        if (mAutoFillProfile == null) {
168234eadcf7d0dbf2d24f92c24f40343d518f6fe3aBen Murdoch                            setAutoFillProfile(new AutoFillProfile(1, name, email, company,
169234eadcf7d0dbf2d24f92c24f40343d518f6fe3aBen Murdoch                                    null, null, null, null, null, null, phone), null);
170234eadcf7d0dbf2d24f92c24f40343d518f6fe3aBen Murdoch                        }
171234eadcf7d0dbf2d24f92c24f40343d518f6fe3aBen Murdoch                    }
1723d6c719b6c85d879c1c3fdc6ac902c3c9fa0a5b3Ben Murdoch                }
1733d6c719b6c85d879c1c3fdc6ac902c3c9fa0a5b3Ben Murdoch            }
17435e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck        }
1753d6c719b6c85d879c1c3fdc6ac902c3c9fa0a5b3Ben Murdoch
1763d6c719b6c85d879c1c3fdc6ac902c3c9fa0a5b3Ben Murdoch        private String getContactField(Uri uri, String field, String itemType) {
1773d6c719b6c85d879c1c3fdc6ac902c3c9fa0a5b3Ben Murdoch            String result = null;
1783d6c719b6c85d879c1c3fdc6ac902c3c9fa0a5b3Ben Murdoch
1793d6c719b6c85d879c1c3fdc6ac902c3c9fa0a5b3Ben Murdoch            Cursor c = mContext.getContentResolver().query(uri, new String[] { field },
1803d6c719b6c85d879c1c3fdc6ac902c3c9fa0a5b3Ben Murdoch                    ContactsContract.Data.MIMETYPE + "=?", new String[] { itemType }, null);
1813d6c719b6c85d879c1c3fdc6ac902c3c9fa0a5b3Ben Murdoch
1827458d4cbde2e5e49503d6e87924930d381b7ad89Ben Murdoch            if (c == null) {
1837458d4cbde2e5e49503d6e87924930d381b7ad89Ben Murdoch                return null;
1847458d4cbde2e5e49503d6e87924930d381b7ad89Ben Murdoch            }
1857458d4cbde2e5e49503d6e87924930d381b7ad89Ben Murdoch
1863d6c719b6c85d879c1c3fdc6ac902c3c9fa0a5b3Ben Murdoch            try {
1873d6c719b6c85d879c1c3fdc6ac902c3c9fa0a5b3Ben Murdoch                // Just use the first returned value if we get more than one.
1883d6c719b6c85d879c1c3fdc6ac902c3c9fa0a5b3Ben Murdoch                if (c.moveToFirst()) {
1893d6c719b6c85d879c1c3fdc6ac902c3c9fa0a5b3Ben Murdoch                    result = c.getString(0);
1903d6c719b6c85d879c1c3fdc6ac902c3c9fa0a5b3Ben Murdoch                }
1913d6c719b6c85d879c1c3fdc6ac902c3c9fa0a5b3Ben Murdoch            } finally {
1923d6c719b6c85d879c1c3fdc6ac902c3c9fa0a5b3Ben Murdoch                c.close();
1933d6c719b6c85d879c1c3fdc6ac902c3c9fa0a5b3Ben Murdoch            }
1943d6c719b6c85d879c1c3fdc6ac902c3c9fa0a5b3Ben Murdoch            return result;
1953d6c719b6c85d879c1c3fdc6ac902c3c9fa0a5b3Ben Murdoch        }
19635e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck    }
19735e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck
198234eadcf7d0dbf2d24f92c24f40343d518f6fe3aBen Murdoch    public synchronized void setAutoFillProfile(AutoFillProfile profile, Message msg) {
199234eadcf7d0dbf2d24f92c24f40343d518f6fe3aBen Murdoch        waitForLoad();
20072d77529cc146e2eb8e36247d448e416b56c865dJohn Reck        int profileId = NO_AUTOFILL_PROFILE_SET;
20135e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck        if (profile != null) {
20272d77529cc146e2eb8e36247d448e416b56c865dJohn Reck            profileId = profile.getUniqueId();
20335e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck            // Update the AutoFill DB with the new profile.
20435e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck            new SaveProfileToDbTask(msg).execute(profile);
20535e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck        } else {
20635e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck            // Delete the current profile.
20735e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck            if (mAutoFillProfile != null) {
20835e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck                new DeleteProfileFromDbTask(msg).execute(mAutoFillProfile.getUniqueId());
20935e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck            }
21035e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck        }
21172d77529cc146e2eb8e36247d448e416b56c865dJohn Reck        // Make sure we set mAutoFillProfile before calling setActiveAutoFillProfileId
21272d77529cc146e2eb8e36247d448e416b56c865dJohn Reck        // Calling setActiveAutoFillProfileId will trigger an update of WebViews
21372d77529cc146e2eb8e36247d448e416b56c865dJohn Reck        // which will expect a new profile to be set
21435e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck        mAutoFillProfile = profile;
21572d77529cc146e2eb8e36247d448e416b56c865dJohn Reck        setActiveAutoFillProfileId(profileId);
21635e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck    }
21735e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck
218234eadcf7d0dbf2d24f92c24f40343d518f6fe3aBen Murdoch    public synchronized AutoFillProfile getAutoFillProfile() {
219234eadcf7d0dbf2d24f92c24f40343d518f6fe3aBen Murdoch        waitForLoad();
22035e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck        return mAutoFillProfile;
22135e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck    }
22235e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck
223234eadcf7d0dbf2d24f92c24f40343d518f6fe3aBen Murdoch    private synchronized void setActiveAutoFillProfileId(int activeProfileId) {
22435e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck        mAutoFillActiveProfileId = activeProfileId;
22535e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck        Editor ed = PreferenceManager.
22635e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck            getDefaultSharedPreferences(mContext).edit();
22735e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck        ed.putInt(PreferenceKeys.PREF_AUTOFILL_ACTIVE_PROFILE_ID, activeProfileId);
22835e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck        ed.apply();
22935e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck    }
23035e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck
23135e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck    private abstract class AutoFillProfileDbTask<T> extends AsyncTask<T, Void, Void> {
23235e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck        AutoFillProfileDatabase mAutoFillProfileDb;
23335e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck        Message mCompleteMessage;
23435e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck
23535e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck        public AutoFillProfileDbTask(Message msg) {
23635e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck            mCompleteMessage = msg;
23735e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck        }
23835e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck
23935e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck        @Override
24035e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck        protected void onPostExecute(Void result) {
24135e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck            if (mCompleteMessage != null) {
24235e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck                mCompleteMessage.sendToTarget();
24335e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck            }
24435e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck            mAutoFillProfileDb.close();
24535e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck        }
24635e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck
24735e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck        @Override
24835e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck        abstract protected Void doInBackground(T... values);
24935e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck    }
25035e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck
25135e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck
25235e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck    private class SaveProfileToDbTask extends AutoFillProfileDbTask<AutoFillProfile> {
25335e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck        public SaveProfileToDbTask(Message msg) {
25435e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck            super(msg);
25535e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck        }
25635e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck
25735e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck        @Override
25835e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck        protected Void doInBackground(AutoFillProfile... values) {
25935e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck            mAutoFillProfileDb = AutoFillProfileDatabase.getInstance(mContext);
260234eadcf7d0dbf2d24f92c24f40343d518f6fe3aBen Murdoch            synchronized (AutofillHandler.this) {
261234eadcf7d0dbf2d24f92c24f40343d518f6fe3aBen Murdoch                assert mAutoFillActiveProfileId != NO_AUTOFILL_PROFILE_SET;
262234eadcf7d0dbf2d24f92c24f40343d518f6fe3aBen Murdoch                AutoFillProfile newProfile = values[0];
263234eadcf7d0dbf2d24f92c24f40343d518f6fe3aBen Murdoch                mAutoFillProfileDb.addOrUpdateProfile(mAutoFillActiveProfileId, newProfile);
264234eadcf7d0dbf2d24f92c24f40343d518f6fe3aBen Murdoch            }
26535e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck            return null;
26635e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck        }
26735e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck    }
26835e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck
26935e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck    private class DeleteProfileFromDbTask extends AutoFillProfileDbTask<Integer> {
27035e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck        public DeleteProfileFromDbTask(Message msg) {
27135e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck            super(msg);
27235e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck        }
27335e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck
27435e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck        @Override
27535e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck        protected Void doInBackground(Integer... values) {
27635e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck            mAutoFillProfileDb = AutoFillProfileDatabase.getInstance(mContext);
27735e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck            int id = values[0];
27835e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck            assert  id > 0;
27935e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck            mAutoFillProfileDb.dropProfile(id);
28035e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck            return null;
28135e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck        }
28235e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck    }
28335e9dd6283a2d65687104eb0b3a459c02dcb150bJohn Reck}
284