We have to make some changes, and it's gotten to the point where maintaining it as a separate library is more hassle than it's worth, especially with Google releasing WorkManager as the preferred job scheduling library.
125 lines
4.5 KiB
Java
125 lines
4.5 KiB
Java
package org.thoughtcrime.securesms.jobs;
|
|
|
|
import android.content.Context;
|
|
import android.util.Log;
|
|
|
|
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
|
import org.thoughtcrime.securesms.crypto.PreKeyUtil;
|
|
import org.thoughtcrime.securesms.dependencies.InjectableType;
|
|
import org.thoughtcrime.securesms.jobmanager.JobParameters;
|
|
import org.thoughtcrime.securesms.jobs.requirements.MasterSecretRequirement;
|
|
import org.whispersystems.libsignal.InvalidKeyIdException;
|
|
import org.whispersystems.libsignal.state.SignedPreKeyRecord;
|
|
import org.whispersystems.libsignal.state.SignedPreKeyStore;
|
|
import org.whispersystems.signalservice.api.SignalServiceAccountManager;
|
|
import org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResponseCodeException;
|
|
import org.whispersystems.signalservice.api.push.exceptions.PushNetworkException;
|
|
|
|
import java.io.IOException;
|
|
import java.util.Collections;
|
|
import java.util.Comparator;
|
|
import java.util.LinkedList;
|
|
import java.util.List;
|
|
import java.util.concurrent.TimeUnit;
|
|
|
|
import javax.inject.Inject;
|
|
|
|
import static org.thoughtcrime.securesms.dependencies.AxolotlStorageModule.SignedPreKeyStoreFactory;
|
|
|
|
public class CleanPreKeysJob extends MasterSecretJob implements InjectableType {
|
|
|
|
private static final String TAG = CleanPreKeysJob.class.getSimpleName();
|
|
|
|
private static final long ARCHIVE_AGE = TimeUnit.DAYS.toMillis(7);
|
|
|
|
@Inject transient SignalServiceAccountManager accountManager;
|
|
@Inject transient SignedPreKeyStoreFactory signedPreKeyStoreFactory;
|
|
|
|
public CleanPreKeysJob(Context context) {
|
|
super(context, JobParameters.newBuilder()
|
|
.withGroupId(CleanPreKeysJob.class.getSimpleName())
|
|
.withRequirement(new MasterSecretRequirement(context))
|
|
.withRetryCount(5)
|
|
.create());
|
|
}
|
|
|
|
@Override
|
|
public void onAdded() {
|
|
|
|
}
|
|
|
|
@Override
|
|
public void onRun(MasterSecret masterSecret) throws IOException {
|
|
try {
|
|
Log.w(TAG, "Cleaning prekeys...");
|
|
|
|
int activeSignedPreKeyId = PreKeyUtil.getActiveSignedPreKeyId(context);
|
|
SignedPreKeyStore signedPreKeyStore = signedPreKeyStoreFactory.create();
|
|
|
|
if (activeSignedPreKeyId < 0) return;
|
|
|
|
SignedPreKeyRecord currentRecord = signedPreKeyStore.loadSignedPreKey(activeSignedPreKeyId);
|
|
List<SignedPreKeyRecord> allRecords = signedPreKeyStore.loadSignedPreKeys();
|
|
LinkedList<SignedPreKeyRecord> oldRecords = removeRecordFrom(currentRecord, allRecords);
|
|
|
|
Collections.sort(oldRecords, new SignedPreKeySorter());
|
|
|
|
Log.w(TAG, "Active signed prekey: " + activeSignedPreKeyId);
|
|
Log.w(TAG, "Old signed prekey record count: " + oldRecords.size());
|
|
|
|
boolean foundAgedRecord = false;
|
|
|
|
for (SignedPreKeyRecord oldRecord : oldRecords) {
|
|
long archiveDuration = System.currentTimeMillis() - oldRecord.getTimestamp();
|
|
|
|
if (archiveDuration >= ARCHIVE_AGE) {
|
|
if (!foundAgedRecord) {
|
|
foundAgedRecord = true;
|
|
} else {
|
|
Log.w(TAG, "Removing signed prekey record: " + oldRecord.getId() + " with timestamp: " + oldRecord.getTimestamp());
|
|
signedPreKeyStore.removeSignedPreKey(oldRecord.getId());
|
|
}
|
|
}
|
|
}
|
|
} catch (InvalidKeyIdException e) {
|
|
Log.w(TAG, e);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public boolean onShouldRetryThrowable(Exception throwable) {
|
|
if (throwable instanceof NonSuccessfulResponseCodeException) return false;
|
|
if (throwable instanceof PushNetworkException) return true;
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public void onCanceled() {
|
|
Log.w(TAG, "Failed to execute clean signed prekeys task.");
|
|
}
|
|
|
|
private LinkedList<SignedPreKeyRecord> removeRecordFrom(SignedPreKeyRecord currentRecord,
|
|
List<SignedPreKeyRecord> records)
|
|
|
|
{
|
|
LinkedList<SignedPreKeyRecord> others = new LinkedList<>();
|
|
|
|
for (SignedPreKeyRecord record : records) {
|
|
if (record.getId() != currentRecord.getId()) {
|
|
others.add(record);
|
|
}
|
|
}
|
|
|
|
return others;
|
|
}
|
|
|
|
private static class SignedPreKeySorter implements Comparator<SignedPreKeyRecord> {
|
|
@Override
|
|
public int compare(SignedPreKeyRecord lhs, SignedPreKeyRecord rhs) {
|
|
if (lhs.getTimestamp() > rhs.getTimestamp()) return -1;
|
|
else if (lhs.getTimestamp() < rhs.getTimestamp()) return 1;
|
|
else return 0;
|
|
}
|
|
}
|
|
|
|
}
|