Prompt the user for a password if none is configured in the VPN profile
[strongswan.git] / src / frontends / android / src / org / strongswan / android / ui / MainActivity.java
1 /*
2 * Copyright (C) 2012 Tobias Brunner
3 * Copyright (C) 2012 Giuliano Grassi
4 * Copyright (C) 2012 Ralf Sager
5 * Hochschule fuer Technik Rapperswil
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 * for more details.
16 */
17
18 package org.strongswan.android.ui;
19
20 import org.strongswan.android.R;
21 import org.strongswan.android.data.VpnProfile;
22 import org.strongswan.android.data.VpnProfileDataSource;
23 import org.strongswan.android.logic.CharonVpnService;
24 import org.strongswan.android.logic.TrustedCertificateManager;
25 import org.strongswan.android.ui.VpnProfileListFragment.OnVpnProfileSelectedListener;
26
27 import android.app.ActionBar;
28 import android.app.Activity;
29 import android.app.AlertDialog;
30 import android.app.AlertDialog.Builder;
31 import android.app.Dialog;
32 import android.app.DialogFragment;
33 import android.content.Context;
34 import android.content.DialogInterface;
35 import android.content.Intent;
36 import android.net.VpnService;
37 import android.os.AsyncTask;
38 import android.os.Bundle;
39 import android.view.LayoutInflater;
40 import android.view.Menu;
41 import android.view.MenuInflater;
42 import android.view.MenuItem;
43 import android.view.View;
44 import android.view.Window;
45 import android.widget.EditText;
46
47 public class MainActivity extends Activity implements OnVpnProfileSelectedListener
48 {
49 private static final int PREPARE_VPN_SERVICE = 0;
50 private VpnProfile activeProfile;
51
52 @Override
53 public void onCreate(Bundle savedInstanceState)
54 {
55 super.onCreate(savedInstanceState);
56 requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
57 setContentView(R.layout.main);
58
59 ActionBar bar = getActionBar();
60 bar.setDisplayShowTitleEnabled(false);
61
62 /* load CA certificates in a background task */
63 new CertificateLoadTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, false);
64 }
65
66 @Override
67 public boolean onCreateOptionsMenu(Menu menu)
68 {
69 MenuInflater inflater = getMenuInflater();
70 inflater.inflate(R.menu.main, menu);
71 return true;
72 }
73
74 @Override
75 public boolean onOptionsItemSelected(MenuItem item)
76 {
77 switch (item.getItemId())
78 {
79 case R.id.menu_reload_certs:
80 new CertificateLoadTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, true);
81 return true;
82 default:
83 return super.onOptionsItemSelected(item);
84 }
85 }
86
87 /**
88 * Prepare the VpnService. If this succeeds the current VPN profile is
89 * started.
90 */
91 protected void prepareVpnService()
92 {
93 Intent intent = VpnService.prepare(this);
94 if (intent != null)
95 {
96 startActivityForResult(intent, PREPARE_VPN_SERVICE);
97 }
98 else
99 {
100 onActivityResult(PREPARE_VPN_SERVICE, RESULT_OK, null);
101 }
102 }
103
104 @Override
105 protected void onActivityResult(int requestCode, int resultCode, Intent data)
106 {
107 switch (requestCode)
108 {
109 case PREPARE_VPN_SERVICE:
110 if (resultCode == RESULT_OK && activeProfile != null)
111 {
112 Intent intent = new Intent(this, CharonVpnService.class);
113 intent.putExtra(VpnProfileDataSource.KEY_ID, activeProfile.getId());
114 /* submit the password as the profile might not store one */
115 intent.putExtra(VpnProfileDataSource.KEY_PASSWORD, activeProfile.getPassword());
116 this.startService(intent);
117 }
118 break;
119 default:
120 super.onActivityResult(requestCode, resultCode, data);
121 }
122 }
123
124 @Override
125 public void onVpnProfileSelected(VpnProfile profile)
126 {
127 activeProfile = profile;
128 if (activeProfile.getPassword() == null)
129 {
130 new LoginDialog().show(getFragmentManager(), "LoginDialog");
131 }
132 else
133 {
134 prepareVpnService();
135 }
136 }
137
138 /**
139 * Class that loads or reloads the cached CA certificates.
140 */
141 private class CertificateLoadTask extends AsyncTask<Boolean, Void, TrustedCertificateManager>
142 {
143 @Override
144 protected void onPreExecute()
145 {
146 setProgressBarIndeterminateVisibility(true);
147 }
148 @Override
149 protected TrustedCertificateManager doInBackground(Boolean... params)
150 {
151 if (params.length > 0 && params[0])
152 { /* force a reload of the certificates */
153 return TrustedCertificateManager.getInstance().reload();
154 }
155 return TrustedCertificateManager.getInstance().load();
156 }
157 @Override
158 protected void onPostExecute(TrustedCertificateManager result)
159 {
160 setProgressBarIndeterminateVisibility(false);
161 }
162 }
163
164 private class LoginDialog extends DialogFragment
165 {
166 @Override
167 public Dialog onCreateDialog(Bundle savedInstanceState)
168 {
169 LayoutInflater inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
170 View view = inflater.inflate(R.layout.login_dialog, null);
171 EditText username = (EditText)view.findViewById(R.id.username);
172 username.setText(activeProfile.getUsername());
173 final EditText password = (EditText)view.findViewById(R.id.password);
174
175 Builder adb = new AlertDialog.Builder(MainActivity.this);
176 adb.setView(view);
177 adb.setTitle(getString(R.string.login_title));
178 adb.setPositiveButton(R.string.login_confirm, new DialogInterface.OnClickListener() {
179 @Override
180 public void onClick(DialogInterface dialog, int whichButton)
181 {
182 activeProfile.setPassword(password.getText().toString().trim());
183 prepareVpnService();
184 }
185 });
186 adb.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
187 @Override
188 public void onClick(DialogInterface dialog, int which)
189 {
190 dismiss();
191 }
192 });
193 return adb.create();
194 }
195 }
196 }