summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMartin Hibdon <mhibdon@google.com>2014-07-17 14:26:43 -0700
committerMartin Hibdon <mhibdon@google.com>2014-07-17 15:46:02 -0700
commit03735a839ba61710f887fffd6d3f605c0b127c2e (patch)
treead1b82a68a9b891a806efdca2d8a2c45b0819c56 /src
parentdb678bada9a25089f4ea32be0d8e6d678749459c (diff)
downloadandroid_packages_apps_Exchange-03735a839ba61710f887fffd6d3f605c0b127c2e.tar.gz
android_packages_apps_Exchange-03735a839ba61710f887fffd6d3f605c0b127c2e.tar.bz2
android_packages_apps_Exchange-03735a839ba61710f887fffd6d3f605c0b127c2e.zip
Improve Exchange AutoDiscover
Clean up the way we attempt multiple different uris, and add ability to attempt an unauthenticated get request if the first two alternatives fail. Also, clean up the way that EasOptions gets its HttpRequest. Change-Id: Ib89e5e30f4fa6b2144d23ac39f3844099bfba4d0
Diffstat (limited to 'src')
-rw-r--r--src/com/android/exchange/eas/EasAutoDiscover.java57
-rw-r--r--src/com/android/exchange/eas/EasOperation.java10
-rw-r--r--src/com/android/exchange/eas/EasOptions.java5
-rw-r--r--src/com/android/exchange/service/EasServerConnection.java6
-rw-r--r--src/com/android/exchange/service/EasService.java32
5 files changed, 79 insertions, 31 deletions
diff --git a/src/com/android/exchange/eas/EasAutoDiscover.java b/src/com/android/exchange/eas/EasAutoDiscover.java
index feb38663..cbcb032b 100644
--- a/src/com/android/exchange/eas/EasAutoDiscover.java
+++ b/src/com/android/exchange/eas/EasAutoDiscover.java
@@ -16,6 +16,7 @@ import com.android.mail.utils.LogUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpStatus;
+import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.entity.StringEntity;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -27,6 +28,11 @@ import java.io.IOException;
public class EasAutoDiscover extends EasOperation {
+ public final static int ATTEMPT_PRIMARY = 0;
+ public final static int ATTEMPT_ALTERNATE = 1;
+ public final static int ATTEMPT_UNAUTHENTICATED_GET = 2;
+ public final static int ATTEMPT_MAX = 2;
+
public final static int RESULT_OK = 1;
public final static int RESULT_SC_UNAUTHORIZED = RESULT_OP_SPECIFIC_ERROR_RESULT - 0;
public final static int RESULT_REDIRECT = RESULT_OP_SPECIFIC_ERROR_RESULT - 1;
@@ -55,17 +61,19 @@ public class EasAutoDiscover extends EasOperation {
private static final String ELEMENT_NAME_RESPONSE = "Response";
private static final String ELEMENT_NAME_AUTODISCOVER = "Autodiscover";
+ private final int mAttemptNumber;
private final String mUri;
private final String mUsername;
private final String mPassword;
private HostAuth mHostAuth;
private String mRedirectUri;
- public EasAutoDiscover(final Context context, final String uri, final String username,
- final String password) {
+ public EasAutoDiscover(final Context context, final String uri, final int attemptNumber,
+ final String username, final String password) {
// We don't actually need an account or a hostAuth, but the EasServerConnection requires
// one. Just create dummy values.
super(context, -1);
+ mAttemptNumber = attemptNumber;
mUri = uri;
mUsername = username;
mPassword = password;
@@ -78,6 +86,25 @@ public class EasAutoDiscover extends EasOperation {
setAccount(new Account(), mHostAuth);
}
+ public static String genUri(final String domain, final int attemptNumber) {
+ // Try the following uris in order, as per
+ // http://msdn.microsoft.com/en-us/library/office/jj900169(v=exchg.150).aspx
+ // TODO: That document also describes a fallback strategy to query DNS for an SRV record,
+ // but this would require additional DNS lookup services that are not currently available
+ // in the android platform,
+ switch (attemptNumber) {
+ case ATTEMPT_PRIMARY:
+ return "https://" + domain + AUTO_DISCOVER_PAGE;
+ case ATTEMPT_ALTERNATE:
+ return "https://autodiscover." + domain + AUTO_DISCOVER_PAGE;
+ case ATTEMPT_UNAUTHENTICATED_GET:
+ return "http://autodiscover." + domain + AUTO_DISCOVER_PAGE;
+ default:
+ LogUtils.wtf(TAG, "Illegal attempt number %d", attemptNumber);
+ return null;
+ }
+ }
+
protected String getRequestUri() {
return mUri;
}
@@ -90,14 +117,6 @@ public class EasAutoDiscover extends EasOperation {
return login.substring(amp + 1);
}
- public static String createUri(final String domain) {
- return "https://" + domain + AUTO_DISCOVER_PAGE;
- }
-
- public static String createAlternateUri(final String domain) {
- return "https://autodiscover." + domain + AUTO_DISCOVER_PAGE;
- }
-
@Override
protected String getCommand() {
return null;
@@ -129,6 +148,24 @@ public class EasAutoDiscover extends EasOperation {
return null;
}
+ /**
+ * Create the request object for this operation.
+ * The default is to use a POST, but some use other request types (e.g. Options).
+ * @return An {@link org.apache.http.client.methods.HttpUriRequest}.
+ * @throws IOException
+ */
+ protected HttpUriRequest makeRequest() throws IOException, MessageInvalidException {
+ final String requestUri = getRequestUri();
+ HttpUriRequest req;
+ if (mAttemptNumber == ATTEMPT_UNAUTHENTICATED_GET) {
+ req = mConnection.makeGet(requestUri);
+ } else {
+ req = mConnection.makePost(requestUri, getRequestEntity(),
+ getRequestContentType(), addPolicyKeyHeaderToRequest());
+ }
+ return req;
+ }
+
public String getRedirectUri() {
return mRedirectUri;
}
diff --git a/src/com/android/exchange/eas/EasOperation.java b/src/com/android/exchange/eas/EasOperation.java
index 19dc1492..174b0001 100644
--- a/src/com/android/exchange/eas/EasOperation.java
+++ b/src/com/android/exchange/eas/EasOperation.java
@@ -156,7 +156,7 @@ public abstract class EasOperation {
protected Account mAccount;
/** The connection to use for this operation. This is created when {@link #mAccount} is set. */
- private EasServerConnection mConnection;
+ protected EasServerConnection mConnection;
public class MessageInvalidException extends Exception {
public MessageInvalidException(final String message) {
@@ -487,16 +487,12 @@ public abstract class EasOperation {
/**
* Create the request object for this operation.
- * Most operations use a POST, but some use other request types (e.g. Options).
+ * The default is to use a POST, but some use other request types (e.g. Options).
* @return An {@link HttpUriRequest}.
* @throws IOException
*/
- private final HttpUriRequest makeRequest() throws IOException, MessageInvalidException {
+ protected HttpUriRequest makeRequest() throws IOException, MessageInvalidException {
final String requestUri = getRequestUri();
- if (requestUri == null) {
- return mConnection.makeOptions();
- }
-
HttpUriRequest req = mConnection.makePost(requestUri, getRequestEntity(),
getRequestContentType(), addPolicyKeyHeaderToRequest());
return req;
diff --git a/src/com/android/exchange/eas/EasOptions.java b/src/com/android/exchange/eas/EasOptions.java
index 131c3919..08a01b1a 100644
--- a/src/com/android/exchange/eas/EasOptions.java
+++ b/src/com/android/exchange/eas/EasOptions.java
@@ -23,7 +23,9 @@ import com.google.common.collect.Sets;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
+import org.apache.http.client.methods.HttpUriRequest;
+import java.io.IOException;
import java.util.HashSet;
/**
@@ -102,6 +104,9 @@ public class EasOptions extends EasOperation {
return null;
}
+ protected HttpUriRequest makeRequest() throws IOException, MessageInvalidException {
+ return mConnection.makeOptions();
+ }
/**
* Find the best protocol version to use from the header.
* @param versionHeader The {@link Header} for the server's supported versions.
diff --git a/src/com/android/exchange/service/EasServerConnection.java b/src/com/android/exchange/service/EasServerConnection.java
index faa092e6..87d5b284 100644
--- a/src/com/android/exchange/service/EasServerConnection.java
+++ b/src/com/android/exchange/service/EasServerConnection.java
@@ -44,6 +44,7 @@ import com.android.mail.utils.LogUtils;
import org.apache.http.HttpEntity;
import org.apache.http.client.HttpClient;
+import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpOptions;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
@@ -313,6 +314,11 @@ public class EasServerConnection {
return post;
}
+ public HttpGet makeGet(final String uri) {
+ final HttpGet get = new HttpGet(uri);
+ return get;
+ }
+
/**
* Make an {@link HttpOptions} request for this connection.
* @return The {@link HttpOptions} object.
diff --git a/src/com/android/exchange/service/EasService.java b/src/com/android/exchange/service/EasService.java
index db6c05e1..fb56e1cc 100644
--- a/src/com/android/exchange/service/EasService.java
+++ b/src/com/android/exchange/service/EasService.java
@@ -153,26 +153,30 @@ public class EasService extends Service {
@Override
public Bundle autoDiscover(final String username, final String password) {
final String domain = EasAutoDiscover.getDomain(username);
- final String uri = EasAutoDiscover.createUri(domain);
- final Bundle result = autoDiscoverInternal(uri, username, password, true);
- final int resultCode = result.getInt(EmailServiceProxy.AUTO_DISCOVER_BUNDLE_ERROR_CODE);
- if (resultCode == EasAutoDiscover.RESULT_BAD_RESPONSE) {
- // Try the alternate uri
- final String alternateUri = EasAutoDiscover.createAlternateUri(domain);
- return autoDiscoverInternal(alternateUri, username, password, true);
- } else {
- return result;
+ for (int attempt = 0; attempt <= EasAutoDiscover.ATTEMPT_MAX; attempt++) {
+ LogUtils.d(TAG, "autodiscover attempt %d", attempt);
+ final String uri = EasAutoDiscover.genUri(domain, attempt);
+ Bundle result = autoDiscoverInternal(uri, attempt, username, password, true);
+ int resultCode = result.getInt(EmailServiceProxy.AUTO_DISCOVER_BUNDLE_ERROR_CODE);
+ if (resultCode != EasAutoDiscover.RESULT_BAD_RESPONSE) {
+ return result;
+ } else {
+ LogUtils.d(TAG, "got BAD_RESPONSE");
+ }
}
+ return null;
}
- private Bundle autoDiscoverInternal(final String uri, final String username,
- final String password, final boolean canRetry) {
- final EasAutoDiscover op = new EasAutoDiscover(EasService.this, uri, username, password);
+ private Bundle autoDiscoverInternal(final String uri, final int attempt,
+ final String username, final String password,
+ final boolean canRetry) {
+ final EasAutoDiscover op = new EasAutoDiscover(EasService.this, uri, attempt,
+ username, password);
final int result = op.performOperation();
if (result == EasAutoDiscover.RESULT_REDIRECT) {
// Try again recursively with the new uri. TODO we should limit the number of redirects.
final String redirectUri = op.getRedirectUri();
- return autoDiscoverInternal(redirectUri, username, password, canRetry);
+ return autoDiscoverInternal(redirectUri, attempt, username, password, canRetry);
} else if (result == EasAutoDiscover.RESULT_SC_UNAUTHORIZED) {
if (canRetry && username.contains("@")) {
// Try again using the bare user name
@@ -180,7 +184,7 @@ public class EasService extends Service {
final String bareUsername = username.substring(0, atSignIndex);
LogUtils.d(TAG, "%d received; trying username: %s", result, atSignIndex);
// Try again recursively, but this time don't allow retries for username.
- return autoDiscoverInternal(uri, bareUsername, password, false);
+ return autoDiscoverInternal(uri, attempt, bareUsername, password, false);
} else {
// Either we're already on our second try or the username didn't have an "@"
// to begin with. Either way, failure.