1 /* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.browser; 18 19 import android.app.Fragment; 20 import android.content.Context; 21 import android.os.Bundle; 22 import android.os.Handler; 23 import android.os.Message; 24 import android.text.Editable; 25 import android.text.TextWatcher; 26 import android.util.Log; 27 import android.view.View; 28 import android.view.ViewGroup; 29 import android.view.View.OnClickListener; 30 import android.view.LayoutInflater; 31 import android.view.Menu; 32 import android.view.MenuInflater; 33 import android.view.MenuItem; 34 import android.view.inputmethod.InputMethodManager; 35 import android.webkit.WebSettingsClassic.AutoFillProfile; 36 import android.widget.Button; 37 import android.widget.EditText; 38 import android.widget.Toast; 39 40 public class AutoFillSettingsFragment extends Fragment { 41 42 private static final String LOGTAG = "AutoFillSettingsFragment"; 43 44 private EditText mFullNameEdit; 45 private EditText mEmailEdit; 46 private EditText mCompanyEdit; 47 private EditText mAddressLine1Edit; 48 private EditText mAddressLine2Edit; 49 private EditText mCityEdit; 50 private EditText mStateEdit; 51 private EditText mZipEdit; 52 private EditText mCountryEdit; 53 private EditText mPhoneEdit; 54 55 private MenuItem mSaveMenuItem; 56 57 private boolean mInitialised; 58 59 // Used to display toast after DB interactions complete. 60 private Handler mHandler; 61 private BrowserSettings mSettings; 62 63 private final static int PROFILE_SAVED_MSG = 100; 64 private final static int PROFILE_DELETED_MSG = 101; 65 66 // For now we support just one profile so it's safe to hardcode the 67 // id to 1 here. In the future this unique identifier will be set 68 // dynamically. 69 private int mUniqueId = 1; 70 71 private class PhoneNumberValidator implements TextWatcher { 72 // Keep in sync with kPhoneNumberLength in chrome/browser/autofill/phone_number.cc 73 private static final int PHONE_NUMBER_LENGTH = 7; 74 private static final String PHONE_NUMBER_SEPARATORS_REGEX = "[\\s\\.\\(\\)-]"; 75 afterTextChanged(Editable s)76 public void afterTextChanged(Editable s) { 77 String phoneNumber = s.toString(); 78 int phoneNumberLength = phoneNumber.length(); 79 80 // Strip out any phone number separators. 81 phoneNumber = phoneNumber.replaceAll(PHONE_NUMBER_SEPARATORS_REGEX, ""); 82 83 int strippedPhoneNumberLength = phoneNumber.length(); 84 85 if (phoneNumberLength > 0 && strippedPhoneNumberLength < PHONE_NUMBER_LENGTH) { 86 mPhoneEdit.setError(getResources().getText( 87 R.string.autofill_profile_editor_phone_number_invalid)); 88 } else { 89 mPhoneEdit.setError(null); 90 } 91 92 updateSaveMenuItemState(); 93 } 94 beforeTextChanged(CharSequence s, int start, int count, int after)95 public void beforeTextChanged(CharSequence s, int start, int count, int after) { 96 } 97 onTextChanged(CharSequence s, int start, int before, int count)98 public void onTextChanged(CharSequence s, int start, int before, int count) { 99 } 100 } 101 102 private class FieldChangedListener implements TextWatcher { afterTextChanged(Editable s)103 public void afterTextChanged(Editable s) { 104 updateSaveMenuItemState(); 105 } 106 beforeTextChanged(CharSequence s, int start, int count, int after)107 public void beforeTextChanged(CharSequence s, int start, int count, int after) { 108 } 109 onTextChanged(CharSequence s, int start, int before, int count)110 public void onTextChanged(CharSequence s, int start, int before, int count) { 111 } 112 113 } 114 115 private TextWatcher mFieldChangedListener = new FieldChangedListener(); 116 AutoFillSettingsFragment()117 public AutoFillSettingsFragment() { 118 mHandler = new Handler() { 119 @Override 120 public void handleMessage(Message msg) { 121 Context c = getActivity(); 122 switch (msg.what) { 123 case PROFILE_SAVED_MSG: 124 if (c != null) { 125 Toast.makeText(c, R.string.autofill_profile_successful_save, 126 Toast.LENGTH_SHORT).show(); 127 closeEditor(); 128 } 129 break; 130 131 case PROFILE_DELETED_MSG: 132 if (c != null) { 133 Toast.makeText(c, R.string.autofill_profile_successful_delete, 134 Toast.LENGTH_SHORT).show(); 135 } 136 break; 137 } 138 } 139 }; 140 } 141 142 @Override onCreate(Bundle savedState)143 public void onCreate(Bundle savedState) { 144 super.onCreate(savedState); 145 setHasOptionsMenu(true); 146 mSettings = BrowserSettings.getInstance(); 147 } 148 149 @Override onCreateOptionsMenu(Menu menu, MenuInflater inflater)150 public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { 151 inflater.inflate(R.menu.autofill_profile_editor, menu); 152 mSaveMenuItem = menu.findItem(R.id.autofill_profile_editor_save_profile_menu_id); 153 updateSaveMenuItemState(); 154 } 155 156 @Override onOptionsItemSelected(MenuItem item)157 public boolean onOptionsItemSelected(MenuItem item) { 158 switch (item.getItemId()) { 159 case R.id.autofill_profile_editor_delete_profile_menu_id: 160 // Clear the UI. 161 mFullNameEdit.setText(""); 162 mEmailEdit.setText(""); 163 mCompanyEdit.setText(""); 164 mAddressLine1Edit.setText(""); 165 mAddressLine2Edit.setText(""); 166 mCityEdit.setText(""); 167 mStateEdit.setText(""); 168 mZipEdit.setText(""); 169 mCountryEdit.setText(""); 170 mPhoneEdit.setText(""); 171 172 // Update browser settings and native with a null profile. This will 173 // trigger the current profile to get deleted from the DB. 174 mSettings.setAutoFillProfile(null, 175 mHandler.obtainMessage(PROFILE_DELETED_MSG)); 176 updateSaveMenuItemState(); 177 return true; 178 179 case R.id.autofill_profile_editor_save_profile_menu_id: 180 AutoFillProfile newProfile = new AutoFillProfile( 181 mUniqueId, 182 mFullNameEdit.getText().toString(), 183 mEmailEdit.getText().toString(), 184 mCompanyEdit.getText().toString(), 185 mAddressLine1Edit.getText().toString(), 186 mAddressLine2Edit.getText().toString(), 187 mCityEdit.getText().toString(), 188 mStateEdit.getText().toString(), 189 mZipEdit.getText().toString(), 190 mCountryEdit.getText().toString(), 191 mPhoneEdit.getText().toString()); 192 193 mSettings.setAutoFillProfile(newProfile, 194 mHandler.obtainMessage(PROFILE_SAVED_MSG)); 195 return true; 196 197 default: 198 return false; 199 } 200 } 201 202 @Override onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)203 public View onCreateView(LayoutInflater inflater, ViewGroup container, 204 Bundle savedInstanceState) { 205 View v = inflater.inflate(R.layout.autofill_settings_fragment, container, false); 206 207 mFullNameEdit = (EditText)v.findViewById(R.id.autofill_profile_editor_name_edit); 208 mEmailEdit = (EditText)v.findViewById(R.id.autofill_profile_editor_email_address_edit); 209 mCompanyEdit = (EditText)v.findViewById(R.id.autofill_profile_editor_company_name_edit); 210 mAddressLine1Edit = (EditText)v.findViewById( 211 R.id.autofill_profile_editor_address_line_1_edit); 212 mAddressLine2Edit = (EditText)v.findViewById( 213 R.id.autofill_profile_editor_address_line_2_edit); 214 mCityEdit = (EditText)v.findViewById(R.id.autofill_profile_editor_city_edit); 215 mStateEdit = (EditText)v.findViewById(R.id.autofill_profile_editor_state_edit); 216 mZipEdit = (EditText)v.findViewById(R.id.autofill_profile_editor_zip_code_edit); 217 mCountryEdit = (EditText)v.findViewById(R.id.autofill_profile_editor_country_edit); 218 mPhoneEdit = (EditText)v.findViewById(R.id.autofill_profile_editor_phone_number_edit); 219 220 mFullNameEdit.addTextChangedListener(mFieldChangedListener); 221 mEmailEdit.addTextChangedListener(mFieldChangedListener); 222 mCompanyEdit.addTextChangedListener(mFieldChangedListener); 223 mAddressLine1Edit.addTextChangedListener(mFieldChangedListener); 224 mAddressLine2Edit.addTextChangedListener(mFieldChangedListener); 225 mCityEdit.addTextChangedListener(mFieldChangedListener); 226 mStateEdit.addTextChangedListener(mFieldChangedListener); 227 mZipEdit.addTextChangedListener(mFieldChangedListener); 228 mCountryEdit.addTextChangedListener(mFieldChangedListener); 229 mPhoneEdit.addTextChangedListener(new PhoneNumberValidator()); 230 231 // Populate the text boxes with any pre existing AutoFill data. 232 AutoFillProfile activeProfile = mSettings.getAutoFillProfile(); 233 if (activeProfile != null) { 234 mFullNameEdit.setText(activeProfile.getFullName()); 235 mEmailEdit.setText(activeProfile.getEmailAddress()); 236 mCompanyEdit.setText(activeProfile.getCompanyName()); 237 mAddressLine1Edit.setText(activeProfile.getAddressLine1()); 238 mAddressLine2Edit.setText(activeProfile.getAddressLine2()); 239 mCityEdit.setText(activeProfile.getCity()); 240 mStateEdit.setText(activeProfile.getState()); 241 mZipEdit.setText(activeProfile.getZipCode()); 242 mCountryEdit.setText(activeProfile.getCountry()); 243 mPhoneEdit.setText(activeProfile.getPhoneNumber()); 244 } 245 246 mInitialised = true; 247 248 updateSaveMenuItemState(); 249 250 return v; 251 } 252 updateSaveMenuItemState()253 private void updateSaveMenuItemState() { 254 if (mSaveMenuItem == null) { 255 return; 256 } 257 258 if (!mInitialised) { 259 mSaveMenuItem.setEnabled(false); 260 return; 261 } 262 263 boolean currentState = mSaveMenuItem.isEnabled(); 264 boolean newState = (mFullNameEdit.getText().toString().length() > 0 || 265 mEmailEdit.getText().toString().length() > 0 || 266 mCompanyEdit.getText().toString().length() > 0 || 267 mAddressLine1Edit.getText().toString().length() > 0 || 268 mAddressLine2Edit.getText().toString().length() > 0 || 269 mCityEdit.getText().toString().length() > 0 || 270 mStateEdit.getText().toString().length() > 0 || 271 mZipEdit.getText().toString().length() > 0 || 272 mCountryEdit.getText().toString().length() > 0) && 273 mPhoneEdit.getError() == null; 274 275 if (currentState != newState) { 276 mSaveMenuItem.setEnabled(newState); 277 } 278 } 279 closeEditor()280 private void closeEditor() { 281 // Hide the IME if the user wants to close while an EditText has focus 282 InputMethodManager imm = (InputMethodManager) getActivity().getSystemService( 283 Context.INPUT_METHOD_SERVICE); 284 imm.hideSoftInputFromWindow(getView().getWindowToken(), 0); 285 if (getFragmentManager().getBackStackEntryCount() > 0) { 286 getFragmentManager().popBackStack(); 287 } else { 288 getActivity().finish(); 289 } 290 } 291 } 292