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