provide upgrade path for accounts with publish-options

Daniel Gultsch created

Change summary

src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java | 15 
src/main/java/eu/siacs/conversations/entities/Account.java              |  1 
src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java   | 10 
3 files changed, 23 insertions(+), 3 deletions(-)

Detailed changes

src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java 🔗

@@ -82,6 +82,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
 	private boolean pepBroken = false;
 
 	private AtomicBoolean ownPushPending = new AtomicBoolean(false);
+	private AtomicBoolean changeAccessMode = new AtomicBoolean(false);
 
 	@Override
 	public void onAdvancedStreamFeaturesAvailable(Account account) {
@@ -411,6 +412,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
 			if (Config.OMEMO_AUTO_EXPIRY != 0) {
 				needsPublishing |= deviceIds.removeAll(getExpiredDevices());
 			}
+			needsPublishing |= this.changeAccessMode.get();
 			for (Integer deviceId : deviceIds) {
 				SignalProtocolAddress ownDeviceAddress = new SignalProtocolAddress(jid.toBareJid().toPreppedString(), deviceId);
 				if (sessions.get(ownDeviceAddress) == null) {
@@ -533,6 +535,11 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
 						}
 					});
 				} else {
+					if (AxolotlService.this.changeAccessMode.compareAndSet(true,false)) {
+						Log.d(Config.LOGTAG,account.getJid().toBareJid()+": done changing access mode");
+						account.setOption(Account.OPTION_REQURIES_ACCESS_MODE_CHANGE,false);
+						mXmppConnectionService.databaseBackend.updateAccount(account);
+					}
 					ownPushPending.set(false);
 					if (packet.getType() == IqPacket.TYPE.ERROR) {
 						pepBroken = true;
@@ -586,6 +593,10 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
 			Log.d(Config.LOGTAG, getLogprefix(account) + "publishBundlesIfNeeded called, but PEP is broken. Ignoring... ");
 			return;
 		}
+		this.changeAccessMode.set(account.isOptionSet(Account.OPTION_REQURIES_ACCESS_MODE_CHANGE) && account.getXmppConnection().getFeatures().pepPublishOptions());
+		if (this.changeAccessMode.get()) {
+			Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": server gained publish-options capabilities. changing access model");
+		}
 		IqPacket packet = mXmppConnectionService.getIqGenerator().retrieveBundlesForDevice(account.getJid().toBareJid(), getOwnDeviceId());
 		mXmppConnectionService.sendIqPacket(account, packet, new OnIqPacketReceived() {
 			@Override
@@ -670,7 +681,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
 					}
 
 
-					if (changed) {
+					if (changed || changeAccessMode.get()) {
 						if (account.getPrivateKeyAlias() != null && Config.X509_VERIFICATION) {
 							mXmppConnectionService.publishDisplayName(account);
 							publishDeviceVerificationAndBundle(signedPreKeyRecord, preKeyRecords, announce, wipe);
@@ -728,7 +739,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
 							publishDeviceBundle(signedPreKeyRecord,preKeyRecords, announceAfter, wipe, false);
 						}
 					});
-				} if (packet.getType() == IqPacket.TYPE.RESULT) {
+				} else if (packet.getType() == IqPacket.TYPE.RESULT) {
 					Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Successfully published bundle. ");
 					if (wipe) {
 						wipeOtherPepDevices();

src/main/java/eu/siacs/conversations/entities/Account.java 🔗

@@ -57,6 +57,7 @@ public class Account extends AbstractEntity {
 	public static final int OPTION_REGISTER = 2;
 	public static final int OPTION_USECOMPRESSION = 3;
 	public static final int OPTION_MAGIC_CREATE = 4;
+	public static final int OPTION_REQURIES_ACCESS_MODE_CHANGE = 5;
 	public final HashSet<Pair<String, String>> inProgressDiscoFetches = new HashSet<>();
 
 	public boolean httpUploadAvailable(long filesize) {

src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java 🔗

@@ -61,7 +61,7 @@ public class DatabaseBackend extends SQLiteOpenHelper {
 	private static DatabaseBackend instance = null;
 
 	private static final String DATABASE_NAME = "history";
-	private static final int DATABASE_VERSION = 35;
+	private static final int DATABASE_VERSION = 36;
 
 	private static String CREATE_CONTATCS_STATEMENT = "create table "
 			+ Contact.TABLENAME + "(" + Contact.ACCOUNT + " TEXT, "
@@ -446,6 +446,14 @@ public class DatabaseBackend extends SQLiteOpenHelper {
 		if (oldVersion < 35 && newVersion >= 35) {
 			db.execSQL(CREATE_MESSAGE_CONVERSATION_INDEX);
 		}
+		if (oldVersion < 36 && newVersion >= 36) {
+			List<Account> accounts = getAccounts(db);
+			for (Account account : accounts) {
+				account.setOption(Account.OPTION_REQURIES_ACCESS_MODE_CHANGE,true);
+				db.update(Account.TABLENAME, account.getContentValues(), Account.UUID
+						+ "=?", new String[]{account.getUuid()});
+			}
+		}
 	}
 
 	private static ContentValues createFingerprintStatusContentValues(FingerprintStatus.Trust trust, boolean active) {