mirror of
https://github.com/oxen-io/session-android.git
synced 2025-01-02 05:07:44 +00:00
Switch to using our own JobManager.
// FREEBIE
This commit is contained in:
parent
73d896f378
commit
b308996885
@ -36,14 +36,13 @@ dependencies {
|
||||
compile 'com.astuetz:pagerslidingtabstrip:1.0.1'
|
||||
compile 'org.w3c:smil:1.0.0'
|
||||
compile 'org.apache.httpcomponents:httpclient-android:4.3.5'
|
||||
compile 'com.path:android-priority-jobqueue:1.1.2'
|
||||
|
||||
androidTestCompile 'com.squareup:fest-android:1.0.8'
|
||||
|
||||
compile project(':library')
|
||||
|
||||
androidTestCompile 'com.google.dexmaker:dexmaker:1.1'
|
||||
androidTestCompile 'com.google.dexmaker:dexmaker-mockito:1.1'
|
||||
|
||||
compile project(':library')
|
||||
compile project(':jobqueue')
|
||||
}
|
||||
|
||||
dependencyVerification {
|
||||
@ -58,7 +57,6 @@ dependencyVerification {
|
||||
'com.googlecode.libphonenumber:libphonenumber:eba17eae81dd622ea89a00a3a8c025b2f25d342e0d9644c5b62e16f15687c3ab',
|
||||
'org.whispersystems:gson:08f4f7498455d1539c9233e5aac18e9b1805815ef29221572996508eb512fe51',
|
||||
'com.google.protobuf:protobuf-java:e0c1c64575c005601725e7c6a02cebf9e1285e888f756b2a1d73ffa8d725cc74',
|
||||
'com.path:android-priority-jobqueue:af8d0dc930c3640518e9548ec887cf7871ab5e3c1ea634a4553dd5c30dd6e4a8'
|
||||
]
|
||||
}
|
||||
|
||||
|
@ -416,63 +416,58 @@ public class PushServiceSocket {
|
||||
private HttpURLConnection makeBaseRequest(String urlFragment, String method, String body)
|
||||
throws NonSuccessfulResponseCodeException, PushNetworkException
|
||||
{
|
||||
HttpURLConnection connection = getConnection(urlFragment, method, body);
|
||||
int responseCode;
|
||||
String responseMessage;
|
||||
String response;
|
||||
|
||||
try {
|
||||
HttpURLConnection connection = getConnection(urlFragment, method);
|
||||
responseCode = connection.getResponseCode();
|
||||
responseMessage = connection.getResponseMessage();
|
||||
} catch (IOException ioe) {
|
||||
throw new PushNetworkException(ioe);
|
||||
}
|
||||
|
||||
if (body != null) {
|
||||
connection.setDoOutput(true);
|
||||
}
|
||||
|
||||
connection.connect();
|
||||
|
||||
if (body != null) {
|
||||
Log.w("PushServiceSocket", method + " -- " + body);
|
||||
OutputStream out = connection.getOutputStream();
|
||||
out.write(body.getBytes());
|
||||
out.close();
|
||||
}
|
||||
|
||||
if (connection.getResponseCode() == 413) {
|
||||
switch (responseCode) {
|
||||
case 413:
|
||||
connection.disconnect();
|
||||
throw new RateLimitException("Rate limit exceeded: " + connection.getResponseCode());
|
||||
}
|
||||
|
||||
if (connection.getResponseCode() == 401 || connection.getResponseCode() == 403) {
|
||||
throw new RateLimitException("Rate limit exceeded: " + responseCode);
|
||||
case 401:
|
||||
case 403:
|
||||
connection.disconnect();
|
||||
throw new AuthorizationFailedException("Authorization failed!");
|
||||
}
|
||||
|
||||
if (connection.getResponseCode() == 404) {
|
||||
case 404:
|
||||
connection.disconnect();
|
||||
throw new NotFoundException("Not found");
|
||||
}
|
||||
|
||||
if (connection.getResponseCode() == 409) {
|
||||
String response = Util.readFully(connection.getErrorStream());
|
||||
case 409:
|
||||
try {
|
||||
response = Util.readFully(connection.getErrorStream());
|
||||
} catch (IOException e) {
|
||||
throw new PushNetworkException(e);
|
||||
}
|
||||
throw new MismatchedDevicesException(new Gson().fromJson(response, MismatchedDevices.class));
|
||||
}
|
||||
|
||||
if (connection.getResponseCode() == 410) {
|
||||
String response = Util.readFully(connection.getErrorStream());
|
||||
case 410:
|
||||
try {
|
||||
response = Util.readFully(connection.getErrorStream());
|
||||
} catch (IOException e) {
|
||||
throw new PushNetworkException(e);
|
||||
}
|
||||
throw new StaleDevicesException(new Gson().fromJson(response, StaleDevices.class));
|
||||
}
|
||||
|
||||
if (connection.getResponseCode() == 417) {
|
||||
case 417:
|
||||
throw new ExpectationFailedException();
|
||||
}
|
||||
|
||||
if (connection.getResponseCode() != 200 && connection.getResponseCode() != 204) {
|
||||
throw new NonSuccessfulResponseCodeException("Bad response: " + connection.getResponseCode() +
|
||||
" " + connection.getResponseMessage());
|
||||
}
|
||||
|
||||
return connection;
|
||||
} catch (IOException e) {
|
||||
throw new PushNetworkException(e);
|
||||
}
|
||||
|
||||
if (responseCode != 200 && responseCode != 204) {
|
||||
throw new NonSuccessfulResponseCodeException("Bad response: " + responseCode + " " +
|
||||
responseMessage);
|
||||
}
|
||||
|
||||
return connection;
|
||||
}
|
||||
|
||||
private HttpURLConnection getConnection(String urlFragment, String method) throws IOException {
|
||||
private HttpURLConnection getConnection(String urlFragment, String method, String body)
|
||||
throws PushNetworkException
|
||||
{
|
||||
try {
|
||||
SSLContext context = SSLContext.getInstance("TLS");
|
||||
context.init(null, trustManagers, null);
|
||||
@ -481,11 +476,11 @@ public class PushServiceSocket {
|
||||
Log.w("PushServiceSocket", "Push service URL: " + serviceUrl);
|
||||
Log.w("PushServiceSocket", "Opening URL: " + url);
|
||||
|
||||
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
|
||||
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
||||
|
||||
if (ENFORCE_SSL) {
|
||||
((HttpsURLConnection)connection).setSSLSocketFactory(context.getSocketFactory());
|
||||
((HttpsURLConnection)connection).setHostnameVerifier(new StrictHostnameVerifier());
|
||||
((HttpsURLConnection) connection).setSSLSocketFactory(context.getSocketFactory());
|
||||
((HttpsURLConnection) connection).setHostnameVerifier(new StrictHostnameVerifier());
|
||||
}
|
||||
|
||||
connection.setRequestMethod(method);
|
||||
@ -495,13 +490,26 @@ public class PushServiceSocket {
|
||||
connection.setRequestProperty("Authorization", getAuthorizationHeader());
|
||||
}
|
||||
|
||||
if (body != null) {
|
||||
connection.setDoOutput(true);
|
||||
}
|
||||
|
||||
connection.connect();
|
||||
|
||||
if (body != null) {
|
||||
Log.w("PushServiceSocket", method + " -- " + body);
|
||||
OutputStream out = connection.getOutputStream();
|
||||
out.write(body.getBytes());
|
||||
out.close();
|
||||
}
|
||||
|
||||
return connection;
|
||||
} catch (IOException e) {
|
||||
throw new PushNetworkException(e);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new AssertionError(e);
|
||||
} catch (KeyManagementException e) {
|
||||
throw new AssertionError(e);
|
||||
} catch (MalformedURLException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -19,14 +19,12 @@ package org.thoughtcrime.securesms;
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
|
||||
import com.path.android.jobqueue.JobManager;
|
||||
import com.path.android.jobqueue.config.Configuration;
|
||||
|
||||
import org.thoughtcrime.securesms.crypto.PRNGFixes;
|
||||
import org.thoughtcrime.securesms.jobs.ContextInjector;
|
||||
import org.thoughtcrime.securesms.jobs.EncryptingJobSerializer;
|
||||
import org.thoughtcrime.securesms.jobs.GcmRefreshJob;
|
||||
import org.thoughtcrime.securesms.jobs.JobLogger;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.whispersystems.jobqueue.JobManager;
|
||||
import org.whispersystems.jobqueue.requirements.NetworkRequirementProvider;
|
||||
|
||||
/**
|
||||
* Will be called once when the TextSecure process is created.
|
||||
@ -60,20 +58,16 @@ public class ApplicationContext extends Application {
|
||||
}
|
||||
|
||||
private void initializeJobManager() {
|
||||
Configuration configuration = new Configuration.Builder(this)
|
||||
.minConsumerCount(1)
|
||||
.injector(new ContextInjector(this))
|
||||
.customLogger(new JobLogger())
|
||||
.build();
|
||||
|
||||
this.jobManager = new JobManager(this, configuration);
|
||||
this.jobManager = new JobManager(this, "TextSecureJobs",
|
||||
new NetworkRequirementProvider(this),
|
||||
new EncryptingJobSerializer(this), 5);
|
||||
}
|
||||
|
||||
private void initializeGcmCheck() {
|
||||
if (TextSecurePreferences.isPushRegistered(this) &&
|
||||
TextSecurePreferences.getGcmRegistrationId(this) == null)
|
||||
{
|
||||
this.jobManager.addJob(new GcmRefreshJob());
|
||||
this.jobManager.add(new GcmRefreshJob(this));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,12 +6,12 @@ import android.content.Intent;
|
||||
import android.util.Log;
|
||||
|
||||
import com.google.android.gms.gcm.GoogleCloudMessaging;
|
||||
import com.path.android.jobqueue.JobManager;
|
||||
|
||||
import org.thoughtcrime.securesms.ApplicationContext;
|
||||
import org.thoughtcrime.securesms.jobs.DeliveryReceiptJob;
|
||||
import org.thoughtcrime.securesms.service.SendReceiveService;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.whispersystems.jobqueue.JobManager;
|
||||
import org.whispersystems.libaxolotl.InvalidVersionException;
|
||||
import org.whispersystems.textsecure.directory.Directory;
|
||||
import org.whispersystems.textsecure.directory.NotInDirectoryException;
|
||||
@ -68,8 +68,9 @@ public class GcmBroadcastReceiver extends BroadcastReceiver {
|
||||
|
||||
if (!message.isReceipt()) {
|
||||
JobManager jobManager = ApplicationContext.getInstance(context).getJobManager();
|
||||
jobManager.addJob(new DeliveryReceiptJob(message.getSource(), message.getTimestampMillis(),
|
||||
message.getRelay()));
|
||||
jobManager.add(new DeliveryReceiptJob(context, message.getSource(),
|
||||
message.getTimestampMillis(),
|
||||
message.getRelay()));
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Log.w(TAG, e);
|
||||
|
@ -1,22 +0,0 @@
|
||||
package org.thoughtcrime.securesms.jobs;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.path.android.jobqueue.BaseJob;
|
||||
import com.path.android.jobqueue.di.DependencyInjector;
|
||||
|
||||
public class ContextInjector implements DependencyInjector {
|
||||
|
||||
private final Context context;
|
||||
|
||||
public ContextInjector(Context context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void inject(BaseJob job) {
|
||||
if (job instanceof ContextJob) {
|
||||
((ContextJob)job).setContext(context);
|
||||
}
|
||||
}
|
||||
}
|
@ -2,15 +2,17 @@ package org.thoughtcrime.securesms.jobs;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.path.android.jobqueue.Job;
|
||||
import com.path.android.jobqueue.Params;
|
||||
import org.whispersystems.jobqueue.Job;
|
||||
import org.whispersystems.jobqueue.JobParameters;
|
||||
import org.whispersystems.jobqueue.dependencies.ContextDependent;
|
||||
|
||||
public abstract class ContextJob extends Job {
|
||||
public abstract class ContextJob extends Job implements ContextDependent {
|
||||
|
||||
transient protected Context context;
|
||||
protected transient Context context;
|
||||
|
||||
protected ContextJob(Params params) {
|
||||
super(params);
|
||||
protected ContextJob(Context context, JobParameters parameters) {
|
||||
super(parameters);
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
public void setContext(Context context) {
|
||||
|
@ -1,10 +1,11 @@
|
||||
package org.thoughtcrime.securesms.jobs;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
import com.path.android.jobqueue.Params;
|
||||
|
||||
import org.thoughtcrime.securesms.push.PushServiceSocketFactory;
|
||||
import org.whispersystems.jobqueue.JobParameters;
|
||||
import org.whispersystems.jobqueue.requirements.NetworkRequirement;
|
||||
import org.whispersystems.textsecure.push.PushServiceSocket;
|
||||
import org.whispersystems.textsecure.push.exceptions.NonSuccessfulResponseCodeException;
|
||||
import org.whispersystems.textsecure.push.exceptions.PushNetworkException;
|
||||
@ -17,8 +18,12 @@ public class DeliveryReceiptJob extends ContextJob {
|
||||
private final long timestamp;
|
||||
private final String relay;
|
||||
|
||||
public DeliveryReceiptJob(String destination, long timestamp, String relay) {
|
||||
super(new Params(Priorities.HIGH).requireNetwork().persist());
|
||||
public DeliveryReceiptJob(Context context, String destination, long timestamp, String relay) {
|
||||
super(context, JobParameters.newBuilder()
|
||||
.withRequirement(new NetworkRequirement(context))
|
||||
.withPersistence()
|
||||
.withRetryCount(50)
|
||||
.create());
|
||||
|
||||
this.destination = destination;
|
||||
this.timestamp = timestamp;
|
||||
@ -36,21 +41,16 @@ public class DeliveryReceiptJob extends ContextJob {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCancel() {
|
||||
public void onCanceled() {
|
||||
Log.w(TAG, "Failed to send receipt after retry exhausted!");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean shouldReRunOnThrowable(Throwable throwable) {
|
||||
public boolean onShouldRetry(Throwable throwable) {
|
||||
Log.w(TAG, throwable);
|
||||
if (throwable instanceof NonSuccessfulResponseCodeException) return false;
|
||||
if (throwable instanceof PushNetworkException) return true;
|
||||
if (throwable instanceof PushNetworkException) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getRetryLimit() {
|
||||
return 50;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,57 @@
|
||||
package org.thoughtcrime.securesms.jobs;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import org.thoughtcrime.securesms.util.ParcelUtil;
|
||||
import org.whispersystems.jobqueue.EncryptionKeys;
|
||||
import org.whispersystems.jobqueue.Job;
|
||||
import org.whispersystems.jobqueue.persistence.JavaJobSerializer;
|
||||
import org.whispersystems.jobqueue.persistence.JobSerializer;
|
||||
import org.whispersystems.libaxolotl.InvalidMessageException;
|
||||
import org.whispersystems.textsecure.crypto.MasterCipher;
|
||||
import org.whispersystems.textsecure.crypto.MasterSecret;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class EncryptingJobSerializer implements JobSerializer {
|
||||
|
||||
private final JavaJobSerializer delegate;
|
||||
|
||||
public EncryptingJobSerializer(Context context) {
|
||||
this.delegate = new JavaJobSerializer(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String serialize(Job job) throws IOException {
|
||||
String plaintext = delegate.serialize(job);
|
||||
|
||||
if (job.getEncryptionKeys() != null) {
|
||||
MasterSecret masterSecret = ParcelUtil.deserialize(job.getEncryptionKeys().getEncoded(),
|
||||
MasterSecret.CREATOR);
|
||||
MasterCipher masterCipher = new MasterCipher(masterSecret);
|
||||
|
||||
return masterCipher.encryptBody(plaintext);
|
||||
} else {
|
||||
return plaintext;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Job deserialize(EncryptionKeys keys, boolean encrypted, String serialized) throws IOException {
|
||||
try {
|
||||
String plaintext;
|
||||
|
||||
if (encrypted) {
|
||||
MasterSecret masterSecret = ParcelUtil.deserialize(keys.getEncoded(), MasterSecret.CREATOR);
|
||||
MasterCipher masterCipher = new MasterCipher(masterSecret);
|
||||
plaintext = masterCipher.decryptBody(serialized);
|
||||
} else {
|
||||
plaintext = serialized;
|
||||
}
|
||||
|
||||
return delegate.deserialize(keys, encrypted, plaintext);
|
||||
} catch (InvalidMessageException e) {
|
||||
throw new IOException(e);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,19 +1,19 @@
|
||||
package org.thoughtcrime.securesms.jobs;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.google.android.gms.common.ConnectionResult;
|
||||
import com.google.android.gms.common.GooglePlayServicesUtil;
|
||||
import com.google.android.gms.gcm.GoogleCloudMessaging;
|
||||
import com.path.android.jobqueue.Params;
|
||||
|
||||
import org.thoughtcrime.securesms.push.PushServiceSocketFactory;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.whispersystems.jobqueue.JobParameters;
|
||||
import org.whispersystems.jobqueue.requirements.NetworkRequirement;
|
||||
import org.whispersystems.textsecure.push.PushServiceSocket;
|
||||
import org.whispersystems.textsecure.push.exceptions.MismatchedDevicesException;
|
||||
import org.whispersystems.textsecure.push.exceptions.NonSuccessfulResponseCodeException;
|
||||
import org.whispersystems.textsecure.push.exceptions.PushNetworkException;
|
||||
|
||||
public class GcmRefreshJob extends ContextJob {
|
||||
|
||||
@ -21,8 +21,8 @@ public class GcmRefreshJob extends ContextJob {
|
||||
|
||||
public static final String REGISTRATION_ID = "312334754206";
|
||||
|
||||
public GcmRefreshJob() {
|
||||
super(new Params(Priorities.NORMAL).requireNetwork());
|
||||
public GcmRefreshJob(Context context) {
|
||||
super(context, JobParameters.newBuilder().withRequirement(new NetworkRequirement(context)).create());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -49,13 +49,14 @@ public class GcmRefreshJob extends ContextJob {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCancel() {
|
||||
public void onCanceled() {
|
||||
Log.w(TAG, "GCM reregistration failed after retry attempt exhaustion!");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean shouldReRunOnThrowable(Throwable throwable) {
|
||||
public boolean onShouldRetry(Throwable throwable) {
|
||||
if (throwable instanceof NonSuccessfulResponseCodeException) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,27 +0,0 @@
|
||||
package org.thoughtcrime.securesms.jobs;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import com.path.android.jobqueue.log.CustomLogger;
|
||||
|
||||
public class JobLogger implements CustomLogger {
|
||||
@Override
|
||||
public boolean isDebugEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void d(String text, Object... args) {
|
||||
Log.w("JobManager", String.format(text, args));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void e(Throwable t, String text, Object... args) {
|
||||
Log.w("JobManager", String.format(text, args), t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void e(String text, Object... args) {
|
||||
Log.w("JobManager", String.format(text, args));
|
||||
}
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
package org.thoughtcrime.securesms.jobs;
|
||||
|
||||
public class Priorities {
|
||||
|
||||
public static final int NORMAL = 500;
|
||||
public static final int HIGH = 1000;
|
||||
|
||||
}
|
28
src/org/thoughtcrime/securesms/util/ParcelUtil.java
Normal file
28
src/org/thoughtcrime/securesms/util/ParcelUtil.java
Normal file
@ -0,0 +1,28 @@
|
||||
package org.thoughtcrime.securesms.util;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
public class ParcelUtil {
|
||||
|
||||
public static byte[] serialize(Parcelable parceable) {
|
||||
Parcel parcel = Parcel.obtain();
|
||||
parceable.writeToParcel(parcel, 0);
|
||||
byte[] bytes = parcel.marshall();
|
||||
parcel.recycle();
|
||||
return bytes;
|
||||
}
|
||||
|
||||
public static Parcel deserialize(byte[] bytes) {
|
||||
Parcel parcel = Parcel.obtain();
|
||||
parcel.unmarshall(bytes, 0, bytes.length);
|
||||
parcel.setDataPosition(0);
|
||||
return parcel;
|
||||
}
|
||||
|
||||
public static <T> T deserialize(byte[] bytes, Parcelable.Creator<T> creator) {
|
||||
Parcel parcel = deserialize(bytes);
|
||||
return creator.createFromParcel(parcel);
|
||||
}
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user