1 /* 2 * Copyright (C) 2009 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.settings.vpn; 18 19 import com.android.settings.R; 20 21 import android.content.Context; 22 import android.net.vpn.VpnProfile; 23 import android.preference.CheckBoxPreference; 24 import android.preference.EditTextPreference; 25 import android.preference.ListPreference; 26 import android.preference.Preference; 27 import android.preference.PreferenceGroup; 28 import android.text.InputType; 29 import android.text.TextUtils; 30 import android.text.method.PasswordTransformationMethod; 31 32 /** 33 * The common class for editing {@link VpnProfile}. 34 */ 35 class VpnProfileEditor { 36 private static final String KEY_VPN_NAME = "vpn_name"; 37 38 private EditTextPreference mName; 39 private EditTextPreference mServerName; 40 private EditTextPreference mDomainSuffices; 41 private VpnProfile mProfile; 42 VpnProfileEditor(VpnProfile p)43 public VpnProfileEditor(VpnProfile p) { 44 mProfile = p; 45 } 46 47 //@Override getProfile()48 public VpnProfile getProfile() { 49 return mProfile; 50 } 51 52 /** 53 * Adds the preferences to the panel. Subclasses should override 54 * {@link #loadExtraPreferencesTo(PreferenceGroup)} instead of this method. 55 */ loadPreferencesTo(PreferenceGroup subpanel)56 public void loadPreferencesTo(PreferenceGroup subpanel) { 57 Context c = subpanel.getContext(); 58 59 mName = (EditTextPreference) subpanel.findPreference(KEY_VPN_NAME); 60 mName.setOnPreferenceChangeListener( 61 new Preference.OnPreferenceChangeListener() { 62 public boolean onPreferenceChange( 63 Preference pref, Object newValue) { 64 setName((String) newValue); 65 return true; 66 } 67 }); 68 setName(getProfile().getName()); 69 mName.getEditText().setInputType(InputType.TYPE_CLASS_TEXT 70 | InputType.TYPE_TEXT_FLAG_CAP_SENTENCES); 71 72 subpanel.addPreference(createServerNamePreference(c)); 73 loadExtraPreferencesTo(subpanel); 74 subpanel.addPreference(createDomainSufficesPreference(c)); 75 } 76 77 /** 78 * Adds the extra preferences to the panel. Subclasses should add 79 * additional preferences in this method. 80 */ loadExtraPreferencesTo(PreferenceGroup subpanel)81 protected void loadExtraPreferencesTo(PreferenceGroup subpanel) { 82 } 83 84 /** 85 * Validates the inputs in the preferences. 86 * 87 * @return an error message that is ready to be displayed in a dialog; or 88 * null if all the inputs are valid 89 */ validate()90 public String validate() { 91 String result = validate(mName, R.string.vpn_a_name); 92 return ((result != null) 93 ? result 94 : validate(mServerName, R.string.vpn_a_vpn_server)); 95 } 96 97 /** 98 * Creates a preference for users to input domain suffices. 99 */ createDomainSufficesPreference(Context c)100 protected EditTextPreference createDomainSufficesPreference(Context c) { 101 EditTextPreference pref = mDomainSuffices = createEditTextPreference(c, 102 R.string.vpn_dns_search_list_title, 103 R.string.vpn_dns_search_list, 104 mProfile.getDomainSuffices(), 105 new Preference.OnPreferenceChangeListener() { 106 public boolean onPreferenceChange( 107 Preference pref, Object newValue) { 108 String v = ((String) newValue).trim(); 109 mProfile.setDomainSuffices(v); 110 setSummary(pref, R.string.vpn_dns_search_list, v, false); 111 return true; 112 } 113 }); 114 pref.getEditText().setInputType(InputType.TYPE_TEXT_VARIATION_URI); 115 return pref; 116 } 117 createServerNamePreference(Context c)118 private Preference createServerNamePreference(Context c) { 119 EditTextPreference pref = mServerName = createEditTextPreference(c, 120 R.string.vpn_vpn_server_title, 121 R.string.vpn_vpn_server, 122 mProfile.getServerName(), 123 new Preference.OnPreferenceChangeListener() { 124 public boolean onPreferenceChange( 125 Preference pref, Object newValue) { 126 String v = ((String) newValue).trim(); 127 mProfile.setServerName(v); 128 setSummary(pref, R.string.vpn_vpn_server, v); 129 return true; 130 } 131 }); 132 pref.getEditText().setInputType(InputType.TYPE_TEXT_VARIATION_URI); 133 return pref; 134 } 135 createEditTextPreference(Context c, int titleId, int prefNameId, String value, Preference.OnPreferenceChangeListener listener)136 protected EditTextPreference createEditTextPreference(Context c, int titleId, 137 int prefNameId, String value, 138 Preference.OnPreferenceChangeListener listener) { 139 EditTextPreference pref = new EditTextPreference(c); 140 pref.setTitle(titleId); 141 pref.setDialogTitle(titleId); 142 setSummary(pref, prefNameId, value); 143 pref.setText(value); 144 pref.setPersistent(true); 145 pref.setOnPreferenceChangeListener(listener); 146 return pref; 147 } 148 validate(Preference pref, int fieldNameId)149 protected String validate(Preference pref, int fieldNameId) { 150 Context c = pref.getContext(); 151 String value = (pref instanceof EditTextPreference) 152 ? ((EditTextPreference) pref).getText() 153 : ((ListPreference) pref).getValue(); 154 String formatString = (pref instanceof EditTextPreference) 155 ? c.getString(R.string.vpn_error_miss_entering) 156 : c.getString(R.string.vpn_error_miss_selecting); 157 return (TextUtils.isEmpty(value) 158 ? String.format(formatString, c.getString(fieldNameId)) 159 : null); 160 } 161 setSummary(Preference pref, int fieldNameId, String v)162 protected void setSummary(Preference pref, int fieldNameId, String v) { 163 setSummary(pref, fieldNameId, v, true); 164 } 165 setSummary(Preference pref, int fieldNameId, String v, boolean required)166 protected void setSummary(Preference pref, int fieldNameId, String v, 167 boolean required) { 168 Context c = pref.getContext(); 169 String formatString = required 170 ? c.getString(R.string.vpn_field_not_set) 171 : c.getString(R.string.vpn_field_not_set_optional); 172 pref.setSummary(TextUtils.isEmpty(v) 173 ? String.format(formatString, c.getString(fieldNameId)) 174 : v); 175 } 176 setCheckBoxTitle(CheckBoxPreference pref, int fieldNameId)177 protected void setCheckBoxTitle(CheckBoxPreference pref, int fieldNameId) { 178 Context c = pref.getContext(); 179 String formatString = c.getString(R.string.vpn_enable_field); 180 pref.setTitle(String.format(formatString, c.getString(fieldNameId))); 181 } 182 setName(String newName)183 private void setName(String newName) { 184 newName = (newName == null) ? "" : newName.trim(); 185 mName.setText(newName); 186 getProfile().setName(newName); 187 setSummary(mName, R.string.vpn_name, newName); 188 } 189 190 // Secret is tricky to handle because empty field may mean "not set" or 191 // "unchanged". This class hides that logic from callers. 192 protected static abstract class SecretHandler { 193 private EditTextPreference mPref; 194 private int mFieldNameId; 195 private boolean mHadSecret; 196 SecretHandler(Context c, int titleId, int fieldNameId)197 protected SecretHandler(Context c, int titleId, int fieldNameId) { 198 String value = getSecretFromProfile(); 199 mHadSecret = !TextUtils.isEmpty(value); 200 mFieldNameId = fieldNameId; 201 202 EditTextPreference pref = mPref = new EditTextPreference(c); 203 pref.setTitle(titleId); 204 pref.setDialogTitle(titleId); 205 pref.getEditText().setInputType( 206 InputType.TYPE_TEXT_VARIATION_PASSWORD); 207 pref.getEditText().setTransformationMethod( 208 new PasswordTransformationMethod()); 209 pref.setText(""); 210 pref.getEditText().setHint(mHadSecret 211 ? R.string.vpn_secret_unchanged 212 : R.string.vpn_secret_not_set); 213 setSecretSummary(value); 214 pref.setPersistent(true); 215 saveSecretToProfile(""); 216 pref.setOnPreferenceChangeListener( 217 new Preference.OnPreferenceChangeListener() { 218 public boolean onPreferenceChange( 219 Preference pref, Object newValue) { 220 saveSecretToProfile((String) newValue); 221 setSecretSummary((String) newValue); 222 return true; 223 } 224 }); 225 } 226 getPreference()227 protected EditTextPreference getPreference() { 228 return mPref; 229 } 230 validate()231 protected String validate() { 232 Context c = mPref.getContext(); 233 String value = mPref.getText(); 234 return ((TextUtils.isEmpty(value) && !mHadSecret) 235 ? String.format( 236 c.getString(R.string.vpn_error_miss_entering), 237 c.getString(mFieldNameId)) 238 : null); 239 } 240 setSecretSummary(String value)241 private void setSecretSummary(String value) { 242 EditTextPreference pref = mPref; 243 Context c = pref.getContext(); 244 String formatString = (TextUtils.isEmpty(value) && !mHadSecret) 245 ? c.getString(R.string.vpn_field_not_set) 246 : c.getString(R.string.vpn_field_is_set); 247 pref.setSummary( 248 String.format(formatString, c.getString(mFieldNameId))); 249 } 250 getSecretFromProfile()251 protected abstract String getSecretFromProfile(); saveSecretToProfile(String secret)252 protected abstract void saveSecretToProfile(String secret); 253 } 254 } 255