1 /* 2 * Copyright (C) 2006 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; 18 19 import android.app.Activity; 20 import android.app.AlertDialog; 21 import android.app.Dialog; 22 import android.app.admin.DevicePolicyManager; 23 import android.content.Context; 24 import android.content.Intent; 25 import android.net.ConnectivityManager; 26 import android.net.Proxy; 27 import android.net.ProxyInfo; 28 import android.os.Bundle; 29 import android.text.Selection; 30 import android.text.Spannable; 31 import android.text.TextUtils; 32 import android.util.Log; 33 import android.view.LayoutInflater; 34 import android.view.View; 35 import android.view.View.OnClickListener; 36 import android.view.View.OnFocusChangeListener; 37 import android.view.ViewGroup; 38 import android.widget.Button; 39 import android.widget.EditText; 40 import android.widget.TextView; 41 42 import com.android.internal.logging.MetricsProto.MetricsEvent; 43 import com.android.settings.SettingsPreferenceFragment.SettingsDialogFragment; 44 45 public class ProxySelector extends InstrumentedFragment implements DialogCreatable { 46 private static final String TAG = "ProxySelector"; 47 48 EditText mHostnameField; 49 EditText mPortField; 50 EditText mExclusionListField; 51 Button mOKButton; 52 Button mClearButton; 53 Button mDefaultButton; 54 55 private static final int ERROR_DIALOG_ID = 0; 56 57 private SettingsDialogFragment mDialogFragment; 58 private View mView; 59 60 @Override 61 public void onCreate(Bundle icicle) { 62 super.onCreate(icicle); 63 } 64 65 @Override 66 public View onCreateView(LayoutInflater inflater, ViewGroup container, 67 Bundle savedInstanceState) { 68 mView = inflater.inflate(R.layout.proxy, container, false); 69 initView(mView); 70 // TODO: Populate based on connection status 71 populateFields(); 72 return mView; 73 } 74 75 @Override 76 public void onActivityCreated(Bundle savedInstanceState) { 77 super.onActivityCreated(savedInstanceState); 78 final DevicePolicyManager dpm = 79 (DevicePolicyManager)getActivity().getSystemService(Context.DEVICE_POLICY_SERVICE); 80 81 final boolean userSetGlobalProxy = (dpm.getGlobalProxyAdmin() == null); 82 // Disable UI if the Global Proxy is being controlled by a Device Admin 83 mHostnameField.setEnabled(userSetGlobalProxy); 84 mPortField.setEnabled(userSetGlobalProxy); 85 mExclusionListField.setEnabled(userSetGlobalProxy); 86 mOKButton.setEnabled(userSetGlobalProxy); 87 mClearButton.setEnabled(userSetGlobalProxy); 88 mDefaultButton.setEnabled(userSetGlobalProxy); 89 } 90 91 // Dialog management 92 93 @Override 94 public Dialog onCreateDialog(int id) { 95 if (id == ERROR_DIALOG_ID) { 96 String hostname = mHostnameField.getText().toString().trim(); 97 String portStr = mPortField.getText().toString().trim(); 98 String exclList = mExclusionListField.getText().toString().trim(); 99 String msg = getActivity().getString(validate(hostname, portStr, exclList)); 100 101 return new AlertDialog.Builder(getActivity()) 102 .setTitle(R.string.proxy_error) 103 .setPositiveButton(R.string.proxy_error_dismiss, null) 104 .setMessage(msg) 105 .create(); 106 } 107 return null; 108 } 109 110 private void showDialog(int dialogId) { 111 if (mDialogFragment != null) { 112 Log.e(TAG, "Old dialog fragment not null!"); 113 } 114 mDialogFragment = new SettingsDialogFragment(this, dialogId); 115 mDialogFragment.show(getActivity().getFragmentManager(), Integer.toString(dialogId)); 116 } 117 118 private void initView(View view) { 119 mHostnameField = (EditText)view.findViewById(R.id.hostname); 120 mHostnameField.setOnFocusChangeListener(mOnFocusChangeHandler); 121 122 mPortField = (EditText)view.findViewById(R.id.port); 123 mPortField.setOnClickListener(mOKHandler); 124 mPortField.setOnFocusChangeListener(mOnFocusChangeHandler); 125 126 mExclusionListField = (EditText)view.findViewById(R.id.exclusionlist); 127 mExclusionListField.setOnFocusChangeListener(mOnFocusChangeHandler); 128 129 mOKButton = (Button)view.findViewById(R.id.action); 130 mOKButton.setOnClickListener(mOKHandler); 131 132 mClearButton = (Button)view.findViewById(R.id.clear); 133 mClearButton.setOnClickListener(mClearHandler); 134 135 mDefaultButton = (Button)view.findViewById(R.id.defaultView); 136 mDefaultButton.setOnClickListener(mDefaultHandler); 137 } 138 139 void populateFields() { 140 final Activity activity = getActivity(); 141 String hostname = ""; 142 int port = -1; 143 String exclList = ""; 144 // Use the last setting given by the user 145 ConnectivityManager cm = 146 (ConnectivityManager)getActivity().getSystemService(Context.CONNECTIVITY_SERVICE); 147 148 ProxyInfo proxy = cm.getGlobalProxy(); 149 if (proxy != null) { 150 hostname = proxy.getHost(); 151 port = proxy.getPort(); 152 exclList = proxy.getExclusionListAsString(); 153 } 154 155 if (hostname == null) { 156 hostname = ""; 157 } 158 159 mHostnameField.setText(hostname); 160 161 String portStr = port == -1 ? "" : Integer.toString(port); 162 mPortField.setText(portStr); 163 164 mExclusionListField.setText(exclList); 165 166 final Intent intent = activity.getIntent(); 167 168 String buttonLabel = intent.getStringExtra("button-label"); 169 if (!TextUtils.isEmpty(buttonLabel)) { 170 mOKButton.setText(buttonLabel); 171 } 172 173 String title = intent.getStringExtra("title"); 174 if (!TextUtils.isEmpty(title)) { 175 activity.setTitle(title); 176 } 177 } 178 179 /** 180 * validate syntax of hostname and port entries 181 * @return 0 on success, string resource ID on failure 182 */ 183 public static int validate(String hostname, String port, String exclList) { 184 switch (Proxy.validate(hostname, port, exclList)) { 185 case Proxy.PROXY_VALID: 186 return 0; 187 case Proxy.PROXY_HOSTNAME_EMPTY: 188 return R.string.proxy_error_empty_host_set_port; 189 case Proxy.PROXY_HOSTNAME_INVALID: 190 return R.string.proxy_error_invalid_host; 191 case Proxy.PROXY_PORT_EMPTY: 192 return R.string.proxy_error_empty_port; 193 case Proxy.PROXY_PORT_INVALID: 194 return R.string.proxy_error_invalid_port; 195 case Proxy.PROXY_EXCLLIST_INVALID: 196 return R.string.proxy_error_invalid_exclusion_list; 197 default: 198 // should neven happen 199 Log.e(TAG, "Unknown proxy settings error"); 200 return -1; 201 } 202 } 203 204 /** 205 * returns true on success, false if the user must correct something 206 */ 207 boolean saveToDb() { 208 209 String hostname = mHostnameField.getText().toString().trim(); 210 String portStr = mPortField.getText().toString().trim(); 211 String exclList = mExclusionListField.getText().toString().trim(); 212 int port = 0; 213 214 int result = validate(hostname, portStr, exclList); 215 if (result != 0) { 216 showDialog(ERROR_DIALOG_ID); 217 return false; 218 } 219 220 if (portStr.length() > 0) { 221 try { 222 port = Integer.parseInt(portStr); 223 } catch (NumberFormatException ex) { 224 // should never happen - caught by validate above 225 return false; 226 } 227 } 228 ProxyInfo p = new ProxyInfo(hostname, port, exclList); 229 // FIXME: The best solution would be to make a better UI that would 230 // disable editing of the text boxes if the user chooses to use the 231 // default settings. i.e. checking a box to always use the default 232 // carrier. http:/b/issue?id=756480 233 // FIXME: If the user types in a proxy that matches the default, should 234 // we keep that setting? Can be fixed with a new UI. 235 ConnectivityManager cm = 236 (ConnectivityManager)getActivity().getSystemService(Context.CONNECTIVITY_SERVICE); 237 238 cm.setGlobalProxy(p); 239 return true; 240 } 241 242 OnClickListener mOKHandler = new OnClickListener() { 243 public void onClick(View v) { 244 if (saveToDb()) { 245 getActivity().onBackPressed(); 246 } 247 } 248 }; 249 250 OnClickListener mClearHandler = new OnClickListener() { 251 public void onClick(View v) { 252 mHostnameField.setText(""); 253 mPortField.setText(""); 254 mExclusionListField.setText(""); 255 } 256 }; 257 258 OnClickListener mDefaultHandler = new OnClickListener() { 259 public void onClick(View v) { 260 // TODO: populate based on connection status 261 populateFields(); 262 } 263 }; 264 265 OnFocusChangeListener mOnFocusChangeHandler = new OnFocusChangeListener() { 266 public void onFocusChange(View v, boolean hasFocus) { 267 if (hasFocus) { 268 TextView textView = (TextView) v; 269 Selection.selectAll((Spannable) textView.getText()); 270 } 271 } 272 }; 273 274 @Override 275 protected int getMetricsCategory() { 276 return MetricsEvent.PROXY_SELECTOR; 277 } 278 } 279