UP: add custom extensions for app<->distributor interaction
On registration the app can pass in a 'Messenger' to get a direct response instead of having to somehow wait for the broadcast receiver to fire. The app name can be passed as a pending intent which allows the distributor to validate the sender.
This commit is contained in:
parent
ca1ee4a565
commit
e3a121121b
|
@ -114,6 +114,8 @@
|
||||||
<action android:name="org.unifiedpush.android.distributor.REGISTER" />
|
<action android:name="org.unifiedpush.android.distributor.REGISTER" />
|
||||||
<action android:name="org.unifiedpush.android.distributor.UNREGISTER" />
|
<action android:name="org.unifiedpush.android.distributor.UNREGISTER" />
|
||||||
<action android:name="org.unifiedpush.android.distributor.feature.BYTES_MESSAGE" />
|
<action android:name="org.unifiedpush.android.distributor.feature.BYTES_MESSAGE" />
|
||||||
|
<action android:name="org.unifiedpush.android.distributor.feature.MESSENGER" />
|
||||||
|
<action android:name="org.unifiedpush.android.distributor.feature.APP_VALIDATION" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.PACKAGE_FULLY_REMOVED" />
|
<action android:name="android.intent.action.PACKAGE_FULLY_REMOVED" />
|
||||||
|
|
|
@ -4,6 +4,9 @@ import android.content.ComponentName;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
|
import android.os.Message;
|
||||||
|
import android.os.Messenger;
|
||||||
|
import android.os.RemoteException;
|
||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import com.google.common.base.Optional;
|
import com.google.common.base.Optional;
|
||||||
|
@ -62,7 +65,7 @@ public class UnifiedPushBroker {
|
||||||
Log.d(
|
Log.d(
|
||||||
Config.LOGTAG,
|
Config.LOGTAG,
|
||||||
account.getJid().asBareJid() + ": trigger endpoint renewal on bind");
|
account.getJid().asBareJid() + ": trigger endpoint renewal on bind");
|
||||||
renewUnifiedEndpoint(transportOptional.get());
|
renewUnifiedEndpoint(transportOptional.get(), null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -74,11 +77,15 @@ public class UnifiedPushBroker {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<Transport> renewUnifiedPushEndpoints() {
|
public Optional<Transport> renewUnifiedPushEndpoints() {
|
||||||
|
return renewUnifiedPushEndpoints(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<Transport> renewUnifiedPushEndpoints(final PushTargetMessenger pushTargetMessenger) {
|
||||||
final Optional<Transport> transportOptional = getTransport();
|
final Optional<Transport> transportOptional = getTransport();
|
||||||
if (transportOptional.isPresent()) {
|
if (transportOptional.isPresent()) {
|
||||||
final Transport transport = transportOptional.get();
|
final Transport transport = transportOptional.get();
|
||||||
if (transport.account.isEnabled()) {
|
if (transport.account.isEnabled()) {
|
||||||
renewUnifiedEndpoint(transportOptional.get());
|
renewUnifiedEndpoint(transportOptional.get(), pushTargetMessenger);
|
||||||
} else {
|
} else {
|
||||||
Log.d(Config.LOGTAG, "skipping UnifiedPush endpoint renewal. Account is disabled");
|
Log.d(Config.LOGTAG, "skipping UnifiedPush endpoint renewal. Account is disabled");
|
||||||
}
|
}
|
||||||
|
@ -88,7 +95,7 @@ public class UnifiedPushBroker {
|
||||||
return transportOptional;
|
return transportOptional;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void renewUnifiedEndpoint(final Transport transport) {
|
private void renewUnifiedEndpoint(final Transport transport, final PushTargetMessenger pushTargetMessenger) {
|
||||||
final Account account = transport.account;
|
final Account account = transport.account;
|
||||||
final UnifiedPushDatabase unifiedPushDatabase = UnifiedPushDatabase.getInstance(service);
|
final UnifiedPushDatabase unifiedPushDatabase = UnifiedPushDatabase.getInstance(service);
|
||||||
final List<UnifiedPushDatabase.PushTarget> renewals =
|
final List<UnifiedPushDatabase.PushTarget> renewals =
|
||||||
|
@ -114,16 +121,23 @@ public class UnifiedPushBroker {
|
||||||
final Element register = registration.addChild("register", Namespace.UNIFIED_PUSH);
|
final Element register = registration.addChild("register", Namespace.UNIFIED_PUSH);
|
||||||
register.setAttribute("application", hashedApplication);
|
register.setAttribute("application", hashedApplication);
|
||||||
register.setAttribute("instance", hashedInstance);
|
register.setAttribute("instance", hashedInstance);
|
||||||
|
final Messenger messenger;
|
||||||
|
if (pushTargetMessenger != null && renewal.equals(pushTargetMessenger.pushTarget)) {
|
||||||
|
messenger = pushTargetMessenger.messenger;
|
||||||
|
} else {
|
||||||
|
messenger = null;
|
||||||
|
}
|
||||||
this.service.sendIqPacket(
|
this.service.sendIqPacket(
|
||||||
account,
|
account,
|
||||||
registration,
|
registration,
|
||||||
(a, response) -> processRegistration(transport, renewal, response));
|
(a, response) -> processRegistration(transport, renewal, messenger, response));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void processRegistration(
|
private void processRegistration(
|
||||||
final Transport transport,
|
final Transport transport,
|
||||||
final UnifiedPushDatabase.PushTarget renewal,
|
final UnifiedPushDatabase.PushTarget renewal,
|
||||||
|
final Messenger messenger,
|
||||||
final IqPacket response) {
|
final IqPacket response) {
|
||||||
if (response.getType() == IqPacket.TYPE.RESULT) {
|
if (response.getType() == IqPacket.TYPE.RESULT) {
|
||||||
final Element registered = response.findChild("registered", Namespace.UNIFIED_PUSH);
|
final Element registered = response.findChild("registered", Namespace.UNIFIED_PUSH);
|
||||||
|
@ -142,7 +156,7 @@ public class UnifiedPushBroker {
|
||||||
Log.d(Config.LOGTAG, "could not parse expiration", e);
|
Log.d(Config.LOGTAG, "could not parse expiration", e);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
renewUnifiedPushEndpoint(transport, renewal, endpoint, expiration);
|
renewUnifiedPushEndpoint(transport, renewal, messenger, endpoint, expiration);
|
||||||
} else {
|
} else {
|
||||||
Log.d(Config.LOGTAG, "could not register UP endpoint " + response.getErrorCondition());
|
Log.d(Config.LOGTAG, "could not register UP endpoint " + response.getErrorCondition());
|
||||||
}
|
}
|
||||||
|
@ -151,6 +165,7 @@ public class UnifiedPushBroker {
|
||||||
private void renewUnifiedPushEndpoint(
|
private void renewUnifiedPushEndpoint(
|
||||||
final Transport transport,
|
final Transport transport,
|
||||||
final UnifiedPushDatabase.PushTarget renewal,
|
final UnifiedPushDatabase.PushTarget renewal,
|
||||||
|
final Messenger messenger,
|
||||||
final String endpoint,
|
final String endpoint,
|
||||||
final long expiration) {
|
final long expiration) {
|
||||||
Log.d(Config.LOGTAG, "registered endpoint " + endpoint + " expiration=" + expiration);
|
Log.d(Config.LOGTAG, "registered endpoint " + endpoint + " expiration=" + expiration);
|
||||||
|
@ -171,9 +186,24 @@ public class UnifiedPushBroker {
|
||||||
+ renewal.instance
|
+ renewal.instance
|
||||||
+ " was updated to "
|
+ " was updated to "
|
||||||
+ endpoint);
|
+ endpoint);
|
||||||
broadcastEndpoint(
|
final UnifiedPushDatabase.ApplicationEndpoint applicationEndpoint = new UnifiedPushDatabase.ApplicationEndpoint(renewal.application, endpoint);
|
||||||
renewal.instance,
|
sendEndpoint(messenger, renewal.instance, applicationEndpoint);
|
||||||
new UnifiedPushDatabase.ApplicationEndpoint(renewal.application, endpoint));
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void sendEndpoint(final Messenger messenger, String instance, final UnifiedPushDatabase.ApplicationEndpoint applicationEndpoint) {
|
||||||
|
if (messenger != null) {
|
||||||
|
Log.d(Config.LOGTAG,"using messenger instead of broadcast to communicate endpoint to "+applicationEndpoint.application);
|
||||||
|
final Message message = new Message();
|
||||||
|
message.obj = endpointIntent(instance, applicationEndpoint);
|
||||||
|
try {
|
||||||
|
messenger.send(message);
|
||||||
|
} catch (final RemoteException e) {
|
||||||
|
Log.d(Config.LOGTAG,"messenger failed. falling back to broadcast");
|
||||||
|
broadcastEndpoint(instance, applicationEndpoint);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
broadcastEndpoint(instance, applicationEndpoint);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -302,14 +332,19 @@ public class UnifiedPushBroker {
|
||||||
private void broadcastEndpoint(
|
private void broadcastEndpoint(
|
||||||
final String instance, final UnifiedPushDatabase.ApplicationEndpoint endpoint) {
|
final String instance, final UnifiedPushDatabase.ApplicationEndpoint endpoint) {
|
||||||
Log.d(Config.LOGTAG, "broadcasting endpoint to " + endpoint.application);
|
Log.d(Config.LOGTAG, "broadcasting endpoint to " + endpoint.application);
|
||||||
final Intent updateIntent = new Intent(UnifiedPushDistributor.ACTION_NEW_ENDPOINT);
|
final Intent updateIntent = endpointIntent(instance, endpoint);
|
||||||
updateIntent.setPackage(endpoint.application);
|
|
||||||
updateIntent.putExtra("token", instance);
|
|
||||||
updateIntent.putExtra("endpoint", endpoint.endpoint);
|
|
||||||
service.sendBroadcast(updateIntent);
|
service.sendBroadcast(updateIntent);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void rebroadcastEndpoint(final String instance, final Transport transport) {
|
private static Intent endpointIntent(final String instance, final UnifiedPushDatabase.ApplicationEndpoint endpoint) {
|
||||||
|
final Intent intent = new Intent(UnifiedPushDistributor.ACTION_NEW_ENDPOINT);
|
||||||
|
intent.setPackage(endpoint.application);
|
||||||
|
intent.putExtra("token", instance);
|
||||||
|
intent.putExtra("endpoint", endpoint.endpoint);
|
||||||
|
return intent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void rebroadcastEndpoint(final Messenger messenger, final String instance, final Transport transport) {
|
||||||
final UnifiedPushDatabase unifiedPushDatabase = UnifiedPushDatabase.getInstance(service);
|
final UnifiedPushDatabase unifiedPushDatabase = UnifiedPushDatabase.getInstance(service);
|
||||||
final UnifiedPushDatabase.ApplicationEndpoint endpoint =
|
final UnifiedPushDatabase.ApplicationEndpoint endpoint =
|
||||||
unifiedPushDatabase.getEndpoint(
|
unifiedPushDatabase.getEndpoint(
|
||||||
|
@ -317,7 +352,7 @@ public class UnifiedPushBroker {
|
||||||
transport.transport.toEscapedString(),
|
transport.transport.toEscapedString(),
|
||||||
instance);
|
instance);
|
||||||
if (endpoint != null) {
|
if (endpoint != null) {
|
||||||
broadcastEndpoint(instance, endpoint);
|
sendEndpoint(messenger, instance, endpoint);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -330,4 +365,14 @@ public class UnifiedPushBroker {
|
||||||
this.transport = transport;
|
this.transport = transport;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class PushTargetMessenger {
|
||||||
|
private final UnifiedPushDatabase.PushTarget pushTarget;
|
||||||
|
private final Messenger messenger;
|
||||||
|
|
||||||
|
public PushTargetMessenger(UnifiedPushDatabase.PushTarget pushTarget, Messenger messenger) {
|
||||||
|
this.pushTarget = pushTarget;
|
||||||
|
this.messenger = messenger;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
package eu.siacs.conversations.services;
|
package eu.siacs.conversations.services;
|
||||||
|
|
||||||
|
import android.app.PendingIntent;
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.pm.ResolveInfo;
|
import android.content.pm.ResolveInfo;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
import android.os.Messenger;
|
||||||
|
import android.os.Parcelable;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import com.google.common.base.Charsets;
|
import com.google.common.base.Charsets;
|
||||||
|
@ -46,12 +49,21 @@ public class UnifiedPushDistributor extends BroadcastReceiver {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final String action = intent.getAction();
|
final String action = intent.getAction();
|
||||||
final String application = intent.getStringExtra("application");
|
final String application;
|
||||||
|
final Parcelable appByPendingIntent = intent.getParcelableExtra("app");
|
||||||
|
if (appByPendingIntent instanceof PendingIntent) {
|
||||||
|
final PendingIntent pendingIntent = (PendingIntent) appByPendingIntent;
|
||||||
|
application = pendingIntent.getIntentSender().getCreatorPackage();
|
||||||
|
Log.d(Config.LOGTAG,"received application name via pending intent "+ application);
|
||||||
|
} else {
|
||||||
|
application = intent.getStringExtra("application");
|
||||||
|
}
|
||||||
|
final Parcelable messenger = intent.getParcelableExtra("messenger");
|
||||||
final String instance = intent.getStringExtra("token");
|
final String instance = intent.getStringExtra("token");
|
||||||
final List<String> features = intent.getStringArrayListExtra("features");
|
final List<String> features = intent.getStringArrayListExtra("features");
|
||||||
switch (Strings.nullToEmpty(action)) {
|
switch (Strings.nullToEmpty(action)) {
|
||||||
case ACTION_REGISTER:
|
case ACTION_REGISTER:
|
||||||
register(context, application, instance, features);
|
register(context, application, instance, features, messenger);
|
||||||
break;
|
break;
|
||||||
case ACTION_UNREGISTER:
|
case ACTION_UNREGISTER:
|
||||||
unregister(context, instance);
|
unregister(context, instance);
|
||||||
|
@ -69,7 +81,8 @@ public class UnifiedPushDistributor extends BroadcastReceiver {
|
||||||
final Context context,
|
final Context context,
|
||||||
final String application,
|
final String application,
|
||||||
final String instance,
|
final String instance,
|
||||||
final Collection<String> features) {
|
final Collection<String> features,
|
||||||
|
final Parcelable messenger) {
|
||||||
if (Strings.isNullOrEmpty(application) || Strings.isNullOrEmpty(instance)) {
|
if (Strings.isNullOrEmpty(application) || Strings.isNullOrEmpty(instance)) {
|
||||||
Log.w(Config.LOGTAG, "ignoring invalid UnifiedPush registration");
|
Log.w(Config.LOGTAG, "ignoring invalid UnifiedPush registration");
|
||||||
return;
|
return;
|
||||||
|
@ -92,6 +105,10 @@ public class UnifiedPushDistributor extends BroadcastReceiver {
|
||||||
final Intent serviceIntent = new Intent(context, XmppConnectionService.class);
|
final Intent serviceIntent = new Intent(context, XmppConnectionService.class);
|
||||||
serviceIntent.setAction(XmppConnectionService.ACTION_RENEW_UNIFIED_PUSH_ENDPOINTS);
|
serviceIntent.setAction(XmppConnectionService.ACTION_RENEW_UNIFIED_PUSH_ENDPOINTS);
|
||||||
serviceIntent.putExtra("instance", instance);
|
serviceIntent.putExtra("instance", instance);
|
||||||
|
serviceIntent.putExtra("application", application);
|
||||||
|
if (messenger instanceof Messenger) {
|
||||||
|
serviceIntent.putExtra("messenger", messenger);
|
||||||
|
}
|
||||||
Compatibility.startService(context, serviceIntent);
|
Compatibility.startService(context, serviceIntent);
|
||||||
} else {
|
} else {
|
||||||
Log.d(Config.LOGTAG, "not successful. sending error message back to application");
|
Log.d(Config.LOGTAG, "not successful. sending error message back to application");
|
||||||
|
|
|
@ -32,6 +32,8 @@ import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Environment;
|
import android.os.Environment;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
|
import android.os.Messenger;
|
||||||
|
import android.os.Parcelable;
|
||||||
import android.os.PowerManager;
|
import android.os.PowerManager;
|
||||||
import android.os.PowerManager.WakeLock;
|
import android.os.PowerManager.WakeLock;
|
||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
|
@ -815,9 +817,18 @@ public class XmppConnectionService extends Service {
|
||||||
break;
|
break;
|
||||||
case ACTION_RENEW_UNIFIED_PUSH_ENDPOINTS:
|
case ACTION_RENEW_UNIFIED_PUSH_ENDPOINTS:
|
||||||
final String instance = intent.getStringExtra("instance");
|
final String instance = intent.getStringExtra("instance");
|
||||||
final Optional<UnifiedPushBroker.Transport> transport = renewUnifiedPushEndpoints();
|
final String application = intent.getStringExtra("application");
|
||||||
|
final Messenger messenger = intent.getParcelableExtra("messenger");
|
||||||
|
final UnifiedPushBroker.PushTargetMessenger pushTargetMessenger;
|
||||||
|
if (messenger != null && application != null && instance != null) {
|
||||||
|
pushTargetMessenger = new UnifiedPushBroker.PushTargetMessenger(new UnifiedPushDatabase.PushTarget(application, instance),messenger);
|
||||||
|
Log.d(Config.LOGTAG,"found push target messenger");
|
||||||
|
} else {
|
||||||
|
pushTargetMessenger = null;
|
||||||
|
}
|
||||||
|
final Optional<UnifiedPushBroker.Transport> transport = renewUnifiedPushEndpoints(pushTargetMessenger);
|
||||||
if (instance != null && transport.isPresent()) {
|
if (instance != null && transport.isPresent()) {
|
||||||
unifiedPushBroker.rebroadcastEndpoint(instance, transport.get());
|
unifiedPushBroker.rebroadcastEndpoint(messenger, instance, transport.get());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ACTION_IDLE_PING:
|
case ACTION_IDLE_PING:
|
||||||
|
@ -2363,8 +2374,12 @@ public class XmppConnectionService extends Service {
|
||||||
return this.unifiedPushBroker.reconfigurePushDistributor();
|
return this.unifiedPushBroker.reconfigurePushDistributor();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Optional<UnifiedPushBroker.Transport> renewUnifiedPushEndpoints(final UnifiedPushBroker.PushTargetMessenger pushTargetMessenger) {
|
||||||
|
return this.unifiedPushBroker.renewUnifiedPushEndpoints(pushTargetMessenger);
|
||||||
|
}
|
||||||
|
|
||||||
public Optional<UnifiedPushBroker.Transport> renewUnifiedPushEndpoints() {
|
public Optional<UnifiedPushBroker.Transport> renewUnifiedPushEndpoints() {
|
||||||
return this.unifiedPushBroker.renewUnifiedPushEndpoints();
|
return this.unifiedPushBroker.renewUnifiedPushEndpoints(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void provisionAccount(final String address, final String password) {
|
private void provisionAccount(final String address, final String password) {
|
||||||
|
|
Loading…
Reference in a new issue