• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.app.Dialog;
22 import android.content.ComponentName;
23 import android.content.Context;
24 import android.content.ServiceConnection;
25 import android.net.vpn.IVpnService;
26 import android.net.vpn.VpnManager;
27 import android.net.vpn.VpnProfile;
28 import android.net.vpn.VpnState;
29 import android.os.ConditionVariable;
30 import android.os.IBinder;
31 import android.os.RemoteException;
32 import android.text.TextUtils;
33 import android.util.Log;
34 import android.view.View;
35 import android.widget.CheckBox;
36 import android.widget.TextView;
37 
38 import java.io.IOException;
39 
40 /**
41  * A {@link VpnProfileActor} that provides an authentication view for users to
42  * input username and password before connecting to the VPN server.
43  */
44 public class AuthenticationActor implements VpnProfileActor {
45     private static final String TAG = AuthenticationActor.class.getName();
46 
47     private Context mContext;
48     private VpnProfile mProfile;
49     private VpnManager mVpnManager;
50 
AuthenticationActor(Context context, VpnProfile p)51     public AuthenticationActor(Context context, VpnProfile p) {
52         mContext = context;
53         mProfile = p;
54         mVpnManager = new VpnManager(context);
55     }
56 
57     //@Override
getProfile()58     public VpnProfile getProfile() {
59         return mProfile;
60     }
61 
62     //@Override
isConnectDialogNeeded()63     public boolean isConnectDialogNeeded() {
64         return true;
65     }
66 
67     //@Override
validateInputs(Dialog d)68     public String validateInputs(Dialog d) {
69         TextView usernameView = (TextView) d.findViewById(R.id.username_value);
70         TextView passwordView = (TextView) d.findViewById(R.id.password_value);
71         Context c = mContext;
72         if (TextUtils.isEmpty(usernameView.getText().toString())) {
73             return c.getString(R.string.vpn_a_username);
74         } else if (TextUtils.isEmpty(passwordView.getText().toString())) {
75             return c.getString(R.string.vpn_a_password);
76         } else {
77             return null;
78         }
79     }
80 
81     //@Override
connect(Dialog d)82     public void connect(Dialog d) {
83         TextView usernameView = (TextView) d.findViewById(R.id.username_value);
84         TextView passwordView = (TextView) d.findViewById(R.id.password_value);
85         CheckBox saveUsername = (CheckBox) d.findViewById(R.id.save_username);
86 
87         try {
88             setSavedUsername(saveUsername.isChecked()
89                     ? usernameView.getText().toString()
90                     : "");
91         } catch (IOException e) {
92             Log.e(TAG, "setSavedUsername()", e);
93         }
94 
95         connect(usernameView.getText().toString(),
96                 passwordView.getText().toString());
97         passwordView.setText("");
98     }
99 
100     //@Override
createConnectView()101     public View createConnectView() {
102         View v = View.inflate(mContext, R.layout.vpn_connect_dialog_view, null);
103         TextView usernameView = (TextView) v.findViewById(R.id.username_value);
104         TextView passwordView = (TextView) v.findViewById(R.id.password_value);
105         CheckBox saveUsername = (CheckBox) v.findViewById(R.id.save_username);
106 
107         String username = mProfile.getSavedUsername();
108         if (!TextUtils.isEmpty(username)) {
109             usernameView.setText(username);
110             saveUsername.setChecked(true);
111             passwordView.requestFocus();
112         }
113         return v;
114     }
115 
getContext()116     protected Context getContext() {
117         return mContext;
118     }
119 
connect(final String username, final String password)120     private void connect(final String username, final String password) {
121         mVpnManager.startVpnService();
122         ServiceConnection c = new ServiceConnection() {
123             public void onServiceConnected(ComponentName className,
124                     IBinder service) {
125                 try {
126                     boolean success = IVpnService.Stub.asInterface(service)
127                             .connect(mProfile, username, password);
128                     if (!success) {
129                         Log.d(TAG, "~~~~~~ connect() failed!");
130                     } else {
131                         Log.d(TAG, "~~~~~~ connect() succeeded!");
132                     }
133                 } catch (Throwable e) {
134                     Log.e(TAG, "connect()", e);
135                     broadcastConnectivity(VpnState.IDLE,
136                             VpnManager.VPN_ERROR_CONNECTION_FAILED);
137                 } finally {
138                     mContext.unbindService(this);
139                 }
140             }
141 
142             public void onServiceDisconnected(ComponentName className) {
143                 checkStatus();
144             }
145         };
146         if (!bindService(c)) {
147             broadcastConnectivity(VpnState.IDLE,
148                     VpnManager.VPN_ERROR_CONNECTION_FAILED);
149         }
150     }
151 
152     //@Override
disconnect()153     public void disconnect() {
154         ServiceConnection c = new ServiceConnection() {
155             public void onServiceConnected(ComponentName className,
156                     IBinder service) {
157                 try {
158                     IVpnService.Stub.asInterface(service).disconnect();
159                 } catch (RemoteException e) {
160                     Log.e(TAG, "disconnect()", e);
161                     checkStatus();
162                 } finally {
163                     mContext.unbindService(this);
164                 }
165             }
166 
167             public void onServiceDisconnected(ComponentName className) {
168                 checkStatus();
169             }
170         };
171         if (!bindService(c)) {
172             checkStatus();
173         }
174     }
175 
176     //@Override
checkStatus()177     public void checkStatus() {
178         final ConditionVariable cv = new ConditionVariable();
179         cv.close();
180         ServiceConnection c = new ServiceConnection() {
181             public synchronized void onServiceConnected(ComponentName className,
182                     IBinder service) {
183                 cv.open();
184                 try {
185                     IVpnService.Stub.asInterface(service).checkStatus(mProfile);
186                 } catch (RemoteException e) {
187                     Log.e(TAG, "checkStatus()", e);
188                     broadcastConnectivity(VpnState.IDLE);
189                 } finally {
190                     mContext.unbindService(this);
191                 }
192             }
193 
194             public void onServiceDisconnected(ComponentName className) {
195                 cv.open();
196                 broadcastConnectivity(VpnState.IDLE);
197                 mContext.unbindService(this);
198             }
199         };
200         if (bindService(c)) {
201             // wait for a second, let status propagate
202             if (!cv.block(1000)) broadcastConnectivity(VpnState.IDLE);
203         }
204     }
205 
bindService(ServiceConnection c)206     private boolean bindService(ServiceConnection c) {
207         return mVpnManager.bindVpnService(c);
208     }
209 
broadcastConnectivity(VpnState s)210     private void broadcastConnectivity(VpnState s) {
211         mVpnManager.broadcastConnectivity(mProfile.getName(), s);
212     }
213 
broadcastConnectivity(VpnState s, int errorCode)214     private void broadcastConnectivity(VpnState s, int errorCode) {
215         mVpnManager.broadcastConnectivity(mProfile.getName(), s, errorCode);
216     }
217 
setSavedUsername(String name)218     private void setSavedUsername(String name) throws IOException {
219         if (!name.equals(mProfile.getSavedUsername())) {
220             mProfile.setSavedUsername(name);
221             VpnSettings.saveProfileToStorage(mProfile);
222         }
223     }
224 }
225