@@ -16,6 +16,7 @@ import com.google.common.collect.ImmutableList;
import org.jetbrains.annotations.NotNull;
+import java.util.ArrayList;
import java.util.List;
import eu.siacs.conversations.Config;
@@ -129,6 +130,23 @@ public class UnifiedPushDatabase extends SQLiteOpenHelper {
return null;
}
+ public List<PushTarget> deletePushTargets() {
+ final SQLiteDatabase sqLiteDatabase = getReadableDatabase();
+ final ImmutableList.Builder<PushTarget> builder = new ImmutableList.Builder<>();
+ try (final Cursor cursor = sqLiteDatabase.query("push",new String[]{"application","instance"},null,null,null,null,null)) {
+ if (cursor != null && cursor.moveToFirst()) {
+ builder.add(new PushTarget(
+ cursor.getString(cursor.getColumnIndexOrThrow("application")),
+ cursor.getString(cursor.getColumnIndexOrThrow("instance"))));
+ }
+ } catch (final Exception e) {
+ Log.d(Config.LOGTAG,"unable to retrieve push targets",e);
+ return builder.build();
+ }
+ sqLiteDatabase.delete("push",null,null);
+ return builder.build();
+ }
+
public boolean hasEndpoints(final UnifiedPushBroker.Transport transport) {
final SQLiteDatabase sqLiteDatabase = getReadableDatabase();
try (final Cursor cursor =
@@ -10,10 +10,18 @@ import android.os.Messenger;
import android.os.RemoteException;
import android.preference.PreferenceManager;
import android.util.Log;
+
+import androidx.annotation.NonNull;
+
import com.google.common.base.Optional;
import com.google.common.base.Strings;
import com.google.common.collect.Iterables;
import com.google.common.io.BaseEncoding;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.MoreExecutors;
+
import eu.siacs.conversations.Config;
import eu.siacs.conversations.R;
import eu.siacs.conversations.entities.Account;
@@ -239,6 +247,9 @@ public class UnifiedPushBroker {
public boolean reconfigurePushDistributor() {
final boolean enabled = getTransport().isPresent();
setUnifiedPushDistributorEnabled(enabled);
+ if (!enabled) {
+ unregisterCurrentPushTargets();
+ }
return enabled;
}
@@ -261,6 +272,43 @@ public class UnifiedPushBroker {
}
}
+ private void unregisterCurrentPushTargets() {
+ final var future = deletePushTargets();
+ Futures.addCallback(
+ future,
+ new FutureCallback<>() {
+ @Override
+ public void onSuccess(
+ final List<UnifiedPushDatabase.PushTarget> pushTargets) {
+ broadcastUnregistered(pushTargets);
+ }
+
+ @Override
+ public void onFailure(@NonNull Throwable throwable) {
+ Log.d(
+ Config.LOGTAG,
+ "could not delete endpoints after UnifiedPushDistributor was disabled");
+ }
+ },
+ MoreExecutors.directExecutor());
+ }
+
+ private ListenableFuture<List<UnifiedPushDatabase.PushTarget>> deletePushTargets() {
+ return Futures.submit(() -> UnifiedPushDatabase.getInstance(service).deletePushTargets(),SCHEDULER);
+ }
+
+ private void broadcastUnregistered(final List<UnifiedPushDatabase.PushTarget> pushTargets) {
+ for(final UnifiedPushDatabase.PushTarget pushTarget : pushTargets) {
+ Log.d(Config.LOGTAG,"sending unregistered to "+pushTarget);
+ broadcastUnregistered(pushTarget);
+ }
+ }
+
+ private void broadcastUnregistered(final UnifiedPushDatabase.PushTarget pushTarget) {
+ final var intent = unregisteredIntent(pushTarget);
+ service.sendBroadcast(intent);
+ }
+
public boolean processPushMessage(
final Account account, final Jid transport, final Element push) {
final String instance = push.getAttribute("instance");
@@ -355,6 +403,7 @@ public class UnifiedPushBroker {
updateIntent.putExtra("token", target.instance);
updateIntent.putExtra("bytesMessage", payload);
updateIntent.putExtra("message", new String(payload, StandardCharsets.UTF_8));
+ // TODO add distributor verification?
service.sendBroadcast(updateIntent);
}
@@ -379,6 +428,19 @@ public class UnifiedPushBroker {
return intent;
}
+ private Intent unregisteredIntent(final UnifiedPushDatabase.PushTarget pushTarget) {
+ final Intent intent = new Intent(UnifiedPushDistributor.ACTION_UNREGISTERED);
+ intent.setPackage(pushTarget.application);
+ intent.putExtra("token", pushTarget.instance);
+ final var distributorVerificationIntent = new Intent();
+ distributorVerificationIntent.setPackage(service.getPackageName());
+ final var pendingIntent =
+ PendingIntent.getBroadcast(
+ service, 0, distributorVerificationIntent, PendingIntent.FLAG_IMMUTABLE);
+ intent.putExtra("distributor", pendingIntent);
+ return intent;
+ }
+
public void rebroadcastEndpoint(final Messenger messenger, final String instance, final Transport transport) {
final UnifiedPushDatabase unifiedPushDatabase = UnifiedPushDatabase.getInstance(service);
final UnifiedPushDatabase.ApplicationEndpoint endpoint =
@@ -29,8 +29,15 @@ import eu.siacs.conversations.utils.Compatibility;
public class UnifiedPushDistributor extends BroadcastReceiver {
+ // distributor actions (these are actios used for connector->distributor broadcasts)
+ // we, the distributor, have a broadcast receiver listening for those actions
+
public static final String ACTION_REGISTER = "org.unifiedpush.android.distributor.REGISTER";
public static final String ACTION_UNREGISTER = "org.unifiedpush.android.distributor.UNREGISTER";
+
+
+ // connector actions (these are actions used for distributor->connector broadcasts)
+ public static final String ACTION_UNREGISTERED = "org.unifiedpush.android.connector.UNREGISTERED";
public static final String ACTION_BYTE_MESSAGE =
"org.unifiedpush.android.distributor.feature.BYTES_MESSAGE";
public static final String ACTION_REGISTRATION_FAILED =
@@ -172,6 +179,7 @@ public class UnifiedPushDistributor extends BroadcastReceiver {
if (unifiedPushDatabase.deleteInstance(instance)) {
quickLog(context, String.format("successfully unregistered token %s from UnifiedPushed (application requested unregister)", instance));
Log.d(Config.LOGTAG, "successfully removed " + instance + " from UnifiedPush");
+ // TODO send UNREGISTERED broadcast back to app?!
}
}