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 android.app.Activity;
     20 import android.app.AlertDialog;
     21 import android.content.ContentResolver;
     22 import android.content.Intent;
     23 import android.net.Proxy;
     24 import android.os.Bundle;
     25 import android.provider.Settings;
     26 import android.text.Selection;
     27 import android.text.Spannable;
     28 import android.text.TextUtils;
     29 import android.util.Log;
     30 import android.view.View;
     31 import android.view.View.OnClickListener;
     32 import android.view.View.OnFocusChangeListener;
     33 import android.widget.Button;
     34 import android.widget.EditText;
     35 import android.widget.TextView;
     36 
     37 import java.util.regex.Matcher;
     38 import java.util.regex.Pattern;
     39 
     40 /**
     41  * To start the Proxy Selector activity, create the following intent.
     42  *
     43  * <code>
     44  *      Intent intent = new Intent();
     45  *      intent.setClassName("com.android.browser.ProxySelector");
     46  *      startActivity(intent);
     47  * </code>
     48  *
     49  * you can add extra options to the intent by using
     50  *
     51  * <code>
     52  *   intent.putExtra(key, value);
     53  * </code>
     54  *
     55  * the extra options are:
     56  *
     57  * button-label: a string label to display for the okay button
     58  * title:        the title of the window
     59  * error-text:   If not null, will be used as the label of the error message.
     60  */
     61 public class ProxySelector extends Activity
     62 {
     63     private final static String LOGTAG = "Settings";
     64 
     65     EditText    mHostnameField;
     66     EditText    mPortField;
     67     Button      mOKButton;
     68 
     69     // Matches blank input, ips, and domain names
     70     private static final String HOSTNAME_REGEXP = "^$|^[a-zA-Z0-9]+(\\-[a-zA-Z0-9]+)*(\\.[a-zA-Z0-9]+(\\-[a-zA-Z0-9]+)*)*$";
     71     private static final Pattern HOSTNAME_PATTERN;
     72     static {
     73         HOSTNAME_PATTERN = Pattern.compile(HOSTNAME_REGEXP);
     74     }
     75 
     76 
     77     public void onCreate(Bundle icicle) {
     78         super.onCreate(icicle);
     79 
     80         if (android.util.Config.LOGV) Log.v(LOGTAG, "[ProxySelector] onStart");
     81 
     82         setContentView(R.layout.proxy);
     83         initView();
     84         populateFields(false);
     85     }
     86 
     87     protected void showError(int error) {
     88 
     89         new AlertDialog.Builder(this)
     90                 .setTitle(R.string.proxy_error)
     91                 .setMessage(error)
     92                 .setPositiveButton(R.string.proxy_error_dismiss, null)
     93                 .show();
     94     }
     95 
     96     void initView() {
     97 
     98         mHostnameField = (EditText)findViewById(R.id.hostname);
     99         mHostnameField.setOnFocusChangeListener(mOnFocusChangeHandler);
    100 
    101         mPortField = (EditText)findViewById(R.id.port);
    102         mPortField.setOnClickListener(mOKHandler);
    103         mPortField.setOnFocusChangeListener(mOnFocusChangeHandler);
    104 
    105         mOKButton = (Button)findViewById(R.id.action);
    106         mOKButton.setOnClickListener(mOKHandler);
    107 
    108         Button b = (Button)findViewById(R.id.clear);
    109         b.setOnClickListener(mClearHandler);
    110 
    111         b = (Button)findViewById(R.id.defaultView);
    112         b.setOnClickListener(mDefaultHandler);
    113     }
    114 
    115     void populateFields(boolean useDefault) {
    116         String hostname = null;
    117         int port = -1;
    118         if (useDefault) {
    119             // Use the default proxy settings provided by the carrier
    120             hostname = Proxy.getDefaultHost();
    121             port = Proxy.getDefaultPort();
    122         } else {
    123             // Use the last setting given by the user
    124             hostname = Proxy.getHost(this);
    125             port = Proxy.getPort(this);
    126         }
    127 
    128         if (hostname == null) {
    129             hostname = "";
    130         }
    131 
    132         mHostnameField.setText(hostname);
    133 
    134         String portStr = port == -1 ? "" : Integer.toString(port);
    135         mPortField.setText(portStr);
    136 
    137         Intent intent = getIntent();
    138 
    139         String buttonLabel = intent.getStringExtra("button-label");
    140         if (!TextUtils.isEmpty(buttonLabel)) {
    141             mOKButton.setText(buttonLabel);
    142         }
    143 
    144         String title = intent.getStringExtra("title");
    145         if (!TextUtils.isEmpty(title)) {
    146             setTitle(title);
    147         }
    148     }
    149 
    150     /**
    151      * validate syntax of hostname and port entries
    152      * @return 0 on success, string resource ID on failure
    153      */
    154     int validate(String hostname, String port) {
    155         Matcher match = HOSTNAME_PATTERN.matcher(hostname);
    156 
    157         if (!match.matches()) return R.string.proxy_error_invalid_host;
    158 
    159         if (hostname.length() > 0 && port.length() == 0) {
    160             return R.string.proxy_error_empty_port;
    161         }
    162 
    163         if (port.length() > 0) {
    164             if (hostname.length() == 0) {
    165                 return R.string.proxy_error_empty_host_set_port;
    166             }
    167             int portVal = -1;
    168             try {
    169                 portVal = Integer.parseInt(port);
    170             } catch (NumberFormatException ex) {
    171                 return R.string.proxy_error_invalid_port;
    172             }
    173             if (portVal <= 0 || portVal > 0xFFFF) {
    174                 return R.string.proxy_error_invalid_port;
    175             }
    176         }
    177         return 0;
    178     }
    179 
    180     /**
    181      * returns true on success, false if the user must correct something
    182      */
    183     boolean saveToDb() {
    184 
    185         String hostname = mHostnameField.getText().toString().trim();
    186         String portStr = mPortField.getText().toString().trim();
    187         int port = -1;
    188 
    189         int result = validate(hostname, portStr);
    190         if (result > 0) {
    191             showError(result);
    192             return false;
    193         }
    194 
    195         if (portStr.length() > 0) {
    196             try {
    197                 port = Integer.parseInt(portStr);
    198             } catch (NumberFormatException ex) {
    199                 return false;
    200             }
    201         }
    202 
    203         // FIXME: The best solution would be to make a better UI that would
    204         // disable editing of the text boxes if the user chooses to use the
    205         // default settings. i.e. checking a box to always use the default
    206         // carrier. http:/b/issue?id=756480
    207         // FIXME: This currently will not work if the default host is blank and
    208         // the user has cleared the input boxes in order to not use a proxy.
    209         // This is a UI problem and can be solved with some better form
    210         // controls.
    211         // FIXME: If the user types in a proxy that matches the default, should
    212         // we keep that setting? Can be fixed with a new UI.
    213         ContentResolver res = getContentResolver();
    214         if (hostname.equals(Proxy.getDefaultHost())
    215                 && port == Proxy.getDefaultPort()) {
    216             // If the user hit the default button and didn't change any of
    217             // the input boxes, treat it as if the user has not specified a
    218             // proxy.
    219             hostname = null;
    220         }
    221 
    222         if (!TextUtils.isEmpty(hostname)) {
    223             hostname += ':' + portStr;
    224         }
    225         Settings.Secure.putString(res, Settings.Secure.HTTP_PROXY, hostname);
    226         sendBroadcast(new Intent(Proxy.PROXY_CHANGE_ACTION));
    227 
    228         return true;
    229     }
    230 
    231     OnClickListener mOKHandler = new OnClickListener() {
    232             public void onClick(View v) {
    233                 if (saveToDb()) {
    234                     finish();
    235                 }
    236             }
    237         };
    238 
    239     OnClickListener mClearHandler = new OnClickListener() {
    240             public void onClick(View v) {
    241                 mHostnameField.setText("");
    242                 mPortField.setText("");
    243             }
    244         };
    245 
    246     OnClickListener mDefaultHandler = new OnClickListener() {
    247             public void onClick(View v) {
    248                 populateFields(true);
    249             }
    250         };
    251 
    252     OnFocusChangeListener mOnFocusChangeHandler = new OnFocusChangeListener() {
    253             public void onFocusChange(View v, boolean hasFocus) {
    254                 if (hasFocus) {
    255                     TextView textView = (TextView) v;
    256                     Selection.selectAll((Spannable) textView.getText());
    257                 }
    258             }
    259         };
    260 }
    261