Browser settings refactor

Change-Id: I6fc1b21f7ea692fbe37a17bf900e9b7408a9c077
diff --git a/src/com/android/browser/AutofillHandler.java b/src/com/android/browser/AutofillHandler.java
new file mode 100644
index 0000000..b0d5dac
--- /dev/null
+++ b/src/com/android/browser/AutofillHandler.java
@@ -0,0 +1,207 @@
+
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.browser;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.Editor;
+import android.database.Cursor;
+import android.os.AsyncTask;
+import android.os.Message;
+import android.preference.PreferenceManager;
+import android.webkit.WebSettings.AutoFillProfile;
+
+public class AutofillHandler {
+
+    private AutoFillProfile mAutoFillProfile;
+    // Default to zero. In the case no profile is set up, the initial
+    // value will come from the AutoFillSettingsFragment when the user
+    // creates a profile. Otherwise, we'll read the ID of the last used
+    // profile from the prefs db.
+    private int mAutoFillActiveProfileId;
+    private static final int NO_AUTOFILL_PROFILE_SET = 0;
+
+    private boolean mLoadFromDbComplete;
+    private Context mContext;
+
+    public AutofillHandler(Context context) {
+        mContext = context;
+    }
+
+    /**
+     * Load settings from the browser app's database. It is performed in
+     * an AsyncTask as it involves plenty of slow disk IO.
+     * NOTE: Strings used for the preferences must match those specified
+     * in the various preference XML files.
+     */
+    public void asyncLoadFromDb() {
+        synchronized (this) {
+            mLoadFromDbComplete = false;
+        }
+        // Run the initial settings load in an AsyncTask as it hits the
+        // disk multiple times through SharedPreferences and SQLite. We
+        // need to be certain though that this has completed before we start
+        // to load pages though, so in the worst case we will block waiting
+        // for it to finish in BrowserActivity.onCreate().
+         new LoadFromDbTask().execute();
+    }
+
+    public void waitForLoad() {
+        synchronized (this) {
+            while (!mLoadFromDbComplete) {
+                try {
+                    wait();
+                } catch (InterruptedException e) {}
+            }
+        }
+    }
+
+    private class LoadFromDbTask extends AsyncTask<Void, Void, Void> {
+
+        @Override
+        protected Void doInBackground(Void... unused) {
+            SharedPreferences p =
+                    PreferenceManager.getDefaultSharedPreferences(mContext);
+
+            // Read the last active AutoFill profile id.
+            mAutoFillActiveProfileId = p.getInt(
+                    PreferenceKeys.PREF_AUTOFILL_ACTIVE_PROFILE_ID,
+                    mAutoFillActiveProfileId);
+
+            // Load the autofill profile data from the database. We use a database separate
+            // to the browser preference DB to make it easier to support multiple profiles
+            // and switching between them.
+            AutoFillProfileDatabase autoFillDb = AutoFillProfileDatabase.getInstance(mContext);
+            Cursor c = autoFillDb.getProfile(mAutoFillActiveProfileId);
+
+            if (c.getCount() > 0) {
+                c.moveToFirst();
+
+                String fullName = c.getString(c.getColumnIndex(
+                        AutoFillProfileDatabase.Profiles.FULL_NAME));
+                String email = c.getString(c.getColumnIndex(
+                        AutoFillProfileDatabase.Profiles.EMAIL_ADDRESS));
+                String company = c.getString(c.getColumnIndex(
+                        AutoFillProfileDatabase.Profiles.COMPANY_NAME));
+                String addressLine1 = c.getString(c.getColumnIndex(
+                        AutoFillProfileDatabase.Profiles.ADDRESS_LINE_1));
+                String addressLine2 = c.getString(c.getColumnIndex(
+                        AutoFillProfileDatabase.Profiles.ADDRESS_LINE_2));
+                String city = c.getString(c.getColumnIndex(
+                        AutoFillProfileDatabase.Profiles.CITY));
+                String state = c.getString(c.getColumnIndex(
+                        AutoFillProfileDatabase.Profiles.STATE));
+                String zip = c.getString(c.getColumnIndex(
+                        AutoFillProfileDatabase.Profiles.ZIP_CODE));
+                String country = c.getString(c.getColumnIndex(
+                        AutoFillProfileDatabase.Profiles.COUNTRY));
+                String phone = c.getString(c.getColumnIndex(
+                        AutoFillProfileDatabase.Profiles.PHONE_NUMBER));
+                mAutoFillProfile = new AutoFillProfile(mAutoFillActiveProfileId,
+                        fullName, email, company, addressLine1, addressLine2, city,
+                        state, zip, country, phone);
+            }
+            c.close();
+            autoFillDb.close();
+
+            synchronized (this) {
+                mLoadFromDbComplete = true;
+                notifyAll();
+            }
+            return null;
+        }
+    }
+
+    public void setAutoFillProfile(AutoFillProfile profile, Message msg) {
+        if (profile != null) {
+            setActiveAutoFillProfileId(profile.getUniqueId());
+            // Update the AutoFill DB with the new profile.
+            new SaveProfileToDbTask(msg).execute(profile);
+        } else {
+            // Delete the current profile.
+            if (mAutoFillProfile != null) {
+                new DeleteProfileFromDbTask(msg).execute(mAutoFillProfile.getUniqueId());
+                setActiveAutoFillProfileId(NO_AUTOFILL_PROFILE_SET);
+            }
+        }
+        mAutoFillProfile = profile;
+    }
+
+    public AutoFillProfile getAutoFillProfile() {
+        return mAutoFillProfile;
+    }
+
+    private void setActiveAutoFillProfileId(int activeProfileId) {
+        mAutoFillActiveProfileId = activeProfileId;
+        Editor ed = PreferenceManager.
+            getDefaultSharedPreferences(mContext).edit();
+        ed.putInt(PreferenceKeys.PREF_AUTOFILL_ACTIVE_PROFILE_ID, activeProfileId);
+        ed.apply();
+    }
+
+    private abstract class AutoFillProfileDbTask<T> extends AsyncTask<T, Void, Void> {
+        AutoFillProfileDatabase mAutoFillProfileDb;
+        Message mCompleteMessage;
+
+        public AutoFillProfileDbTask(Message msg) {
+            mCompleteMessage = msg;
+        }
+
+        @Override
+        protected void onPostExecute(Void result) {
+            if (mCompleteMessage != null) {
+                mCompleteMessage.sendToTarget();
+            }
+            mAutoFillProfileDb.close();
+        }
+
+        @Override
+        abstract protected Void doInBackground(T... values);
+    }
+
+
+    private class SaveProfileToDbTask extends AutoFillProfileDbTask<AutoFillProfile> {
+        public SaveProfileToDbTask(Message msg) {
+            super(msg);
+        }
+
+        @Override
+        protected Void doInBackground(AutoFillProfile... values) {
+            mAutoFillProfileDb = AutoFillProfileDatabase.getInstance(mContext);
+            assert mAutoFillActiveProfileId != NO_AUTOFILL_PROFILE_SET;
+            AutoFillProfile newProfile = values[0];
+            mAutoFillProfileDb.addOrUpdateProfile(mAutoFillActiveProfileId, newProfile);
+            return null;
+        }
+    }
+
+    private class DeleteProfileFromDbTask extends AutoFillProfileDbTask<Integer> {
+        public DeleteProfileFromDbTask(Message msg) {
+            super(msg);
+        }
+
+        @Override
+        protected Void doInBackground(Integer... values) {
+            mAutoFillProfileDb = AutoFillProfileDatabase.getInstance(mContext);
+            int id = values[0];
+            assert  id > 0;
+            mAutoFillProfileDb.dropProfile(id);
+            return null;
+        }
+    }
+}