Skip to content

Commit

Permalink
Switch to using our own JobManager.
Browse files Browse the repository at this point in the history
// FREEBIE
  • Loading branch information
moxie0 committed Oct 21, 2014
1 parent 73d896f commit b308996
Show file tree
Hide file tree
Showing 12 changed files with 183 additions and 151 deletions.
8 changes: 3 additions & 5 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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'
]
}

Expand Down
104 changes: 56 additions & 48 deletions library/src/org/whispersystems/textsecure/push/PushServiceSocket.java
Original file line number Diff line number Diff line change
Expand Up @@ -416,63 +416,58 @@ private String makeRequest(String urlFragment, String method, String body)
private HttpURLConnection makeBaseRequest(String urlFragment, String method, String body)
throws NonSuccessfulResponseCodeException, PushNetworkException
{
try {
HttpURLConnection connection = getConnection(urlFragment, method);

if (body != null) {
connection.setDoOutput(true);
}

connection.connect();
HttpURLConnection connection = getConnection(urlFragment, method, body);
int responseCode;
String responseMessage;
String response;

if (body != null) {
Log.w("PushServiceSocket", method + " -- " + body);
OutputStream out = connection.getOutputStream();
out.write(body.getBytes());
out.close();
}
try {
responseCode = connection.getResponseCode();
responseMessage = connection.getResponseMessage();
} catch (IOException ioe) {
throw new PushNetworkException(ioe);
}

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);
Expand All @@ -481,11 +476,11 @@ private HttpURLConnection getConnection(String urlFragment, String method) throw
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);
Expand All @@ -495,13 +490,26 @@ private HttpURLConnection getConnection(String urlFragment, String method) throw
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);
}
}

Expand Down
20 changes: 7 additions & 13 deletions src/org/thoughtcrime/securesms/ApplicationContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,12 @@
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.
Expand Down Expand Up @@ -60,20 +58,16 @@ private void initializeRandomNumberFix() {
}

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));
}
}

Expand Down
7 changes: 4 additions & 3 deletions src/org/thoughtcrime/securesms/gcm/GcmBroadcastReceiver.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@
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;
Expand Down Expand Up @@ -68,8 +68,9 @@ private void handleReceivedMessage(Context context, String data) {

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);
Expand Down
22 changes: 0 additions & 22 deletions src/org/thoughtcrime/securesms/jobs/ContextInjector.java

This file was deleted.

14 changes: 8 additions & 6 deletions src/org/thoughtcrime/securesms/jobs/ContextJob.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,17 @@

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) {
Expand Down
24 changes: 12 additions & 12 deletions src/org/thoughtcrime/securesms/jobs/DeliveryReceiptJob.java
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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;
Expand All @@ -36,21 +41,16 @@ public void onRun() throws Throwable {
}

@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;
}
}
57 changes: 57 additions & 0 deletions src/org/thoughtcrime/securesms/jobs/EncryptingJobSerializer.java
Original file line number Diff line number Diff line change
@@ -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);
}
}
}

0 comments on commit b308996

Please sign in to comment.