/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.gecko.sync.jpake.stage;
import java.io.IOException;
import java.net.URISyntaxException;
import java.security.GeneralSecurityException;
import org.mozilla.gecko.sync.Logger;
import org.mozilla.gecko.sync.jpake.JPakeClient;
import org.mozilla.gecko.sync.jpake.JPakeResponse;
import org.mozilla.gecko.sync.net.BaseResource;
import org.mozilla.gecko.sync.net.SyncResourceDelegate;
import org.mozilla.gecko.sync.setup.Constants;
import ch.boye.httpclientandroidlib.HttpResponse;
import ch.boye.httpclientandroidlib.client.ClientProtocolException;
import ch.boye.httpclientandroidlib.client.methods.HttpRequestBase;
import ch.boye.httpclientandroidlib.impl.client.DefaultHttpClient;
import ch.boye.httpclientandroidlib.message.BasicHeader;
public class GetChannelStage extends JPakeStage {
private interface GetChannelStageDelegate {
public void handleSuccess(String channel);
public void handleFailure(String error);
public void handleError(Exception e);
}
@Override
public void execute(final JPakeClient jClient) {
Logger.debug(LOG_TAG, "Getting channel.");
// Make delegate to handle responses and propagate them to JPakeClient.
GetChannelStageDelegate callbackDelegate = new GetChannelStageDelegate() {
@Override
public void handleSuccess(String channel) {
if (jClient.finished) {
Logger.debug(LOG_TAG, "Finished; returning.");
return;
}
jClient.channelUrl = jClient.jpakeServer + channel;
Logger.debug(LOG_TAG, "Using channel " + channel);
jClient.makeAndDisplayPin(channel);
jClient.runNextStage();
}
@Override
public void handleFailure(String error) {
Logger.error(LOG_TAG, "Got HTTP failure: " + error);
jClient.abort(error);
}
@Override
public void handleError(Exception e) {
Logger.error(LOG_TAG, "Threw HTTP exception.", e);
jClient.abort(Constants.JPAKE_ERROR_CHANNEL);
}
};
try {
makeChannelRequest(callbackDelegate, jClient.jpakeServer + "new_channel", jClient.clientId);
} catch (URISyntaxException e) {
Logger.error(LOG_TAG, "Incorrect URI syntax.", e);
jClient.abort(Constants.JPAKE_ERROR_CHANNEL);
return;
} catch (Exception e) {
Logger.error(LOG_TAG, "Unexpected exception.", e);
jClient.abort(Constants.JPAKE_ERROR_CHANNEL);
return;
}
}
private void makeChannelRequest(final GetChannelStageDelegate callbackDelegate, String getChannelUrl, final String clientId) throws URISyntaxException {
final BaseResource httpResource = new BaseResource(getChannelUrl);
httpResource.delegate = new SyncResourceDelegate(httpResource) {
@Override
public void addHeaders(HttpRequestBase request, DefaultHttpClient client) {
request.setHeader(new BasicHeader("X-KeyExchange-Id", clientId));
}
@Override
public void handleHttpResponse(HttpResponse response) {
try {
JPakeResponse res = new JPakeResponse(response);
Object body = null;
try {
body = res.jsonBody();
} catch (Exception e) {
callbackDelegate.handleError(e);
return;
}
String channel = body instanceof String ? (String) body : null;
if (channel == null) {
callbackDelegate.handleFailure(Constants.JPAKE_ERROR_CHANNEL);
return;
}
callbackDelegate.handleSuccess(channel);
} finally {
BaseResource.consumeEntity(response);
}
}
@Override
public void handleHttpProtocolException(ClientProtocolException e) {
callbackDelegate.handleError(e);
}
@Override
public void handleHttpIOException(IOException e) {
callbackDelegate.handleError(e);
}
@Override
public void handleTransportException(GeneralSecurityException e) {
callbackDelegate.handleError(e);
}
@Override
public int connectionTimeout() {
return JPakeClient.REQUEST_TIMEOUT;
}
};
// Make GET request.
JPakeClient.runOnThread(new Runnable() {
@Override
public void run() {
httpResource.get();
}
});
}
}