Home | History | Annotate | Download | only in vpn2
      1 /*
      2  * Copyright (C) 2015 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.vpn2;
     18 
     19 import android.app.AlertDialog;
     20 import android.app.Dialog;
     21 import android.app.DialogFragment;
     22 import android.content.Context;
     23 import android.content.DialogInterface;
     24 import android.content.res.Resources;
     25 import android.net.ConnectivityManager;
     26 import android.os.Bundle;
     27 import android.security.Credentials;
     28 import android.security.KeyStore;
     29 import android.text.TextUtils;
     30 import android.view.LayoutInflater;
     31 import android.view.View;
     32 import android.widget.ArrayAdapter;
     33 import android.widget.ListView;
     34 import android.widget.Toast;
     35 
     36 import com.android.internal.net.VpnProfile;
     37 import com.android.settings.R;
     38 import com.google.android.collect.Lists;
     39 
     40 import java.util.ArrayList;
     41 import java.util.List;
     42 
     43 /**
     44  * Dialog to configure always-on VPN.
     45  */
     46 public class LockdownConfigFragment extends DialogFragment {
     47     private List<VpnProfile> mProfiles;
     48     private List<CharSequence> mTitles;
     49     private int mCurrentIndex;
     50 
     51     private static final String TAG_LOCKDOWN = "lockdown";
     52 
     53     private static class TitleAdapter extends ArrayAdapter<CharSequence> {
     54         public TitleAdapter(Context context, List<CharSequence> objects) {
     55             super(context, com.android.internal.R.layout.select_dialog_singlechoice_material,
     56                     android.R.id.text1, objects);
     57         }
     58     }
     59 
     60     public static void show(VpnSettings parent) {
     61         if (!parent.isAdded()) return;
     62 
     63         final LockdownConfigFragment dialog = new LockdownConfigFragment();
     64         dialog.show(parent.getFragmentManager(), TAG_LOCKDOWN);
     65     }
     66 
     67     private static String getStringOrNull(KeyStore keyStore, String key) {
     68         if (!keyStore.isUnlocked()) {
     69             return null;
     70         }
     71         final byte[] value = keyStore.get(key);
     72         return value == null ? null : new String(value);
     73     }
     74 
     75     private void initProfiles(KeyStore keyStore, Resources res) {
     76         final String lockdownKey = getStringOrNull(keyStore, Credentials.LOCKDOWN_VPN);
     77 
     78         mProfiles = VpnSettings.loadVpnProfiles(keyStore, VpnProfile.TYPE_PPTP);
     79         mTitles = new ArrayList<>(1 + mProfiles.size());
     80         mTitles.add(res.getText(R.string.vpn_lockdown_none));
     81 
     82         mCurrentIndex = 0;
     83         for (VpnProfile profile : mProfiles) {
     84             if (TextUtils.equals(profile.key, lockdownKey)) {
     85                 mCurrentIndex = mTitles.size();
     86             }
     87             mTitles.add(profile.name);
     88         }
     89     }
     90 
     91     @Override
     92     public Dialog onCreateDialog(Bundle savedInstanceState) {
     93         final Context context = getActivity();
     94         final KeyStore keyStore = KeyStore.getInstance();
     95 
     96         initProfiles(keyStore, context.getResources());
     97 
     98         final AlertDialog.Builder builder = new AlertDialog.Builder(context);
     99         final LayoutInflater dialogInflater = LayoutInflater.from(builder.getContext());
    100 
    101         builder.setTitle(R.string.vpn_menu_lockdown);
    102 
    103         final View view = dialogInflater.inflate(R.layout.vpn_lockdown_editor, null, false);
    104         final ListView listView = (ListView) view.findViewById(android.R.id.list);
    105         listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
    106         listView.setAdapter(new TitleAdapter(context, mTitles));
    107         listView.setItemChecked(mCurrentIndex, true);
    108         builder.setView(view);
    109 
    110         builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
    111             @Override
    112             public void onClick(DialogInterface dialog, int which) {
    113                 final int newIndex = listView.getCheckedItemPosition();
    114                 if (mCurrentIndex == newIndex) return;
    115 
    116                 if (newIndex == 0) {
    117                     keyStore.delete(Credentials.LOCKDOWN_VPN);
    118                 } else {
    119                     final VpnProfile profile = mProfiles.get(newIndex - 1);
    120                     if (!profile.isValidLockdownProfile()) {
    121                         Toast.makeText(context, R.string.vpn_lockdown_config_error,
    122                                 Toast.LENGTH_LONG).show();
    123                         return;
    124                     }
    125                     keyStore.put(Credentials.LOCKDOWN_VPN, profile.key.getBytes(),
    126                             KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED);
    127                 }
    128 
    129                 // kick profiles since we changed them
    130                 ConnectivityManager.from(getActivity()).updateLockdownVpn();
    131             }
    132         });
    133 
    134         return builder.create();
    135     }
    136 }
    137 
    138