Add save-username checkbox in the connect dialog.

* changes
  + Add checkbox to layout file and handling code in related classes.
  + Add new methods to VpnProfileActor.
  + Move dialog handling to VpnSettings from AuthenticatorActor in order
    to support screen orientation change.
  + Hide "Connect" in the context menu if the profile is connecting.
  + Enable connecting profile in case it was disabled in last call.
This commit is contained in:
Hung-ying Tyan
2009-06-15 20:24:38 +08:00
parent 4226b0af53
commit d22da2096b
5 changed files with 294 additions and 179 deletions

View File

@@ -45,4 +45,10 @@
android:singleLine="True"/> android:singleLine="True"/>
</LinearLayout> </LinearLayout>
<CheckBox android:id="@+id/save_username"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/vpn_connect_margin_left"
android:text="@string/vpn_save_username" />
</LinearLayout> </LinearLayout>

View File

@@ -1755,6 +1755,7 @@ found in the list of installed applications.</string>
<string name="vpn_password_colon">Password:</string> <string name="vpn_password_colon">Password:</string>
<string name="vpn_username">User name</string> <string name="vpn_username">User name</string>
<string name="vpn_password">Password</string> <string name="vpn_password">Password</string>
<string name="vpn_save_username">Remember me</string>
<string name="vpn_you_miss_a_field">You missed a field!</string> <string name="vpn_you_miss_a_field">You missed a field!</string>
<string name="vpn_please_fill_up">Please fill up \"%s\".</string> <string name="vpn_please_fill_up">Please fill up \"%s\".</string>
@@ -1800,10 +1801,11 @@ found in the list of installed applications.</string>
<!-- EditTextPreference summary text when VPN is not connected --> <!-- EditTextPreference summary text when VPN is not connected -->
<string name="vpn_connect_hint">Select to connect</string> <string name="vpn_connect_hint">Select to connect</string>
<!-- dialog title when asking for username and password --> <!-- dialog title when asking for username and password -->
<string name="vpn_connect_to">Connect to</string> <string name="vpn_connect_to">Connect to %s</string>
<string name="vpn_default_profile_name">nowhere</string>
<string name="vpn_name">VPN Name</string> <string name="vpn_name">VPN Name</string>
<string name="vpn_name_summary">Give a name to this VPN;</string> <string name="vpn_name_summary">Give a name to this VPN</string>
<string name="vpn_profile_added">'%s' is added</string> <string name="vpn_profile_added">'%s' is added</string>
<string name="vpn_profile_replaced">Changes are made to '%s'</string> <string name="vpn_profile_replaced">Changes are made to '%s'</string>

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2007 The Android Open Source Project * Copyright (C) 2009 The Android Open Source Project
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -18,48 +18,32 @@ package com.android.settings.vpn;
import com.android.settings.R; import com.android.settings.R;
import android.app.AlertDialog; import android.app.Dialog;
import android.content.ComponentName; import android.content.ComponentName;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.ServiceConnection; import android.content.ServiceConnection;
import android.net.vpn.IVpnService; import android.net.vpn.IVpnService;
import android.net.vpn.VpnManager; import android.net.vpn.VpnManager;
import android.net.vpn.VpnProfile; import android.net.vpn.VpnProfile;
import android.net.vpn.VpnState; import android.net.vpn.VpnState;
import android.os.Bundle;
import android.os.IBinder; import android.os.IBinder;
import android.os.Parcelable;
import android.os.RemoteException; import android.os.RemoteException;
import android.util.Log; import android.util.Log;
import android.view.View; import android.view.View;
import android.widget.EditText; import android.widget.CheckBox;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast;
import java.io.IOException;
/** /**
* A {@link VpnProfileActor} that provides an authentication view for users to
* input username and password before connecting to the VPN server.
*/ */
public class AuthenticationActor implements VpnProfileActor, public class AuthenticationActor implements VpnProfileActor {
DialogInterface.OnClickListener, DialogInterface.OnCancelListener {
private static final String TAG = AuthenticationActor.class.getName(); private static final String TAG = AuthenticationActor.class.getName();
private static final int ONE_SECOND = 1000; // ms private static final int ONE_SECOND = 1000; // ms
private static final String STATE_IS_DIALOG_OPEN = "is_dialog_open";
private static final String STATE_USERNAME = "username";
private static final String STATE_PASSWORD = "password";
private Context mContext; private Context mContext;
private TextView mUsernameView;
private TextView mPasswordView;
private VpnProfile mProfile; private VpnProfile mProfile;
private View mView;
private VpnManager mVpnManager; private VpnManager mVpnManager;
private AlertDialog mConnectDialog;
private AlertDialog mDisconnectDialog;
public AuthenticationActor(Context context, VpnProfile p) { public AuthenticationActor(Context context, VpnProfile p) {
mContext = context; mContext = context;
@@ -73,77 +57,54 @@ public class AuthenticationActor implements VpnProfileActor,
} }
//@Override //@Override
public synchronized void connect() { public boolean isConnectDialogNeeded() {
connect("", ""); return true;
} }
//@Override //@Override
public void onClick(DialogInterface dialog, int which) { public String validateInputs(Dialog d) {
dismissConnectDialog(); TextView usernameView = (TextView) d.findViewById(R.id.username_value);
switch (which) { TextView passwordView = (TextView) d.findViewById(R.id.password_value);
case DialogInterface.BUTTON1: // connect
if (validateInputs()) {
broadcastConnectivity(VpnState.CONNECTING);
connectInternal();
}
break;
case DialogInterface.BUTTON2: // cancel
broadcastConnectivity(VpnState.CANCELLED);
break;
}
}
//@Override
public void onCancel(DialogInterface dialog) {
dismissConnectDialog();
broadcastConnectivity(VpnState.CANCELLED);
}
private void connect(String username, String password) {
Context c = mContext; Context c = mContext;
mConnectDialog = new AlertDialog.Builder(c) if (Util.isNullOrEmpty(usernameView.getText().toString())) {
.setView(createConnectView(username, password)) return c.getString(R.string.vpn_username);
.setTitle(c.getString(R.string.vpn_connect_to) + " " } else if (Util.isNullOrEmpty(passwordView.getText().toString())) {
+ mProfile.getName()) return c.getString(R.string.vpn_password);
.setPositiveButton(c.getString(R.string.vpn_connect_button), } else {
this) return null;
.setNegativeButton(c.getString(R.string.vpn_cancel_button),
this)
.setOnCancelListener(this)
.create();
mConnectDialog.show();
}
//@Override
public synchronized void onSaveState(Bundle outState) {
outState.putBoolean(STATE_IS_DIALOG_OPEN, (mConnectDialog != null));
if (mConnectDialog != null) {
assert(mConnectDialog.isShowing());
outState.putBoolean(STATE_IS_DIALOG_OPEN, (mConnectDialog != null));
outState.putString(STATE_USERNAME,
mUsernameView.getText().toString());
outState.putString(STATE_PASSWORD,
mPasswordView.getText().toString());
dismissConnectDialog();
} }
} }
//@Override //@Override
public synchronized void onRestoreState(final Bundle savedState) { public void connect(Dialog d) {
boolean isDialogOpen = savedState.getBoolean(STATE_IS_DIALOG_OPEN); TextView usernameView = (TextView) d.findViewById(R.id.username_value);
if (isDialogOpen) { TextView passwordView = (TextView) d.findViewById(R.id.password_value);
connect(savedState.getString(STATE_USERNAME), CheckBox saveUsername = (CheckBox) d.findViewById(R.id.save_username);
savedState.getString(STATE_PASSWORD));
// save username
if (saveUsername.isChecked()) {
mProfile.setSavedUsername(usernameView.getText().toString());
} else {
mProfile.setSavedUsername("");
} }
connect(usernameView.getText().toString(),
passwordView.getText().toString());
passwordView.setText("");
} }
private synchronized void dismissConnectDialog() { //@Override
mConnectDialog.dismiss(); public View createConnectView() {
mConnectDialog = null; return View.inflate(mContext, R.layout.vpn_connect_dialog_view, null);
} }
private void connectInternal() { //@Override
public void updateConnectView(Dialog d) {
String username = mProfile.getSavedUsername();
if (username == null) username = "";
updateConnectView(d, username, "", !Util.isNullOrEmpty(username));
}
private void connect(final String username, final String password) {
mVpnManager.startVpnService(); mVpnManager.startVpnService();
ServiceConnection c = new ServiceConnection() { ServiceConnection c = new ServiceConnection() {
public void onServiceConnected(ComponentName className, public void onServiceConnected(ComponentName className,
@@ -151,10 +112,7 @@ public class AuthenticationActor implements VpnProfileActor,
boolean success = false; boolean success = false;
try { try {
success = IVpnService.Stub.asInterface(service) success = IVpnService.Stub.asInterface(service)
.connect(mProfile, .connect(mProfile, username, password);
mUsernameView.getText().toString(),
mPasswordView.getText().toString());
mPasswordView.setText("");
} catch (Throwable e) { } catch (Throwable e) {
Log.e(TAG, "connect()", e); Log.e(TAG, "connect()", e);
checkStatus(); checkStatus();
@@ -230,61 +188,20 @@ public class AuthenticationActor implements VpnProfileActor,
return mVpnManager.bindVpnService(c); return mVpnManager.bindVpnService(c);
} }
private void updateConnectView(Dialog d, String username,
String password, boolean toSaveUsername) {
TextView usernameView = (TextView) d.findViewById(R.id.username_value);
TextView passwordView = (TextView) d.findViewById(R.id.password_value);
CheckBox saveUsername = (CheckBox) d.findViewById(R.id.save_username);
usernameView.setText(username);
passwordView.setText(password);
saveUsername.setChecked(toSaveUsername);
}
private void broadcastConnectivity(VpnState s) { private void broadcastConnectivity(VpnState s) {
mVpnManager.broadcastConnectivity(mProfile.getName(), s); mVpnManager.broadcastConnectivity(mProfile.getName(), s);
} }
// returns true if inputs pass validation
private boolean validateInputs() {
Context c = mContext;
String error = null;
if (Util.isNullOrEmpty(mUsernameView.getText().toString())) {
error = c.getString(R.string.vpn_username);
} else if (Util.isNullOrEmpty(mPasswordView.getText().toString())) {
error = c.getString(R.string.vpn_password);
}
if (error == null) {
return true;
} else {
new AlertDialog.Builder(c)
.setTitle(c.getString(R.string.vpn_you_miss_a_field))
.setMessage(String.format(
c.getString(R.string.vpn_please_fill_up), error))
.setPositiveButton(c.getString(R.string.vpn_back_button),
createBackButtonListener())
.show();
return false;
}
}
private View createConnectView(String username, String password) {
View v = View.inflate(mContext, R.layout.vpn_connect_dialog_view, null);
mUsernameView = (TextView) v.findViewById(R.id.username_value);
mPasswordView = (TextView) v.findViewById(R.id.password_value);
mUsernameView.setText(username);
mPasswordView.setText(password);
copyFieldsFromOldView(v);
mView = v;
return v;
}
private void copyFieldsFromOldView(View newView) {
if (mView == null) return;
mUsernameView.setText(
((TextView) mView.findViewById(R.id.username_value)).getText());
mPasswordView.setText(
((TextView) mView.findViewById(R.id.password_value)).getText());
}
private DialogInterface.OnClickListener createBackButtonListener() {
return new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
connect();
}
};
}
private void wait(Object o, int ms) { private void wait(Object o, int ms) {
synchronized (o) { synchronized (o) {
try { try {

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2007 The Android Open Source Project * Copyright (C) 2009 The Android Open Source Project
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -16,8 +16,9 @@
package com.android.settings.vpn; package com.android.settings.vpn;
import android.app.Dialog;
import android.net.vpn.VpnProfile; import android.net.vpn.VpnProfile;
import android.os.Bundle; import android.view.View;
/** /**
* The interface to act on a {@link VpnProfile}. * The interface to act on a {@link VpnProfile}.
@@ -26,9 +27,34 @@ public interface VpnProfileActor {
VpnProfile getProfile(); VpnProfile getProfile();
/** /**
* Establishes a VPN connection. * Returns true if a connect dialog is needed before establishing a
* connection.
*/ */
void connect(); boolean isConnectDialogNeeded();
/**
* Creates the view in the connect dialog.
*/
View createConnectView();
/**
* Updates the view in the connect dialog.
* @param dialog the recycled connect dialog.
*/
void updateConnectView(Dialog dialog);
/**
* Validates the inputs in the dialog.
* @param dialog the connect dialog
* @return an error message if the inputs are not valid
*/
String validateInputs(Dialog dialog);
/**
* Establishes a VPN connection.
* @param dialog the connect dialog
*/
void connect(Dialog dialog);
/** /**
* Tears down the connection. * Tears down the connection.
@@ -41,14 +67,4 @@ public interface VpnProfileActor {
* broadcast receiver and to receives the broadcast events. * broadcast receiver and to receives the broadcast events.
*/ */
void checkStatus(); void checkStatus();
/**
* Called to save the states when the device is rotated.
*/
void onSaveState(Bundle outState);
/**
* Called to restore the states on the rotated screen.
*/
void onRestoreState(Bundle savedState);
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2007 The Android Open Source Project * Copyright (C) 2009 The Android Open Source Project
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -19,6 +19,7 @@ package com.android.settings.vpn;
import com.android.settings.R; import com.android.settings.R;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.app.Dialog;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
@@ -28,6 +29,7 @@ import android.net.vpn.VpnProfile;
import android.net.vpn.VpnState; import android.net.vpn.VpnState;
import android.net.vpn.VpnType; import android.net.vpn.VpnType;
import android.os.Bundle; import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable; import android.os.Parcelable;
import android.preference.Preference; import android.preference.Preference;
import android.preference.PreferenceActivity; import android.preference.PreferenceActivity;
@@ -58,7 +60,8 @@ import java.util.Map;
/** /**
* The preference activity for configuring VPN settings. * The preference activity for configuring VPN settings.
*/ */
public class VpnSettings extends PreferenceActivity { public class VpnSettings extends PreferenceActivity implements
DialogInterface.OnClickListener {
// Key to the field exchanged for profile editing. // Key to the field exchanged for profile editing.
static final String KEY_VPN_PROFILE = "vpn_profile"; static final String KEY_VPN_PROFILE = "vpn_profile";
@@ -83,6 +86,8 @@ public class VpnSettings extends PreferenceActivity {
private static final int CONTEXT_MENU_EDIT_ID = ContextMenu.FIRST + 2; private static final int CONTEXT_MENU_EDIT_ID = ContextMenu.FIRST + 2;
private static final int CONTEXT_MENU_DELETE_ID = ContextMenu.FIRST + 3; private static final int CONTEXT_MENU_DELETE_ID = ContextMenu.FIRST + 3;
private static final int CONNECT_BUTTON = DialogInterface.BUTTON1;
private PreferenceScreen mAddVpn; private PreferenceScreen mAddVpn;
private PreferenceCategory mVpnListContainer; private PreferenceCategory mVpnListContainer;
@@ -95,8 +100,8 @@ public class VpnSettings extends PreferenceActivity {
// profile engaged in a connection // profile engaged in a connection
private VpnProfile mActiveProfile; private VpnProfile mActiveProfile;
// actor engaged in an action // actor engaged in connecting
private VpnProfileActor mActiveActor; private VpnProfileActor mConnectingActor;
private VpnManager mVpnManager = new VpnManager(this); private VpnManager mVpnManager = new VpnManager(this);
@@ -112,7 +117,6 @@ public class VpnSettings extends PreferenceActivity {
// restore VpnProfile list and construct VpnPreference map // restore VpnProfile list and construct VpnPreference map
mVpnListContainer = (PreferenceCategory) findPreference(PREF_VPN_LIST); mVpnListContainer = (PreferenceCategory) findPreference(PREF_VPN_LIST);
retrieveVpnListFromStorage();
// set up the "add vpn" preference // set up the "add vpn" preference
mAddVpn = (PreferenceScreen) findPreference(PREF_ADD_VPN); mAddVpn = (PreferenceScreen) findPreference(PREF_ADD_VPN);
@@ -132,12 +136,21 @@ public class VpnSettings extends PreferenceActivity {
} }
@Override @Override
protected synchronized void onSaveInstanceState(Bundle outState) { public void onResume() {
if (mActiveActor == null) return; super.onResume();
if ((mVpnProfileList == null) || mVpnProfileList.isEmpty()) {
retrieveVpnListFromStorage();
checkVpnConnectionStatusInBackground();
}
}
@Override
protected synchronized void onSaveInstanceState(Bundle outState) {
if (mConnectingActor == null) return;
mActiveActor.onSaveState(outState);
outState.putString(STATE_ACTIVE_ACTOR, outState.putString(STATE_ACTIVE_ACTOR,
mActiveActor.getProfile().getName()); mConnectingActor.getProfile().getName());
} }
@Override @Override
@@ -145,9 +158,10 @@ public class VpnSettings extends PreferenceActivity {
String profileName = savedState.getString(STATE_ACTIVE_ACTOR); String profileName = savedState.getString(STATE_ACTIVE_ACTOR);
if (Util.isNullOrEmpty(profileName)) return; if (Util.isNullOrEmpty(profileName)) return;
final VpnProfile p = mVpnPreferenceMap.get(profileName).mProfile; retrieveVpnListFromStorage();
mActiveActor = getActor(p);
mActiveActor.onRestoreState(savedState); VpnProfile p = mVpnPreferenceMap.get(profileName).mProfile;
mConnectingActor = getActor(p);
} }
@Override @Override
@@ -157,6 +171,33 @@ public class VpnSettings extends PreferenceActivity {
mVpnManager.unregisterConnectivityReceiver(mConnectivityReceiver); mVpnManager.unregisterConnectivityReceiver(mConnectivityReceiver);
} }
@Override
protected Dialog onCreateDialog (int id) {
if (mConnectingActor == null) {
Log.e(TAG, "no connecting actor to create the dialog");
}
String name = (mConnectingActor == null)
? getString(R.string.vpn_default_profile_name)
: mConnectingActor.getProfile().getName();
Dialog d = new AlertDialog.Builder(this)
.setView(mConnectingActor.createConnectView())
.setTitle(String.format(getString(R.string.vpn_connect_to),
name))
.setPositiveButton(getString(R.string.vpn_connect_button),
this)
.setNegativeButton(getString(R.string.vpn_cancel_button),
this)
.create();
return d;
}
@Override
protected void onPrepareDialog (int id, Dialog dialog) {
if (mConnectingActor != null) {
mConnectingActor.updateConnectView(dialog);
}
}
@Override @Override
public void onCreateContextMenu(ContextMenu menu, View v, public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) { ContextMenuInfo menuInfo) {
@@ -174,7 +215,7 @@ public class VpnSettings extends PreferenceActivity {
menu.add(0, CONTEXT_MENU_CONNECT_ID, 0, R.string.vpn_menu_connect) menu.add(0, CONTEXT_MENU_CONNECT_ID, 0, R.string.vpn_menu_connect)
.setEnabled(isIdle && (mActiveProfile == null)); .setEnabled(isIdle && (mActiveProfile == null));
menu.add(0, CONTEXT_MENU_DISCONNECT_ID, 0, R.string.vpn_menu_disconnect) menu.add(0, CONTEXT_MENU_DISCONNECT_ID, 0, R.string.vpn_menu_disconnect)
.setEnabled(!isIdle); .setEnabled(state == VpnState.CONNECTED);
menu.add(0, CONTEXT_MENU_EDIT_ID, 0, R.string.vpn_menu_edit) menu.add(0, CONTEXT_MENU_EDIT_ID, 0, R.string.vpn_menu_edit)
.setEnabled(isNotConnect); .setEnabled(isNotConnect);
menu.add(0, CONTEXT_MENU_DELETE_ID, 0, R.string.vpn_menu_delete) menu.add(0, CONTEXT_MENU_DELETE_ID, 0, R.string.vpn_menu_delete)
@@ -214,7 +255,7 @@ public class VpnSettings extends PreferenceActivity {
mIndexOfEditedProfile = -1; mIndexOfEditedProfile = -1;
if ((resultCode == RESULT_CANCELED) || (data == null)) { if ((resultCode == RESULT_CANCELED) || (data == null)) {
Log.v(TAG, "no result returned by editor"); Log.d(TAG, "no result returned by editor");
return; return;
} }
@@ -264,6 +305,35 @@ public class VpnSettings extends PreferenceActivity {
} }
} }
// Called when the buttons on the connect dialog are clicked.
//@Override
public synchronized void onClick(DialogInterface dialog, int which) {
dismissDialog(0);
if (which == CONNECT_BUTTON) {
Dialog d = (Dialog) dialog;
String error = mConnectingActor.validateInputs(d);
if (error == null) {
changeState(mConnectingActor.getProfile(), VpnState.CONNECTING);
mConnectingActor.connect(d);
return;
} else {
// show error dialog
new AlertDialog.Builder(this)
.setTitle(R.string.vpn_you_miss_a_field)
.setMessage(String.format(
getString(R.string.vpn_please_fill_up), error))
.setPositiveButton(R.string.vpn_back_button,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,
int which) {
showDialog(0);
}
})
.show();
}
}
}
// Replaces the profile at index in mVpnProfileList with p. // Replaces the profile at index in mVpnProfileList with p.
// Returns true if p's name is a duplicate. // Returns true if p's name is a duplicate.
private boolean checkDuplicateName(VpnProfile p, int index) { private boolean checkDuplicateName(VpnProfile p, int index) {
@@ -353,13 +423,17 @@ public class VpnSettings extends PreferenceActivity {
VpnPreference pref = mVpnPreferenceMap.get(p.getName()); VpnPreference pref = mVpnPreferenceMap.get(p.getName());
switch (p.getState()) { switch (p.getState()) {
case IDLE: case IDLE:
changeState(p, VpnState.CONNECTING); mConnectingActor = getActor(new VpnProfileWrapper(p));
mActiveActor = getActor(p); if (mConnectingActor.isConnectDialogNeeded()) {
mActiveActor.connect(); showDialog(0);
} else {
changeState(p, VpnState.CONNECTING);
mConnectingActor.connect(null);
}
break; break;
case CONNECTING: case CONNECTING:
// TODO: bring up a dialog to confirm disconnect // do nothing
break; break;
case CONNECTED: case CONNECTED:
@@ -376,14 +450,13 @@ public class VpnSettings extends PreferenceActivity {
VpnState oldState = p.getState(); VpnState oldState = p.getState();
if (oldState == state) return; if (oldState == state) return;
Log.d(TAG, "changeState: " + p.getName() + ": " + state);
p.setState(state); p.setState(state);
mVpnPreferenceMap.get(p.getName()).setSummary( mVpnPreferenceMap.get(p.getName()).setSummary(
getProfileSummaryString(p)); getProfileSummaryString(p));
switch (state) { switch (state) {
case CONNECTED: case CONNECTED:
mActiveActor = null; mConnectingActor = null;
// pass through // pass through
case CONNECTING: case CONNECTING:
mActiveProfile = p; mActiveProfile = p;
@@ -403,7 +476,7 @@ public class VpnSettings extends PreferenceActivity {
case IDLE: case IDLE:
assert(mActiveProfile != p); assert(mActiveProfile != p);
mActiveProfile = null; mActiveProfile = null;
mActiveActor = null; mConnectingActor = null;
enableProfilePreferences(); enableProfilePreferences();
if (oldState == VpnState.CONNECTING) mConnectingError = true; if (oldState == VpnState.CONNECTING) mConnectingError = true;
@@ -432,10 +505,13 @@ public class VpnSettings extends PreferenceActivity {
for (VpnProfile p : mVpnProfileList) { for (VpnProfile p : mVpnProfileList) {
switch (p.getState()) { switch (p.getState()) {
case DISCONNECTING: case DISCONNECTING:
case IDLE: case IDLE:
mVpnPreferenceMap.get(p.getName()).setEnabled(false); mVpnPreferenceMap.get(p.getName()).setEnabled(false);
break; break;
default:
mVpnPreferenceMap.get(p.getName()).setEnabled(true);
} }
} }
} }
@@ -466,6 +542,7 @@ public class VpnSettings extends PreferenceActivity {
private void retrieveVpnListFromStorage() { private void retrieveVpnListFromStorage() {
mVpnPreferenceMap = new LinkedHashMap<String, VpnPreference>(); mVpnPreferenceMap = new LinkedHashMap<String, VpnPreference>();
mVpnProfileList = new ArrayList<VpnProfile>(); mVpnProfileList = new ArrayList<VpnProfile>();
mVpnListContainer.removeAll();
File root = new File(PROFILES_ROOT); File root = new File(PROFILES_ROOT);
String[] dirs = root.list(); String[] dirs = root.list();
@@ -476,6 +553,7 @@ public class VpnSettings extends PreferenceActivity {
if (!f.exists()) continue; if (!f.exists()) continue;
try { try {
VpnProfile p = deserialize(f); VpnProfile p = deserialize(f);
if (p == null) continue;
if (!checkIdConsistency(dir, p)) continue; if (!checkIdConsistency(dir, p)) continue;
mVpnProfileList.add(p); mVpnProfileList.add(p);
@@ -485,7 +563,6 @@ public class VpnSettings extends PreferenceActivity {
} }
} }
disableProfilePreferencesIfOneActive(); disableProfilePreferencesIfOneActive();
checkVpnConnectionStatusInBackground();
} }
private void checkVpnConnectionStatusInBackground() { private void checkVpnConnectionStatusInBackground() {
@@ -502,7 +579,7 @@ public class VpnSettings extends PreferenceActivity {
// are consistent. // are consistent.
private boolean checkIdConsistency(String dirName, VpnProfile p) { private boolean checkIdConsistency(String dirName, VpnProfile p) {
if (!dirName.equals(p.getId())) { if (!dirName.equals(p.getId())) {
Log.v(TAG, "ID inconsistent: " + dirName + " vs " + p.getId()); Log.d(TAG, "ID inconsistent: " + dirName + " vs " + p.getId());
return false; return false;
} else { } else {
return true; return true;
@@ -517,7 +594,8 @@ public class VpnSettings extends PreferenceActivity {
ois.close(); ois.close();
return p; return p;
} catch (ClassNotFoundException e) { } catch (ClassNotFoundException e) {
throw new RuntimeException(e); Log.d(TAG, "deserialize a profile", e);
return null;
} }
} }
@@ -582,4 +660,100 @@ public class VpnSettings extends PreferenceActivity {
} }
} }
} }
// to catch saved user name in the connect dialog
private class VpnProfileWrapper extends VpnProfile {
private VpnProfile mProfile;
VpnProfileWrapper(VpnProfile p) {
mProfile = p;
}
@Override
public void setSavedUsername(String name) {
if ((name != null) && !name.equals(mProfile.getSavedUsername())) {
mProfile.setSavedUsername(name);
try {
saveProfileToStorage(mProfile);
} catch (IOException e) {
Log.d(TAG, "save username", e);
// harmless
}
}
}
@Override
public String getSavedUsername() {
return mProfile.getSavedUsername();
}
@Override
public void writeToParcel(Parcel parcel, int flags) {
mProfile.writeToParcel(parcel, flags);
}
@Override
public void setName(String name) {
}
@Override
public String getName() {
return mProfile.getName();
}
@Override
public void setId(String id) {
}
@Override
public String getId() {
return mProfile.getId();
}
@Override
public void setServerName(String name) {
}
@Override
public String getServerName() {
return mProfile.getServerName();
}
@Override
public void setDomainSuffices(String entries) {
}
@Override
public String getDomainSuffices() {
return mProfile.getDomainSuffices();
}
@Override
public void setRouteList(String entries) {
}
@Override
public String getRouteList() {
return mProfile.getRouteList();
}
@Override
public void setState(VpnState state) {
}
@Override
public VpnState getState() {
return mProfile.getState();
}
@Override
public boolean isIdle() {
return mProfile.isIdle();
}
@Override
public VpnType getType() {
return mProfile.getType();
}
}
} }