1 2 /* 3 * Copyright (C) 2011 The Android Open Source Project 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 package com.android.browser; 19 20 import android.content.Context; 21 import android.content.SharedPreferences; 22 import android.content.SharedPreferences.Editor; 23 import android.database.Cursor; 24 import android.os.AsyncTask; 25 import android.os.Message; 26 import android.preference.PreferenceManager; 27 import android.webkit.WebSettings.AutoFillProfile; 28 29 import java.util.concurrent.CountDownLatch; 30 31 public class AutofillHandler { 32 33 private AutoFillProfile mAutoFillProfile; 34 // Default to zero. In the case no profile is set up, the initial 35 // value will come from the AutoFillSettingsFragment when the user 36 // creates a profile. Otherwise, we'll read the ID of the last used 37 // profile from the prefs db. 38 private int mAutoFillActiveProfileId; 39 private static final int NO_AUTOFILL_PROFILE_SET = 0; 40 41 private CountDownLatch mLoaded = new CountDownLatch(1); 42 private Context mContext; 43 44 public AutofillHandler(Context context) { 45 mContext = context.getApplicationContext(); 46 } 47 48 /** 49 * Load settings from the browser app's database. It is performed in 50 * an AsyncTask as it involves plenty of slow disk IO. 51 * NOTE: Strings used for the preferences must match those specified 52 * in the various preference XML files. 53 */ 54 public void asyncLoadFromDb() { 55 // Run the initial settings load in an AsyncTask as it hits the 56 // disk multiple times through SharedPreferences and SQLite. We 57 // need to be certain though that this has completed before we start 58 // to load pages though, so in the worst case we will block waiting 59 // for it to finish in BrowserActivity.onCreate(). 60 new LoadFromDb().start(); 61 } 62 63 public void waitForLoad() { 64 try { 65 mLoaded.await(); 66 } catch (InterruptedException e) {} 67 } 68 69 private class LoadFromDb extends Thread { 70 71 @Override 72 public void run() { 73 SharedPreferences p = 74 PreferenceManager.getDefaultSharedPreferences(mContext); 75 76 // Read the last active AutoFill profile id. 77 mAutoFillActiveProfileId = p.getInt( 78 PreferenceKeys.PREF_AUTOFILL_ACTIVE_PROFILE_ID, 79 mAutoFillActiveProfileId); 80 81 // Load the autofill profile data from the database. We use a database separate 82 // to the browser preference DB to make it easier to support multiple profiles 83 // and switching between them. 84 AutoFillProfileDatabase autoFillDb = AutoFillProfileDatabase.getInstance(mContext); 85 Cursor c = autoFillDb.getProfile(mAutoFillActiveProfileId); 86 87 if (c.getCount() > 0) { 88 c.moveToFirst(); 89 90 String fullName = c.getString(c.getColumnIndex( 91 AutoFillProfileDatabase.Profiles.FULL_NAME)); 92 String email = c.getString(c.getColumnIndex( 93 AutoFillProfileDatabase.Profiles.EMAIL_ADDRESS)); 94 String company = c.getString(c.getColumnIndex( 95 AutoFillProfileDatabase.Profiles.COMPANY_NAME)); 96 String addressLine1 = c.getString(c.getColumnIndex( 97 AutoFillProfileDatabase.Profiles.ADDRESS_LINE_1)); 98 String addressLine2 = c.getString(c.getColumnIndex( 99 AutoFillProfileDatabase.Profiles.ADDRESS_LINE_2)); 100 String city = c.getString(c.getColumnIndex( 101 AutoFillProfileDatabase.Profiles.CITY)); 102 String state = c.getString(c.getColumnIndex( 103 AutoFillProfileDatabase.Profiles.STATE)); 104 String zip = c.getString(c.getColumnIndex( 105 AutoFillProfileDatabase.Profiles.ZIP_CODE)); 106 String country = c.getString(c.getColumnIndex( 107 AutoFillProfileDatabase.Profiles.COUNTRY)); 108 String phone = c.getString(c.getColumnIndex( 109 AutoFillProfileDatabase.Profiles.PHONE_NUMBER)); 110 mAutoFillProfile = new AutoFillProfile(mAutoFillActiveProfileId, 111 fullName, email, company, addressLine1, addressLine2, city, 112 state, zip, country, phone); 113 } 114 c.close(); 115 autoFillDb.close(); 116 117 mLoaded.countDown(); 118 } 119 } 120 121 public void setAutoFillProfile(AutoFillProfile profile, Message msg) { 122 int profileId = NO_AUTOFILL_PROFILE_SET; 123 if (profile != null) { 124 profileId = profile.getUniqueId(); 125 // Update the AutoFill DB with the new profile. 126 new SaveProfileToDbTask(msg).execute(profile); 127 } else { 128 // Delete the current profile. 129 if (mAutoFillProfile != null) { 130 new DeleteProfileFromDbTask(msg).execute(mAutoFillProfile.getUniqueId()); 131 } 132 } 133 // Make sure we set mAutoFillProfile before calling setActiveAutoFillProfileId 134 // Calling setActiveAutoFillProfileId will trigger an update of WebViews 135 // which will expect a new profile to be set 136 mAutoFillProfile = profile; 137 setActiveAutoFillProfileId(profileId); 138 } 139 140 public AutoFillProfile getAutoFillProfile() { 141 return mAutoFillProfile; 142 } 143 144 private void setActiveAutoFillProfileId(int activeProfileId) { 145 mAutoFillActiveProfileId = activeProfileId; 146 Editor ed = PreferenceManager. 147 getDefaultSharedPreferences(mContext).edit(); 148 ed.putInt(PreferenceKeys.PREF_AUTOFILL_ACTIVE_PROFILE_ID, activeProfileId); 149 ed.apply(); 150 } 151 152 private abstract class AutoFillProfileDbTask<T> extends AsyncTask<T, Void, Void> { 153 AutoFillProfileDatabase mAutoFillProfileDb; 154 Message mCompleteMessage; 155 156 public AutoFillProfileDbTask(Message msg) { 157 mCompleteMessage = msg; 158 } 159 160 @Override 161 protected void onPostExecute(Void result) { 162 if (mCompleteMessage != null) { 163 mCompleteMessage.sendToTarget(); 164 } 165 mAutoFillProfileDb.close(); 166 } 167 168 @Override 169 abstract protected Void doInBackground(T... values); 170 } 171 172 173 private class SaveProfileToDbTask extends AutoFillProfileDbTask<AutoFillProfile> { 174 public SaveProfileToDbTask(Message msg) { 175 super(msg); 176 } 177 178 @Override 179 protected Void doInBackground(AutoFillProfile... values) { 180 mAutoFillProfileDb = AutoFillProfileDatabase.getInstance(mContext); 181 assert mAutoFillActiveProfileId != NO_AUTOFILL_PROFILE_SET; 182 AutoFillProfile newProfile = values[0]; 183 mAutoFillProfileDb.addOrUpdateProfile(mAutoFillActiveProfileId, newProfile); 184 return null; 185 } 186 } 187 188 private class DeleteProfileFromDbTask extends AutoFillProfileDbTask<Integer> { 189 public DeleteProfileFromDbTask(Message msg) { 190 super(msg); 191 } 192 193 @Override 194 protected Void doInBackground(Integer... values) { 195 mAutoFillProfileDb = AutoFillProfileDatabase.getInstance(mContext); 196 int id = values[0]; 197 assert id > 0; 198 mAutoFillProfileDb.dropProfile(id); 199 return null; 200 } 201 } 202 } 203