9e8ae2ff256e79121c5373a7be776c744056cbb9
[strongswan.git] / src / frontends / android / src / org / strongswan / android / ui / VpnProfileDetailActivity.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.TrustedCertificateManager;
24
25 import android.app.Activity;
26 import android.app.AlertDialog;
27 import android.content.DialogInterface;
28 import android.content.Intent;
29 import android.os.AsyncTask;
30 import android.os.Bundle;
31 import android.util.Log;
32 import android.view.Menu;
33 import android.view.MenuInflater;
34 import android.view.MenuItem;
35 import android.view.View;
36 import android.view.Window;
37 import android.widget.CheckBox;
38 import android.widget.CompoundButton;
39 import android.widget.CompoundButton.OnCheckedChangeListener;
40 import android.widget.EditText;
41
42 public class VpnProfileDetailActivity extends Activity
43 {
44 private VpnProfileDataSource mDataSource;
45 private Long mId;
46 private VpnProfile mProfile;
47 private boolean mCertsLoaded;
48 private String mCertAlias;
49 private EditText mName;
50 private EditText mGateway;
51 private EditText mUsername;
52 private EditText mPassword;
53 private CheckBox mCheckAuto;
54
55 @Override
56 public void onCreate(Bundle savedInstanceState)
57 {
58 super.onCreate(savedInstanceState);
59 requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
60
61 /* the title is set when we load the profile, if any */
62 getActionBar().setDisplayHomeAsUpEnabled(true);
63
64 mDataSource = new VpnProfileDataSource(this);
65 mDataSource.open();
66
67 setContentView(R.layout.profile_detail_view);
68
69 mName = (EditText)findViewById(R.id.name);
70 mPassword = (EditText)findViewById(R.id.password);
71 mGateway = (EditText)findViewById(R.id.gateway);
72 mUsername = (EditText)findViewById(R.id.username);
73
74 mCheckAuto = (CheckBox)findViewById(R.id.ca_auto);
75
76 mCheckAuto.setOnCheckedChangeListener(new OnCheckedChangeListener() {
77 @Override
78 public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)
79 {
80
81 }
82 });
83
84 mId = savedInstanceState == null ? null : savedInstanceState.getLong(VpnProfileDataSource.KEY_ID);
85 if (mId == null)
86 {
87 Bundle extras = getIntent().getExtras();
88 mId = extras == null ? null : extras.getLong(VpnProfileDataSource.KEY_ID);
89 }
90
91 loadProfileData();
92
93 new CertificateLoadTask().execute();
94 }
95
96 @Override
97 protected void onDestroy()
98 {
99 super.onDestroy();
100 mDataSource.close();
101 }
102
103 @Override
104 protected void onSaveInstanceState(Bundle outState)
105 {
106 super.onSaveInstanceState(outState);
107 if (mId != null)
108 {
109 outState.putLong(VpnProfileDataSource.KEY_ID, mId);
110 }
111 }
112
113 @Override
114 public boolean onCreateOptionsMenu(Menu menu)
115 {
116 MenuInflater inflater = getMenuInflater();
117 inflater.inflate(R.menu.profile_edit, menu);
118 return true;
119 }
120
121 @Override
122 public boolean onOptionsItemSelected(MenuItem item)
123 {
124 switch (item.getItemId())
125 {
126 case android.R.id.home:
127 case R.id.menu_cancel:
128 finish();
129 return true;
130 case R.id.menu_accept:
131 saveProfile();
132 return true;
133 default:
134 return super.onOptionsItemSelected(item);
135 }
136 }
137
138 /**
139 * Show an alert in case the previously selected certificate is not found anymore
140 * or the user did not select a certificate in the spinner.
141 */
142 private void showCertificateAlert()
143 {
144 AlertDialog.Builder adb = new AlertDialog.Builder(VpnProfileDetailActivity.this);
145 adb.setTitle(R.string.alert_text_nocertfound_title);
146 adb.setMessage(R.string.alert_text_nocertfound);
147 adb.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
148 @Override
149 public void onClick(DialogInterface dialog, int id)
150 {
151 dialog.cancel();
152 }
153 });
154 adb.show();
155 }
156
157 /**
158 * Asynchronously executed task which confirms that the certificates are loaded.
159 * They are loaded from the main Activity already but might not be ready yet, or
160 * unloaded again.
161 *
162 * Once loaded the CA certificate spinner and checkboxes are updated
163 * accordingly.
164 */
165 private class CertificateLoadTask extends AsyncTask<Void, Void, TrustedCertificateManager>
166 {
167 @Override
168 protected void onPreExecute()
169 {
170 setProgressBarIndeterminateVisibility(true);
171 }
172
173 @Override
174 protected TrustedCertificateManager doInBackground(Void... params)
175 {
176 return TrustedCertificateManager.getInstance().load();
177 }
178
179 @Override
180 protected void onPostExecute(TrustedCertificateManager result)
181 {
182 setProgressBarIndeterminateVisibility(false);
183 mCertsLoaded = true;
184 }
185 }
186
187 /**
188 * Save or update the profile depending on whether we actually have a
189 * profile object or not (this was created in updateProfileData)
190 */
191 private void saveProfile()
192 {
193 if (verifyInput())
194 {
195 if (mProfile != null)
196 {
197 updateProfileData();
198 mDataSource.updateVpnProfile(mProfile);
199 }
200 else
201 {
202 mProfile = new VpnProfile();
203 updateProfileData();
204 mDataSource.insertProfile(mProfile);
205 }
206 setResult(RESULT_OK, new Intent().putExtra(VpnProfileDataSource.KEY_ID, mProfile.getId()));
207 finish();
208 }
209 }
210
211 /**
212 * Verify the user input and display error messages.
213 * @return true if the input is valid
214 */
215 private boolean verifyInput()
216 {
217 boolean valid = true;
218 if (mGateway.getText().toString().trim().isEmpty())
219 {
220 mGateway.setError(getString(R.string.alert_text_no_input_gateway));
221 valid = false;
222 }
223 if (mUsername.getText().toString().trim().isEmpty())
224 {
225 mUsername.setError(getString(R.string.alert_text_no_input_username));
226 valid = false;
227 }
228 if (!mCheckAuto.isChecked())
229 {
230 showCertificateAlert();
231 valid = false;
232 }
233 return valid;
234 }
235
236 /**
237 * Update the profile object with the data entered by the user
238 */
239 private void updateProfileData()
240 {
241 /* the name is optional, we default to the gateway if none is given */
242 String name = mName.getText().toString().trim();
243 String gateway = mGateway.getText().toString().trim();
244 mProfile.setName(name.isEmpty() ? gateway : name);
245 mProfile.setGateway(gateway);
246 mProfile.setUsername(mUsername.getText().toString().trim());
247 String password = mPassword.getText().toString().trim();
248 password = password.isEmpty() ? null : password;
249 mProfile.setPassword(password);
250 }
251
252 /**
253 * Load an existing profile if we got an ID
254 */
255 private void loadProfileData()
256 {
257 getActionBar().setTitle(R.string.add_profile);
258 if (mId != null)
259 {
260 mProfile = mDataSource.getVpnProfile(mId);
261 if (mProfile != null)
262 {
263 mName.setText(mProfile.getName());
264 mGateway.setText(mProfile.getGateway());
265 mUsername.setText(mProfile.getUsername());
266 mPassword.setText(mProfile.getPassword());
267 mCertAlias = mProfile.getCertificateAlias();
268 getActionBar().setTitle(mProfile.getName());
269 }
270 else
271 {
272 Log.e(VpnProfileDetailActivity.class.getSimpleName(),
273 "VPN profile with id " + mId + " not found");
274 finish();
275 }
276 }
277 mCheckAuto.setChecked(mCertAlias == null);
278 }
279 }