130 lines
5.3 KiB
Java
130 lines
5.3 KiB
Java
package org.sufficientlysecure.keychain.keysync;
|
|
|
|
|
|
import java.util.concurrent.atomic.AtomicBoolean;
|
|
|
|
import android.app.NotificationManager;
|
|
import android.content.Context;
|
|
|
|
import androidx.annotation.NonNull;
|
|
import androidx.core.app.NotificationCompat;
|
|
import androidx.core.app.NotificationCompat.Builder;
|
|
import androidx.work.Worker;
|
|
import androidx.work.WorkerParameters;
|
|
import org.sufficientlysecure.keychain.Constants.NotificationIds;
|
|
import org.sufficientlysecure.keychain.NotificationChannelManager;
|
|
import org.sufficientlysecure.keychain.R;
|
|
import org.sufficientlysecure.keychain.daos.KeyWritableRepository;
|
|
import org.sufficientlysecure.keychain.network.orbot.OrbotHelper;
|
|
import org.sufficientlysecure.keychain.operations.KeySyncOperation;
|
|
import org.sufficientlysecure.keychain.operations.KeySyncParcel;
|
|
import org.sufficientlysecure.keychain.operations.results.ImportKeyResult;
|
|
import org.sufficientlysecure.keychain.pgp.Progressable;
|
|
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
|
|
import org.sufficientlysecure.keychain.ui.OrbotRequiredDialogActivity;
|
|
import org.sufficientlysecure.keychain.util.ResourceUtils;
|
|
import timber.log.Timber;
|
|
|
|
|
|
public class KeyserverSyncWorker extends Worker {
|
|
private AtomicBoolean cancellationSignal = new AtomicBoolean(false);
|
|
|
|
public KeyserverSyncWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
|
|
super(context, workerParams);
|
|
}
|
|
|
|
@NonNull
|
|
@Override
|
|
public Result doWork() {
|
|
KeyWritableRepository keyWritableRepository = KeyWritableRepository.create(getApplicationContext());
|
|
|
|
Timber.d("Starting key sync…");
|
|
Progressable notificationProgressable = notificationShowForProgress();
|
|
KeySyncOperation keySync = new KeySyncOperation(getApplicationContext(), keyWritableRepository, notificationProgressable, cancellationSignal);
|
|
ImportKeyResult result = keySync.execute(KeySyncParcel.createRefreshOutdated(), CryptoInputParcel.createCryptoInputParcel());
|
|
return handleUpdateResult(result);
|
|
}
|
|
|
|
/**
|
|
* Since we're returning START_REDELIVER_INTENT in onStartCommand, we need to remember to call
|
|
* stopSelf(int) to prevent the Intent from being redelivered if our work is already done
|
|
*
|
|
* @param result
|
|
* result of keyserver sync
|
|
*/
|
|
private Result handleUpdateResult(ImportKeyResult result) {
|
|
if (result.isPending()) {
|
|
Timber.d("Orbot required for sync but not running, attempting to start");
|
|
// result is pending due to Orbot not being started
|
|
// try to start it silently, if disabled show notifications
|
|
new OrbotHelper.SilentStartManager() {
|
|
@Override
|
|
protected void onOrbotStarted() {
|
|
}
|
|
|
|
@Override
|
|
protected void onSilentStartDisabled() {
|
|
OrbotRequiredDialogActivity.showOrbotRequiredNotification(getApplicationContext());
|
|
}
|
|
}.startOrbotAndListen(getApplicationContext(), false);
|
|
return Result.retry();
|
|
} else if (isStopped()) {
|
|
Timber.d("Keyserver sync cancelled");
|
|
return Result.failure();
|
|
} else {
|
|
Timber.d("Keyserver sync completed: Updated: %d, Failed: %d", result.mUpdatedKeys, result.mBadKeys);
|
|
return Result.success();
|
|
}
|
|
}
|
|
|
|
private Progressable notificationShowForProgress() {
|
|
final Context context = getApplicationContext();
|
|
NotificationManager notificationManager =
|
|
(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
|
|
if (notificationManager == null) {
|
|
return null;
|
|
}
|
|
|
|
NotificationChannelManager.getInstance(context).createNotificationChannelsIfNecessary();
|
|
|
|
NotificationCompat.Builder builder = new Builder(context, NotificationChannelManager.KEYSERVER_SYNC)
|
|
.setSmallIcon(R.drawable.ic_stat_notify_24dp)
|
|
.setLargeIcon(ResourceUtils.getDrawableAsNotificationBitmap(context, R.mipmap.ic_launcher))
|
|
.setContentTitle(context.getString(R.string.notify_title_keysync))
|
|
.setPriority(NotificationCompat.PRIORITY_MIN)
|
|
.setTimeoutAfter(5000)
|
|
.setVibrate(null)
|
|
.setSound(null)
|
|
.setProgress(0, 0, true);
|
|
|
|
return new Progressable() {
|
|
@Override
|
|
public void setProgress(Integer ignored, int current, int total) {
|
|
if (total == 0) {
|
|
notificationManager.cancel(NotificationIds.KEYSERVER_SYNC);
|
|
return;
|
|
}
|
|
|
|
builder.setProgress(total, current, false);
|
|
if (current == total) {
|
|
builder.setContentTitle(context.getString(R.string.notify_title_keysync_finished, total));
|
|
builder.setContentText(null);
|
|
} else {
|
|
builder.setContentText(context.getString(R.string.notify_content_keysync, current, total));
|
|
}
|
|
notificationManager.notify(NotificationIds.KEYSERVER_SYNC, builder.build());
|
|
}
|
|
|
|
@Override
|
|
public void setPreventCancel() {
|
|
}
|
|
};
|
|
}
|
|
|
|
@Override
|
|
public void onStopped() {
|
|
super.onStopped();
|
|
cancellationSignal.set(true);
|
|
}
|
|
}
|