Rework EAS account creation & ssl operation

* Fixes 2048663, 2025029, and 2100131
* Add "Trust Certificates" checkbox in EAS account creation
* Use custom ClientConnectionManager for HttpClient with registry
  for plain, ssl, and tssl (trusted ssl) connection
* Use a ConnectionPool for HttpClient connections
* Remove "Domain" checkbox in  EAS account creation
* Remove tests related to the "Domain" field
* TODO Write a test for valid usernames (requires a bit of research)
  <name>, <email address>, <domain>/<name, and <domain>\<name> are all
  valid, but there might be others

Change-Id: I4a0338df5960bfd3d679a88aaf22d1c49f49992b
This commit is contained in:
Marc Blank 2009-09-05 15:14:46 -07:00
parent 7f3f3f392d
commit cef2344e70
12 changed files with 165 additions and 115 deletions

View File

@ -69,24 +69,16 @@
android:imeOptions="actionDone"
android:layout_height="wrap_content"
android:layout_width="fill_parent" />
<TextView
android:text="@string/account_setup_exchange_domain_label"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="?android:attr/textColorPrimary" />
<EditText
android:id="@+id/account_domain"
android:hint="@string/account_setup_exchange_domain_hint"
inputType="text"
android:imeOptions="actionDone"
android:layout_height="wrap_content"
android:layout_width="fill_parent" />
<CheckBox
android:id="@+id/account_ssl"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:text="@string/account_setup_exchange_ssl_label" />
<CheckBox
android:id="@+id/account_trust_certificates"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:text="@string/account_setup_exchange_trust_certificates_label" />
</LinearLayout>
<RelativeLayout

View File

@ -364,6 +364,8 @@
<string name="account_setup_exchange_domain_hint">Enter domain here</string>
<!-- On "Exchange" setup screen, the use-SSL checkbox label -->
<string name="account_setup_exchange_ssl_label">Use secure connection (SSL)</string>
<!-- On "Exchange" setup screen, the trust ssl certificates checkbox label -->
<string name="account_setup_exchange_trust_certificates_label">Accept all SSL certificates</string>
<!-- In Account setup options screen, Activity title -->
<string name="account_setup_options_title">Account options</string>

View File

@ -19,18 +19,20 @@ package com.android.email.activity.setup;
import com.android.email.R;
import com.android.email.Utility;
import com.android.email.provider.EmailContent;
import com.android.email.provider.EmailContent.Account;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.CompoundButton.OnCheckedChangeListener;
import java.net.URI;
import java.net.URISyntaxException;
@ -45,7 +47,8 @@ import java.net.URISyntaxException;
* User (login)
* Password
*/
public class AccountSetupExchange extends Activity implements OnClickListener {
public class AccountSetupExchange extends Activity implements OnClickListener,
OnCheckedChangeListener {
private static final String EXTRA_ACCOUNT = "account";
private static final String EXTRA_MAKE_DEFAULT = "makeDefault";
private static final String EXTRA_EAS_FLOW = "easFlow";
@ -53,14 +56,14 @@ public class AccountSetupExchange extends Activity implements OnClickListener {
private EditText mUsernameView;
private EditText mPasswordView;
private EditText mServerView;
private EditText mDomainView;
private CheckBox mSslSecurityView;
private CheckBox mTrustCertificatesView;
private Button mNextButton;
private EmailContent.Account mAccount;
private Account mAccount;
private boolean mMakeDefault;
public static void actionIncomingSettings(Activity fromActivity, EmailContent.Account account,
public static void actionIncomingSettings(Activity fromActivity, Account account,
boolean makeDefault, boolean easFlowMode) {
Intent i = new Intent(fromActivity, AccountSetupExchange.class);
i.putExtra(EXTRA_ACCOUNT, account);
@ -69,7 +72,7 @@ public class AccountSetupExchange extends Activity implements OnClickListener {
fromActivity.startActivity(i);
}
public static void actionEditIncomingSettings(Activity fromActivity, EmailContent.Account account)
public static void actionEditIncomingSettings(Activity fromActivity, Account account)
{
Intent i = new Intent(fromActivity, AccountSetupExchange.class);
i.setAction(Intent.ACTION_EDIT);
@ -81,7 +84,7 @@ public class AccountSetupExchange extends Activity implements OnClickListener {
* For now, we'll simply replicate outgoing, for the purpose of satisfying the
* account settings flow.
*/
public static void actionEditOutgoingSettings(Activity fromActivity, EmailContent.Account account)
public static void actionEditOutgoingSettings(Activity fromActivity, Account account)
{
Intent i = new Intent(fromActivity, AccountSetupExchange.class);
i.setAction(Intent.ACTION_EDIT);
@ -97,8 +100,9 @@ public class AccountSetupExchange extends Activity implements OnClickListener {
mUsernameView = (EditText) findViewById(R.id.account_username);
mPasswordView = (EditText) findViewById(R.id.account_password);
mServerView = (EditText) findViewById(R.id.account_server);
mDomainView = (EditText) findViewById(R.id.account_domain);
mSslSecurityView = (CheckBox) findViewById(R.id.account_ssl);
mSslSecurityView.setOnCheckedChangeListener(this);
mTrustCertificatesView = (CheckBox) findViewById(R.id.account_trust_certificates);
mNextButton = (Button)findViewById(R.id.next);
mNextButton.setOnClickListener(this);
@ -121,7 +125,6 @@ public class AccountSetupExchange extends Activity implements OnClickListener {
mUsernameView.addTextChangedListener(validationTextWatcher);
mPasswordView.addTextChangedListener(validationTextWatcher);
mServerView.addTextChangedListener(validationTextWatcher);
mDomainView.addTextChangedListener(validationTextWatcher);
mAccount = (EmailContent.Account) getIntent().getParcelableExtra(EXTRA_ACCOUNT);
mMakeDefault = getIntent().getBooleanExtra(EXTRA_MAKE_DEFAULT, false);
@ -164,12 +167,10 @@ public class AccountSetupExchange extends Activity implements OnClickListener {
mServerView.setText(uri.getHost());
}
String domain = uri.getPath();
if (!TextUtils.isEmpty(domain)) {
mDomainView.setText(domain.substring(1));
}
mSslSecurityView.setChecked(uri.getScheme().contains("ssl"));
boolean ssl = uri.getScheme().contains("ssl");
mSslSecurityView.setChecked(ssl);
mTrustCertificatesView.setChecked(uri.getScheme().contains("tssl"));
mTrustCertificatesView.setVisibility(ssl ? View.VISIBLE : View.GONE);
} catch (URISyntaxException use) {
/*
@ -233,15 +234,12 @@ public class AccountSetupExchange extends Activity implements OnClickListener {
*/
private URI getUri() throws URISyntaxException {
boolean sslRequired = mSslSecurityView.isChecked();
String scheme = sslRequired ? "eas+ssl+" : "eas";
boolean trustCertificates = mTrustCertificatesView.isChecked();
String scheme = (sslRequired) ? (trustCertificates ? "eas+tssl+" : "eas+ssl+") : "eas";
String userInfo = mUsernameView.getText().toString().trim() + ":" +
mPasswordView.getText().toString().trim();
String host = mServerView.getText().toString().trim();
String domain = mDomainView.getText().toString().trim();
String path = null;
if (domain.length() > 0) {
path = "/" + domain;
}
URI uri = new URI(
scheme,
@ -281,4 +279,10 @@ public class AccountSetupExchange extends Activity implements OnClickListener {
break;
}
}
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (buttonView.getId() == R.id.account_ssl) {
mTrustCertificatesView.setVisibility(isChecked ? View.VISIBLE : View.GONE);
}
}
}

View File

@ -46,7 +46,6 @@ import java.util.HashMap;
public class ExchangeStore extends Store {
public static final String LOG_TAG = "ExchangeStore";
private Context mContext;
private URI mUri;
private final ExchangeTransport mTransport;
@ -66,7 +65,6 @@ public class ExchangeStore extends Store {
*/
private ExchangeStore(String _uri, Context context, PersistentDataCallbacks callbacks)
throws MessagingException {
mContext = context;
try {
mUri = new URI(_uri);
} catch (URISyntaxException e) {
@ -157,14 +155,14 @@ public class ExchangeStore extends Store {
private static HashMap<String, ExchangeTransport> sUriToInstanceMap =
new HashMap<String, ExchangeTransport>();
private static final HashMap<String, Integer> sFolderMap = new HashMap<String, Integer>();
/**
* Public factory. The transport should be a singleton (per Uri)
*/
public synchronized static ExchangeTransport getInstance(URI uri, Context context)
throws MessagingException {
if (!uri.getScheme().equals("eas") && !uri.getScheme().equals("eas+ssl+")) {
if (!uri.getScheme().equals("eas") && !uri.getScheme().equals("eas+ssl+") &&
!uri.getScheme().equals("eas+tssl+")) {
throw new MessagingException("Invalid scheme");
}
@ -221,9 +219,11 @@ public class ExchangeStore extends Store {
public void checkSettings(URI uri) throws MessagingException {
setUri(uri);
boolean ssl = uri.getScheme().contains("ssl+");
boolean tssl = uri.getScheme().contains("tssl+");
try {
int port = ssl ? 443 : 80;
int result = new EmailServiceProxy(mContext, SyncManager.class)
.validate("eas", mHost, mUsername, mPassword, ssl ? 443 : 80, ssl);
.validate("eas", mHost, mUsername, mPassword, port, ssl, tssl);
if (result != MessagingException.NO_ERROR) {
if (result == MessagingException.AUTHENTICATION_FAILED) {
throw new AuthenticationFailedException("Authentication failed.");

View File

@ -16,18 +16,17 @@
package com.android.email.mail.store;
import org.apache.harmony.xnet.provider.jsse.SSLParameters;
import android.net.http.DomainNameChecker;
import java.security.cert.X509Certificate;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.X509TrustManager;
import org.apache.harmony.xnet.provider.jsse.SSLParameters;
public final class TrustManagerFactory {
private static X509TrustManager sUnsecureTrustManager
= new SimpleX509TrustManager();
private static X509TrustManager sUnsecureTrustManager = new SimpleX509TrustManager();
private static class SimpleX509TrustManager implements X509TrustManager {
public void checkClientTrusted(X509Certificate[] chain, String authType)
@ -63,8 +62,7 @@ public final class TrustManagerFactory {
mTrustManager.checkServerTrusted(chain, authType);
if (!DomainNameChecker.match(chain[0], mHost)) {
throw new CertificateException("Certificate domain name does not match "
+ mHost);
throw new CertificateException("Certificate domain name does not match " + mHost);
}
}
@ -77,8 +75,7 @@ public final class TrustManagerFactory {
}
public static X509TrustManager get(String host, boolean secure) {
return secure ? new SecureX509TrustManager(
SSLParameters.getDefaultTrustManager(), host)
return secure ? new SecureX509TrustManager(SSLParameters.getDefaultTrustManager(), host)
: sUnsecureTrustManager;
}
}

View File

@ -1916,6 +1916,7 @@ public abstract class EmailContent {
public static final int FLAG_SSL = 1;
public static final int FLAG_TLS = 2;
public static final int FLAG_AUTHENTICATE = 4;
public static final int FLAG_TRUST_ALL_CERTIFICATES = 8;
public String mProtocol;
public String mAddress;
@ -2013,7 +2014,9 @@ public abstract class EmailContent {
*/
public String getStoreUri() {
String security = "";
if ((mFlags & FLAG_SSL) != 0) {
if ((mFlags & FLAG_TRUST_ALL_CERTIFICATES) != 0) {
security = "+tssl+";
} else if ((mFlags & FLAG_SSL) != 0) {
security = "+ssl+";
} else if ((mFlags & FLAG_TLS) != 0) {
security = "+tls+";
@ -2068,10 +2071,15 @@ public abstract class EmailContent {
mProtocol = (schemeParts.length >= 1) ? schemeParts[0] : null;
boolean ssl = false;
boolean tls = false;
boolean tssl = false;
if (schemeParts.length >= 2) {
if ("ssl".equals(schemeParts[1])) {
String part1 = schemeParts[1];
if ("tssl".equals(part1)) {
ssl = true;
} else if ("tls".equals(schemeParts[1])) {
tssl = true;
} else if ("ssl".equals(part1)) {
ssl = true;
} else if ("tls".equals(part1)) {
tls = true;
}
}
@ -2083,6 +2091,9 @@ public abstract class EmailContent {
if (tls) {
mFlags |= FLAG_TLS;
}
if (tssl) {
mFlags |= FLAG_TRUST_ALL_CERTIFICATES;
}
mAddress = uri.getHost();
mPort = uri.getPort();
@ -2092,11 +2103,11 @@ public abstract class EmailContent {
if ("pop3".equals(mProtocol)) {
mPort = ssl ? 995 : 110;
} else if ("imap".equals(mProtocol)) {
mPort = ssl ? 993 : 143;
mPort = ssl || tssl ? 993 : 143;
} else if ("eas".equals(mProtocol)) {
mPort = ssl ? 443 : 80;
mPort = ssl || tssl ? 443 : 80;
} else if ("smtp".equals(mProtocol)) {
mPort = ssl ? 465 : 25;
mPort = ssl || tssl ? 465 : 25;
}
}

View File

@ -184,12 +184,14 @@ public class EmailServiceProxy implements IEmailService {
}
public int validate(final String protocol, final String host, final String userName,
final String password, final int port, final boolean ssl) throws RemoteException {
final String password, final int port, final boolean ssl,
final boolean trustCertificates) throws RemoteException {
setTask(new Runnable () {
public void run() {
try {
if (mCallback != null) mService.setCallback(mCallback);
mReturn = mService.validate(protocol, host, userName, password, port, ssl);
mReturn = mService.validate(protocol, host, userName, password, port, ssl,
trustCertificates);
} catch (RemoteException e) {
}
}

View File

@ -101,7 +101,7 @@ public abstract class AbstractSyncService implements Runnable {
* @throws MessagingException
*/
public abstract void validateAccount(String host, String userName, String password, int port,
boolean ssl, Context context) throws MessagingException;
boolean ssl, boolean trustCertificates, Context context) throws MessagingException;
public AbstractSyncService(Context _context, Mailbox _mailbox) {
mContext = _context;
@ -129,12 +129,13 @@ public abstract class AbstractSyncService implements Runnable {
* @throws MessagingException
*/
static public void validate(Class<? extends AbstractSyncService> klass, String host,
String userName, String password, int port, boolean ssl, Context context)
String userName, String password, int port, boolean ssl, boolean trustCertificates,
Context context)
throws MessagingException {
AbstractSyncService svc;
try {
svc = klass.newInstance();
svc.validateAccount(host, userName, password, port, ssl, context);
svc.validateAccount(host, userName, password, port, ssl, trustCertificates, context);
} catch (IllegalAccessException e) {
throw new MessagingException("internal error", e);
} catch (InstantiationException e) {

View File

@ -46,6 +46,7 @@ import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpOptions;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.BasicHttpParams;
@ -65,11 +66,11 @@ import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URLEncoder;
import java.security.cert.CertificateException;
import java.util.ArrayList;
import java.util.HashMap;
public class EasSyncService extends AbstractSyncService {
private static final String EMAIL_WINDOW_SIZE = "5";
public static final String PIM_WINDOW_SIZE = "20";
private static final String WHERE_ACCOUNT_KEY_AND_SERVER_ID =
@ -133,6 +134,7 @@ public class EasSyncService extends AbstractSyncService {
public String mUserName;
public String mPassword;
private boolean mSsl = true;
private boolean mTrustSsl = false;
public ContentResolver mContentResolver;
private String[] mBindArguments = new String[2];
private ArrayList<String> mPingChangeList;
@ -149,6 +151,7 @@ public class EasSyncService extends AbstractSyncService {
mContentResolver = _context.getContentResolver();
HostAuth ha = HostAuth.restoreHostAuthWithId(_context, mAccount.mHostAuthKeyRecv);
mSsl = (ha.mFlags & HostAuth.FLAG_SSL) != 0;
mTrustSsl = (ha.mFlags & HostAuth.FLAG_TRUST_ALL_CERTIFICATES) != 0;
}
private EasSyncService(String prefix) {
@ -191,7 +194,7 @@ public class EasSyncService extends AbstractSyncService {
@Override
public void validateAccount(String hostAddress, String userName, String password, int port,
boolean ssl, Context context) throws MessagingException {
boolean ssl, boolean trustCertificates, Context context) throws MessagingException {
try {
userLog("Testing EAS: ", hostAddress, ", ", userName, ", ssl = ", ssl ? "1" : "0");
EasSyncService svc = new EasSyncService("%TestAccount%");
@ -200,6 +203,7 @@ public class EasSyncService extends AbstractSyncService {
svc.mUserName = userName;
svc.mPassword = password;
svc.mSsl = ssl;
svc.mTrustSsl = trustCertificates;
svc.mDeviceId = SyncManager.getDeviceId();
HttpResponse resp = svc.sendHttpClientOptions();
int code = resp.getStatusLine().getStatusCode();
@ -218,7 +222,12 @@ public class EasSyncService extends AbstractSyncService {
throw new MessagingException(MessagingException.IOERROR);
}
} catch (IOException e) {
userLog("IOException caught, reporting I/O error: ", e.getMessage());
Throwable cause = e.getCause();
if (cause != null && cause instanceof CertificateException) {
userLog("CertificateException caught: ", e.getMessage());
throw new MessagingException(MessagingException.GENERAL_SECURITY);
}
userLog("IOException caught: ", e.getMessage());
throw new MessagingException(MessagingException.IOERROR);
}
@ -351,7 +360,7 @@ public class EasSyncService extends AbstractSyncService {
mCmdString = "&User=" + safeUserName + "&DeviceId=" + mDeviceId + "&DeviceType="
+ mDeviceType;
}
String us = (mSsl ? "https" : "http") + "://" + mHostAddress +
String us = (mSsl ? (mTrustSsl ? "httpts" : "https") : "http") + "://" + mHostAddress +
"/Microsoft-Server-ActiveSync";
if (cmd != null) {
us += "?Cmd=" + cmd + mCmdString;
@ -369,11 +378,17 @@ public class EasSyncService extends AbstractSyncService {
method.setHeader("User-Agent", mDeviceType + '/' + Eas.VERSION);
}
private ClientConnectionManager getClientConnectionManager() {
return SyncManager.getClientConnectionManager();
}
private HttpClient getHttpClient(int timeout) {
HttpParams params = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(params, 15*SECONDS);
HttpConnectionParams.setSoTimeout(params, timeout);
return new DefaultHttpClient(params);
HttpConnectionParams.setSocketBufferSize(params, 8192);
HttpClient client = new DefaultHttpClient(getClientConnectionManager(), params);
return client;
}
protected HttpResponse sendHttpClientPost(String cmd, byte[] bytes) throws IOException {

View File

@ -21,7 +21,7 @@ import com.android.exchange.EmailContent;
interface IEmailService {
int validate(in String protocol, in String host, in String userName, in String password,
int port, boolean ssl) ;
int port, boolean ssl, boolean trustCertificates) ;
void startSync(long mailboxId);
void stopSync(long mailboxId);

View File

@ -18,6 +18,7 @@
package com.android.exchange;
import com.android.email.mail.MessagingException;
import com.android.email.mail.store.TrustManagerFactory;
import com.android.email.provider.EmailContent;
import com.android.email.provider.EmailContent.Account;
import com.android.email.provider.EmailContent.Attachment;
@ -29,6 +30,19 @@ import com.android.email.provider.EmailContent.Message;
import com.android.email.provider.EmailContent.SyncColumns;
import com.android.exchange.utility.FileLogger;
import org.apache.harmony.xnet.provider.jsse.SSLContextImpl;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.params.ConnManagerPNames;
import org.apache.http.conn.params.ConnPerRoute;
import org.apache.http.conn.routing.HttpRoute;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpParams;
import android.accounts.AccountManager;
import android.accounts.OnAccountsUpdatedListener;
import android.app.AlarmManager;
@ -65,10 +79,16 @@ import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
/**
* The SyncManager handles all aspects of starting, maintaining, and stopping the various sync
* adapters used by Exchange. However, it is capable of handing any kind of email sync, and it
@ -176,6 +196,8 @@ public class SyncManager extends Service implements Runnable {
private static Thread sServiceThread = null;
// Cached unique device id
private static String sDeviceId = null;
// ConnectionManager that all EAS threads can use
private static ClientConnectionManager sClientConnectionManager = null;
private boolean mStop = false;
@ -240,10 +262,10 @@ public class SyncManager extends Service implements Runnable {
private final IEmailService.Stub mBinder = new IEmailService.Stub() {
public int validate(String protocol, String host, String userName, String password,
int port, boolean ssl) throws RemoteException {
int port, boolean ssl, boolean trustCertificates) throws RemoteException {
try {
AbstractSyncService.validate(EasSyncService.class, host, userName, password, port,
ssl, SyncManager.this);
ssl, trustCertificates, SyncManager.this);
return MessagingException.NO_ERROR;
} catch (MessagingException e) {
return e.getExceptionType();
@ -672,6 +694,52 @@ public class SyncManager extends Service implements Runnable {
}
}
static public ConnPerRoute sConnPerRoute = new ConnPerRoute() {
public int getMaxForRoute(HttpRoute route) {
return 8;
}
};
static public synchronized ClientConnectionManager getClientConnectionManager() {
if (sClientConnectionManager == null) {
// Create a registry for our three schemes; http and https will use built-in factories
SchemeRegistry registry = new SchemeRegistry();
registry.register(new Scheme("http",
PlainSocketFactory.getSocketFactory(), 80));
registry.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443));
// Create a new SSLSocketFactory for our "trusted ssl"
// Get the unsecure trust manager from the factory
X509TrustManager trustManager = TrustManagerFactory.get(null, false);
TrustManager[] trustManagers = new TrustManager[] {trustManager};
SSLContext sslcontext;
try {
sslcontext = SSLContext.getInstance("TLS");
sslcontext.init(null, trustManagers, null);
SSLContextImpl sslContext = new SSLContextImpl();
try {
sslContext.engineInit(null, trustManagers, null, null, null);
} catch (KeyManagementException e) {
throw new AssertionError(e);
}
// Ok, now make our factory
SSLSocketFactory sf = new SSLSocketFactory(sslContext.engineGetSocketFactory());
sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
// Register the httpts scheme with our factory
registry.register(new Scheme("httpts", sf, 443));
// And create a ccm with our registry
HttpParams params = new BasicHttpParams();
params.setIntParameter(ConnManagerPNames.MAX_TOTAL_CONNECTIONS, 25);
params.setParameter(ConnManagerPNames.MAX_CONNECTIONS_PER_ROUTE, sConnPerRoute);
sClientConnectionManager = new ThreadSafeClientConnManager(params, registry);
} catch (NoSuchAlgorithmException e2) {
} catch (KeyManagementException e1) {
}
}
// Null is a valid return result if we get an exception
return sClientConnectionManager;
}
@Override
public void onDestroy() {
log("!!! EAS SyncManager destroyed");

View File

@ -38,7 +38,6 @@ public class AccountSetupExchangeTests extends
private AccountSetupExchange mActivity;
private EditText mServerView;
private EditText mDomainView;
private Button mNextButton;
public AccountSetupExchangeTests() {
@ -56,7 +55,7 @@ public class AccountSetupExchangeTests extends
// This sets up a default URI which can be used by any of the test methods below.
// Individual test methods can replace this with a custom URI if they wish
// (except those that run on the UI thread - for them, it's too late to change it.)
Intent i = getTestIntent("eas://user:password@server.com/domain");
Intent i = getTestIntent("eas://user:password@server.com");
setActivityIntent(i);
}
@ -64,17 +63,20 @@ public class AccountSetupExchangeTests extends
* Test processing with a complete, good URI -> good fields
*/
public void testGoodUri() {
Intent i = getTestIntent("eas://user:password@server.com/domain");
Intent i = getTestIntent("eas://user:password@server.com");
setActivityIntent(i);
getActivityAndFields();
assertTrue(mNextButton.isEnabled());
}
// TODO Add tests for valid usernames in eas
// They would be <name> or <name>\<domain> or <name>/<domain> or a valid email address
/**
* No user is not OK - not enabled
*/
public void testBadUriNoUser() {
Intent i = getTestIntent("eas://:password@server.com/domain");
Intent i = getTestIntent("eas://:password@server.com");
setActivityIntent(i);
getActivityAndFields();
assertFalse(mNextButton.isEnabled());
@ -84,7 +86,7 @@ public class AccountSetupExchangeTests extends
* No password is not OK - not enabled
*/
public void testBadUriNoPassword() {
Intent i = getTestIntent("eas://user@server.com/domain");
Intent i = getTestIntent("eas://user@server.com");
setActivityIntent(i);
getActivityAndFields();
assertFalse(mNextButton.isEnabled());
@ -116,49 +118,6 @@ public class AccountSetupExchangeTests extends
mServerView.setText("serv$er.com");
assertFalse(mNextButton.isEnabled());
}
/**
* No EAS domain is OK - enabled
*/
public void testBadUriNoDomain() {
Intent i = getTestIntent("eas://user:password@server.com");
setActivityIntent(i);
getActivityAndFields();
assertTrue(mNextButton.isEnabled());
}
/**
* Test for non-standard but OK domain names
*/
@UiThreadTest
public void testGoodDomainVariants() {
getActivityAndFields();
assertTrue(mNextButton.isEnabled());
mDomainView.setText(" domain ");
assertTrue(mNextButton.isEnabled());
}
/**
* Test for non-empty but non-OK domain names
*
* TODO: These are tests that *should* fail but the code is not checking these cases
*/
@UiThreadTest
public void disabled_testBadDomainVariants() {
getActivityAndFields();
assertTrue(mNextButton.isEnabled());
mDomainView.setText(" ");
assertTrue(mNextButton.isEnabled());
mDomainView.setText("do main");
assertFalse(mNextButton.isEnabled());
}
/**
* TODO: More tests of exchange-specific fields?
*/
/**
* Get the activity (which causes it to be started, using our intent) and get the UI fields
@ -166,7 +125,6 @@ public class AccountSetupExchangeTests extends
private void getActivityAndFields() {
mActivity = getActivity();
mServerView = (EditText) mActivity.findViewById(R.id.account_server);
mDomainView = (EditText) mActivity.findViewById(R.id.account_domain);
mNextButton = (Button) mActivity.findViewById(R.id.next);
}