Added new UI to select a specific CA certificate
With this change there is no need to wait for all certificates being loaded anymore (this happens only when the user opens the selection activity).
This commit is contained in:
@@ -91,6 +91,33 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="@string/profile_ca_auto_label" />
|
android:text="@string/profile_ca_auto_label" />
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:id="@+id/select_certificate"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:minHeight="?android:attr/listPreferredItemHeight"
|
||||||
|
android:background="?android:attr/selectableItemBackground"
|
||||||
|
android:padding="10dp" >
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/select_certificate_title"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||||
|
android:text="@string/profile_ca_select_certificate_label" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/select_certificate_subtitle"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_below="@id/select_certificate_title"
|
||||||
|
android:layout_alignLeft="@id/select_certificate_title"
|
||||||
|
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||||
|
android:textColor="?android:attr/textColorSecondary"
|
||||||
|
android:text="@string/profile_ca_select_certificate" />
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
@@ -51,6 +51,8 @@
|
|||||||
<string name="profile_password_hint">(anfordern wenn benötigt)</string>
|
<string name="profile_password_hint">(anfordern wenn benötigt)</string>
|
||||||
<string name="profile_ca_label">CA-Zertifikat:</string>
|
<string name="profile_ca_label">CA-Zertifikat:</string>
|
||||||
<string name="profile_ca_auto_label">Automatisch wählen</string>
|
<string name="profile_ca_auto_label">Automatisch wählen</string>
|
||||||
|
<string name="profile_ca_select_certificate_label">CA-Zertifikat auswählen</string>
|
||||||
|
<string name="profile_ca_select_certificate">Wählen Sie ein bestimmtes CA-Zertifikat</string>
|
||||||
<!-- Warnings/Notifications in the details view -->
|
<!-- Warnings/Notifications in the details view -->
|
||||||
<string name="alert_text_no_input_gateway">Bitte geben Sie hier die Gateway-Adresse ein</string>
|
<string name="alert_text_no_input_gateway">Bitte geben Sie hier die Gateway-Adresse ein</string>
|
||||||
<string name="alert_text_no_input_username">Bitte geben Sie hier Ihren Benutzernamen ein</string>
|
<string name="alert_text_no_input_username">Bitte geben Sie hier Ihren Benutzernamen ein</string>
|
||||||
|
|||||||
@@ -51,6 +51,8 @@
|
|||||||
<string name="profile_password_hint">(prompt when needed)</string>
|
<string name="profile_password_hint">(prompt when needed)</string>
|
||||||
<string name="profile_ca_label">CA certificate:</string>
|
<string name="profile_ca_label">CA certificate:</string>
|
||||||
<string name="profile_ca_auto_label">Select automatically</string>
|
<string name="profile_ca_auto_label">Select automatically</string>
|
||||||
|
<string name="profile_ca_select_certificate_label">Select CA certificate</string>
|
||||||
|
<string name="profile_ca_select_certificate">Select a specific CA certificate</string>
|
||||||
<!-- Warnings/Notifications in the details view -->
|
<!-- Warnings/Notifications in the details view -->
|
||||||
<string name="alert_text_no_input_gateway">Please enter the gateway address here</string>
|
<string name="alert_text_no_input_gateway">Please enter the gateway address here</string>
|
||||||
<string name="alert_text_no_input_username">Please enter your username here</string>
|
<string name="alert_text_no_input_username">Please enter your username here</string>
|
||||||
|
|||||||
+14
-1
@@ -16,16 +16,19 @@
|
|||||||
package org.strongswan.android.ui;
|
package org.strongswan.android.ui;
|
||||||
|
|
||||||
import org.strongswan.android.R;
|
import org.strongswan.android.R;
|
||||||
|
import org.strongswan.android.data.TrustedCertificateEntry;
|
||||||
|
import org.strongswan.android.data.VpnProfileDataSource;
|
||||||
|
|
||||||
import android.app.ActionBar;
|
import android.app.ActionBar;
|
||||||
import android.app.ActionBar.Tab;
|
import android.app.ActionBar.Tab;
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.Fragment;
|
import android.app.Fragment;
|
||||||
import android.app.FragmentTransaction;
|
import android.app.FragmentTransaction;
|
||||||
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
|
|
||||||
public class TrustedCertificatesActivity extends Activity
|
public class TrustedCertificatesActivity extends Activity implements TrustedCertificateListFragment.OnTrustedCertificateSelectedListener
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState)
|
public void onCreate(Bundle savedInstanceState)
|
||||||
@@ -71,6 +74,16 @@ public class TrustedCertificatesActivity extends Activity
|
|||||||
return super.onOptionsItemSelected(item);
|
return super.onOptionsItemSelected(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTrustedCertificateSelected(TrustedCertificateEntry selected)
|
||||||
|
{
|
||||||
|
/* the user selected a certificate, return to calling activity */
|
||||||
|
Intent intent = new Intent();
|
||||||
|
intent.putExtra(VpnProfileDataSource.KEY_CERTIFICATE, selected.getAlias());
|
||||||
|
setResult(Activity.RESULT_OK, intent);
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
|
||||||
public static class TrustedCertificatesTabListener implements ActionBar.TabListener
|
public static class TrustedCertificatesTabListener implements ActionBar.TabListener
|
||||||
{
|
{
|
||||||
private final String mTag;
|
private final String mTag;
|
||||||
|
|||||||
@@ -17,7 +17,10 @@
|
|||||||
|
|
||||||
package org.strongswan.android.ui;
|
package org.strongswan.android.ui;
|
||||||
|
|
||||||
|
import java.security.cert.X509Certificate;
|
||||||
|
|
||||||
import org.strongswan.android.R;
|
import org.strongswan.android.R;
|
||||||
|
import org.strongswan.android.data.TrustedCertificateEntry;
|
||||||
import org.strongswan.android.data.VpnProfile;
|
import org.strongswan.android.data.VpnProfile;
|
||||||
import org.strongswan.android.data.VpnProfileDataSource;
|
import org.strongswan.android.data.VpnProfileDataSource;
|
||||||
import org.strongswan.android.logic.TrustedCertificateManager;
|
import org.strongswan.android.logic.TrustedCertificateManager;
|
||||||
@@ -26,37 +29,42 @@ import android.app.Activity;
|
|||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.AsyncTask;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuInflater;
|
import android.view.MenuInflater;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.Window;
|
import android.view.View.OnClickListener;
|
||||||
import android.widget.CheckBox;
|
import android.widget.CheckBox;
|
||||||
import android.widget.CompoundButton;
|
import android.widget.CompoundButton;
|
||||||
import android.widget.CompoundButton.OnCheckedChangeListener;
|
import android.widget.CompoundButton.OnCheckedChangeListener;
|
||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
|
import android.widget.RelativeLayout;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
public class VpnProfileDetailActivity extends Activity
|
public class VpnProfileDetailActivity extends Activity
|
||||||
{
|
{
|
||||||
|
private static final int SELECT_TRUSTED_CERTIFICATE = 0;
|
||||||
|
|
||||||
private VpnProfileDataSource mDataSource;
|
private VpnProfileDataSource mDataSource;
|
||||||
private Long mId;
|
private Long mId;
|
||||||
|
private TrustedCertificateEntry mCertEntry;
|
||||||
private VpnProfile mProfile;
|
private VpnProfile mProfile;
|
||||||
private boolean mCertsLoaded;
|
|
||||||
private String mCertAlias;
|
|
||||||
private EditText mName;
|
private EditText mName;
|
||||||
private EditText mGateway;
|
private EditText mGateway;
|
||||||
private EditText mUsername;
|
private EditText mUsername;
|
||||||
private EditText mPassword;
|
private EditText mPassword;
|
||||||
private CheckBox mCheckAuto;
|
private CheckBox mCheckAuto;
|
||||||
|
private RelativeLayout mSelectCert;
|
||||||
|
private TextView mCertTitle;
|
||||||
|
private TextView mCertSubtitle;
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState)
|
public void onCreate(Bundle savedInstanceState)
|
||||||
{
|
{
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
|
|
||||||
|
|
||||||
/* the title is set when we load the profile, if any */
|
/* the title is set when we load the profile, if any */
|
||||||
getActionBar().setDisplayHomeAsUpEnabled(true);
|
getActionBar().setDisplayHomeAsUpEnabled(true);
|
||||||
@@ -72,12 +80,24 @@ public class VpnProfileDetailActivity extends Activity
|
|||||||
mUsername = (EditText)findViewById(R.id.username);
|
mUsername = (EditText)findViewById(R.id.username);
|
||||||
|
|
||||||
mCheckAuto = (CheckBox)findViewById(R.id.ca_auto);
|
mCheckAuto = (CheckBox)findViewById(R.id.ca_auto);
|
||||||
|
mSelectCert = (RelativeLayout)findViewById(R.id.select_certificate);
|
||||||
|
mCertTitle = (TextView)findViewById(R.id.select_certificate_title);
|
||||||
|
mCertSubtitle = (TextView)findViewById(R.id.select_certificate_subtitle);
|
||||||
|
|
||||||
mCheckAuto.setOnCheckedChangeListener(new OnCheckedChangeListener() {
|
mCheckAuto.setOnCheckedChangeListener(new OnCheckedChangeListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)
|
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)
|
||||||
{
|
{
|
||||||
|
updateCertificateSelector();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
mSelectCert.setOnClickListener(new OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v)
|
||||||
|
{
|
||||||
|
Intent intent = new Intent(VpnProfileDetailActivity.this, TrustedCertificatesActivity.class);
|
||||||
|
startActivityForResult(intent, SELECT_TRUSTED_CERTIFICATE);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -88,9 +108,9 @@ public class VpnProfileDetailActivity extends Activity
|
|||||||
mId = extras == null ? null : extras.getLong(VpnProfileDataSource.KEY_ID);
|
mId = extras == null ? null : extras.getLong(VpnProfileDataSource.KEY_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
loadProfileData();
|
loadProfileData(savedInstanceState);
|
||||||
|
|
||||||
new CertificateLoadTask().execute();
|
updateCertificateSelector();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -108,6 +128,10 @@ public class VpnProfileDetailActivity extends Activity
|
|||||||
{
|
{
|
||||||
outState.putLong(VpnProfileDataSource.KEY_ID, mId);
|
outState.putLong(VpnProfileDataSource.KEY_ID, mId);
|
||||||
}
|
}
|
||||||
|
if (mCertEntry != null)
|
||||||
|
{
|
||||||
|
outState.putString(VpnProfileDataSource.KEY_CERTIFICATE, mCertEntry.getAlias());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -135,6 +159,25 @@ public class VpnProfileDetailActivity extends Activity
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onActivityResult(int requestCode, int resultCode, Intent data)
|
||||||
|
{
|
||||||
|
switch (requestCode)
|
||||||
|
{
|
||||||
|
case SELECT_TRUSTED_CERTIFICATE:
|
||||||
|
if (resultCode == RESULT_OK)
|
||||||
|
{
|
||||||
|
String alias = data.getStringExtra(VpnProfileDataSource.KEY_CERTIFICATE);
|
||||||
|
X509Certificate certificate = TrustedCertificateManager.getInstance().getCACertificateFromAlias(alias);
|
||||||
|
mCertEntry = certificate == null ? null : new TrustedCertificateEntry(alias, certificate);
|
||||||
|
updateCertificateSelector();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
super.onActivityResult(requestCode, resultCode, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show an alert in case the previously selected certificate is not found anymore
|
* Show an alert in case the previously selected certificate is not found anymore
|
||||||
* or the user did not select a certificate in the spinner.
|
* or the user did not select a certificate in the spinner.
|
||||||
@@ -155,32 +198,31 @@ public class VpnProfileDetailActivity extends Activity
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Asynchronously executed task which confirms that the certificates are loaded.
|
* Update the CA certificate selection UI depending on whether the
|
||||||
* They are loaded from the main Activity already but might not be ready yet, or
|
* certificate should be automatically selected or not.
|
||||||
* unloaded again.
|
|
||||||
*
|
|
||||||
* Once loaded the CA certificate spinner and checkboxes are updated
|
|
||||||
* accordingly.
|
|
||||||
*/
|
*/
|
||||||
private class CertificateLoadTask extends AsyncTask<Void, Void, TrustedCertificateManager>
|
private void updateCertificateSelector()
|
||||||
{
|
{
|
||||||
@Override
|
if (!mCheckAuto.isChecked())
|
||||||
protected void onPreExecute()
|
|
||||||
{
|
{
|
||||||
setProgressBarIndeterminateVisibility(true);
|
mSelectCert.setEnabled(true);
|
||||||
}
|
mSelectCert.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
@Override
|
if (mCertEntry != null)
|
||||||
protected TrustedCertificateManager doInBackground(Void... params)
|
{
|
||||||
{
|
mCertTitle.setText(mCertEntry.getSubjectPrimary());
|
||||||
return TrustedCertificateManager.getInstance().load();
|
mCertSubtitle.setText(mCertEntry.getSubjectSecondary());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mCertTitle.setText(R.string.profile_ca_select_certificate_label);
|
||||||
|
mCertSubtitle.setText(R.string.profile_ca_select_certificate);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
@Override
|
|
||||||
protected void onPostExecute(TrustedCertificateManager result)
|
|
||||||
{
|
{
|
||||||
setProgressBarIndeterminateVisibility(false);
|
mSelectCert.setEnabled(false);
|
||||||
mCertsLoaded = true;
|
mSelectCert.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -225,7 +267,7 @@ public class VpnProfileDetailActivity extends Activity
|
|||||||
mUsername.setError(getString(R.string.alert_text_no_input_username));
|
mUsername.setError(getString(R.string.alert_text_no_input_username));
|
||||||
valid = false;
|
valid = false;
|
||||||
}
|
}
|
||||||
if (!mCheckAuto.isChecked())
|
if (!mCheckAuto.isChecked() && mCertEntry == null)
|
||||||
{
|
{
|
||||||
showCertificateAlert();
|
showCertificateAlert();
|
||||||
valid = false;
|
valid = false;
|
||||||
@@ -247,13 +289,19 @@ public class VpnProfileDetailActivity extends Activity
|
|||||||
String password = mPassword.getText().toString().trim();
|
String password = mPassword.getText().toString().trim();
|
||||||
password = password.isEmpty() ? null : password;
|
password = password.isEmpty() ? null : password;
|
||||||
mProfile.setPassword(password);
|
mProfile.setPassword(password);
|
||||||
|
String certAlias = mCheckAuto.isChecked() ? null : mCertEntry.getAlias();
|
||||||
|
mProfile.setCertificateAlias(certAlias);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load an existing profile if we got an ID
|
* Load an existing profile if we got an ID
|
||||||
|
*
|
||||||
|
* @param savedInstanceState previously saved state
|
||||||
*/
|
*/
|
||||||
private void loadProfileData()
|
private void loadProfileData(Bundle savedInstanceState)
|
||||||
{
|
{
|
||||||
|
String alias = null;
|
||||||
|
|
||||||
getActionBar().setTitle(R.string.add_profile);
|
getActionBar().setTitle(R.string.add_profile);
|
||||||
if (mId != null)
|
if (mId != null)
|
||||||
{
|
{
|
||||||
@@ -264,7 +312,7 @@ public class VpnProfileDetailActivity extends Activity
|
|||||||
mGateway.setText(mProfile.getGateway());
|
mGateway.setText(mProfile.getGateway());
|
||||||
mUsername.setText(mProfile.getUsername());
|
mUsername.setText(mProfile.getUsername());
|
||||||
mPassword.setText(mProfile.getPassword());
|
mPassword.setText(mProfile.getPassword());
|
||||||
mCertAlias = mProfile.getCertificateAlias();
|
alias = mProfile.getCertificateAlias();
|
||||||
getActionBar().setTitle(mProfile.getName());
|
getActionBar().setTitle(mProfile.getName());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -274,6 +322,22 @@ public class VpnProfileDetailActivity extends Activity
|
|||||||
finish();
|
finish();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mCheckAuto.setChecked(mCertAlias == null);
|
|
||||||
|
/* check if the user selected a certificate previously */
|
||||||
|
alias = savedInstanceState == null ? alias : savedInstanceState.getString(VpnProfileDataSource.KEY_CERTIFICATE);
|
||||||
|
mCheckAuto.setChecked(alias == null);
|
||||||
|
if (alias != null)
|
||||||
|
{
|
||||||
|
X509Certificate certificate = TrustedCertificateManager.getInstance().getCACertificateFromAlias(alias);
|
||||||
|
if (certificate != null)
|
||||||
|
{
|
||||||
|
mCertEntry = new TrustedCertificateEntry(alias, certificate);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ /* previously selected certificate is not here anymore */
|
||||||
|
showCertificateAlert();
|
||||||
|
mCertEntry = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user