mirror of
https://github.com/classilla/tenfourfox.git
synced 2024-07-31 06:29:45 +00:00
159 lines
5.5 KiB
Java
159 lines
5.5 KiB
Java
/* 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.mozstumbler.service.utils;
|
|
|
|
import android.os.Build;
|
|
import android.util.Log;
|
|
|
|
import org.mozilla.mozstumbler.service.AppGlobals;
|
|
import org.mozilla.mozstumbler.service.Prefs;
|
|
|
|
import java.io.BufferedOutputStream;
|
|
import java.io.IOException;
|
|
import java.io.InputStream;
|
|
import java.io.OutputStream;
|
|
import java.net.HttpURLConnection;
|
|
import java.net.MalformedURLException;
|
|
import java.net.URL;
|
|
|
|
public abstract class AbstractCommunicator {
|
|
|
|
private static final String LOG_TAG = AppGlobals.makeLogTag(AbstractCommunicator.class.getSimpleName());
|
|
private static final String NICKNAME_HEADER = "X-Nickname";
|
|
private static final String USER_AGENT_HEADER = "User-Agent";
|
|
private HttpURLConnection mHttpURLConnection;
|
|
private final String mUserAgent;
|
|
private static int sBytesSentTotal = 0;
|
|
private static String sMozApiKey;
|
|
|
|
public abstract String getUrlString();
|
|
|
|
public static class HttpErrorException extends IOException {
|
|
private static final long serialVersionUID = -5404095858043243126L;
|
|
public final int responseCode;
|
|
|
|
public HttpErrorException(int responseCode) {
|
|
super();
|
|
this.responseCode = responseCode;
|
|
}
|
|
|
|
public boolean isTemporary() {
|
|
return responseCode >= 500 && responseCode <= 599;
|
|
}
|
|
}
|
|
|
|
public static class SyncSummary {
|
|
public int numIoExceptions;
|
|
public int totalBytesSent;
|
|
}
|
|
|
|
public static class NetworkSendResult {
|
|
public int bytesSent;
|
|
// Zero is no error, for HTTP error cases, set this code to the error
|
|
public int errorCode = -1;
|
|
}
|
|
|
|
public abstract NetworkSendResult cleanSend(byte[] data);
|
|
|
|
public String getNickname() {
|
|
return null;
|
|
}
|
|
|
|
public AbstractCommunicator() {
|
|
Prefs prefs = Prefs.getInstanceWithoutContext();
|
|
mUserAgent = (prefs != null)? prefs.getUserAgent() : "fennec-stumbler-unset-user-agent";
|
|
}
|
|
|
|
private void openConnectionAndSetHeaders() {
|
|
try {
|
|
Prefs prefs = Prefs.getInstanceWithoutContext();
|
|
if (sMozApiKey == null || prefs != null) {
|
|
sMozApiKey = prefs.getMozApiKey();
|
|
}
|
|
URL url = new URL(getUrlString() + "?key=" + sMozApiKey);
|
|
mHttpURLConnection = (HttpURLConnection) url.openConnection();
|
|
mHttpURLConnection.setRequestMethod("POST");
|
|
} catch (MalformedURLException e) {
|
|
throw new IllegalArgumentException(e);
|
|
} catch (IOException e) {
|
|
Log.e(LOG_TAG, "Couldn't open a connection: " + e);
|
|
}
|
|
mHttpURLConnection.setDoOutput(true);
|
|
mHttpURLConnection.setRequestProperty(USER_AGENT_HEADER, mUserAgent);
|
|
mHttpURLConnection.setRequestProperty("Content-Type", "application/json");
|
|
|
|
// Workaround for a bug in Android mHttpURLConnection. When the library
|
|
// reuses a stale connection, the connection may fail with an EOFException
|
|
if (Build.VERSION.SDK_INT > 13 && Build.VERSION.SDK_INT < 19) {
|
|
mHttpURLConnection.setRequestProperty("Connection", "Close");
|
|
}
|
|
String nickname = getNickname();
|
|
if (nickname != null) {
|
|
mHttpURLConnection.setRequestProperty(NICKNAME_HEADER, nickname);
|
|
}
|
|
}
|
|
|
|
private byte[] zipData(byte[] data) throws IOException {
|
|
byte[] output = Zipper.zipData(data);
|
|
return output;
|
|
}
|
|
|
|
private void sendData(byte[] data) throws IOException{
|
|
mHttpURLConnection.setFixedLengthStreamingMode(data.length);
|
|
OutputStream out = new BufferedOutputStream(mHttpURLConnection.getOutputStream());
|
|
out.write(data);
|
|
out.flush();
|
|
int code = mHttpURLConnection.getResponseCode();
|
|
final boolean isSuccessCode2XX = (code/100 == 2);
|
|
if (!isSuccessCode2XX) {
|
|
throw new HttpErrorException(code);
|
|
}
|
|
}
|
|
|
|
public enum ZippedState { eNotZipped, eAlreadyZipped };
|
|
/* Return the number of bytes sent. */
|
|
public int send(byte[] data, ZippedState isAlreadyZipped) throws IOException {
|
|
openConnectionAndSetHeaders();
|
|
String logMsg;
|
|
try {
|
|
if (isAlreadyZipped != ZippedState.eAlreadyZipped) {
|
|
data = zipData(data);
|
|
}
|
|
mHttpURLConnection.setRequestProperty("Content-Encoding","gzip");
|
|
} catch (IOException e) {
|
|
Log.e(LOG_TAG, "Couldn't compress and send data, falling back to plain-text: ", e);
|
|
close();
|
|
}
|
|
|
|
try {
|
|
sendData(data);
|
|
} finally {
|
|
close();
|
|
}
|
|
sBytesSentTotal += data.length;
|
|
logMsg = "Send data: " + String.format("%.2f", data.length / 1024.0) + " kB";
|
|
logMsg += " Session Total:" + String.format("%.2f", sBytesSentTotal / 1024.0) + " kB";
|
|
AppGlobals.guiLogInfo(logMsg, "#FFFFCC", true);
|
|
Log.d(LOG_TAG, logMsg);
|
|
return data.length;
|
|
}
|
|
|
|
public InputStream getInputStream() {
|
|
try {
|
|
return mHttpURLConnection.getInputStream();
|
|
} catch (IOException e) {
|
|
return mHttpURLConnection.getErrorStream();
|
|
}
|
|
}
|
|
|
|
public void close() {
|
|
if (mHttpURLConnection == null) {
|
|
return;
|
|
}
|
|
mHttpURLConnection.disconnect();
|
|
mHttpURLConnection = null;
|
|
}
|
|
}
|