Add an automatic session reset interval.

fork-5.53.8
Greyson Parrelli 2021-01-16 14:17:32 -05:00
rodzic 2c1c6fab35
commit a2dc781840
5 zmienionych plików z 101 dodań i 8 usunięć

Wyświetl plik

@ -13,6 +13,7 @@ import com.annimon.stream.Stream;
import com.google.protobuf.ByteString;
import com.google.protobuf.InvalidProtocolBufferException;
import net.sqlcipher.SQLException;
import net.sqlcipher.database.SQLiteConstraintException;
import org.signal.core.util.logging.Log;
@ -28,6 +29,7 @@ import org.thoughtcrime.securesms.database.IdentityDatabase.IdentityRecord;
import org.thoughtcrime.securesms.database.IdentityDatabase.VerifiedStatus;
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper;
import org.thoughtcrime.securesms.database.model.ThreadRecord;
import org.thoughtcrime.securesms.database.model.databaseprotos.DeviceLastResetTime;
import org.thoughtcrime.securesms.database.model.databaseprotos.ProfileKeyCredentialColumnData;
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
import org.thoughtcrime.securesms.groups.GroupId;
@ -128,6 +130,7 @@ public class RecipientDatabase extends Database {
private static final String MENTION_SETTING = "mention_setting";
private static final String STORAGE_PROTO = "storage_proto";
private static final String LAST_GV1_MIGRATE_REMINDER = "last_gv1_migrate_reminder";
private static final String LAST_SESSION_RESET = "last_session_reset";
public static final String SEARCH_PROFILE_NAME = "search_signal_profile";
private static final String SORT_NAME = "sort_name";
@ -346,7 +349,8 @@ public class RecipientDatabase extends Database {
MENTION_SETTING + " INTEGER DEFAULT " + MentionSetting.ALWAYS_NOTIFY.getId() + ", " +
STORAGE_PROTO + " TEXT DEFAULT NULL, " +
CAPABILITIES + " INTEGER DEFAULT 0, " +
LAST_GV1_MIGRATE_REMINDER + " INTEGER DEFAULT 0);";
LAST_GV1_MIGRATE_REMINDER + " INTEGER DEFAULT 0, " +
LAST_SESSION_RESET + " BLOB DEFAULT NULL);";
private static final String INSIGHTS_INVITEE_LIST = "SELECT " + TABLE_NAME + "." + ID +
" FROM " + TABLE_NAME +
@ -1512,6 +1516,30 @@ public class RecipientDatabase extends Database {
return 0;
}
public void setLastSessionResetTime(@NonNull RecipientId id, DeviceLastResetTime lastResetTime) {
ContentValues values = new ContentValues(1);
values.put(LAST_SESSION_RESET, lastResetTime.toByteArray());
update(id, values);
}
public @NonNull DeviceLastResetTime getLastSessionResetTimes(@NonNull RecipientId id) {
SQLiteDatabase db = databaseHelper.getReadableDatabase();
try (Cursor cursor = db.query(TABLE_NAME, new String[] {LAST_SESSION_RESET}, ID_WHERE, SqlUtil.buildArgs(id), null, null, null)) {
if (cursor.moveToFirst()) {
try {
return DeviceLastResetTime.parseFrom(CursorUtil.requireBlob(cursor, LAST_SESSION_RESET));
} catch (InvalidProtocolBufferException | SQLException e) {
Log.w(TAG, e);
return DeviceLastResetTime.newBuilder().build();
}
}
}
return DeviceLastResetTime.newBuilder().build();
}
public void setCapabilities(@NonNull RecipientId id, @NonNull SignalServiceProfile.Capabilities capabilities) {
long value = 0;

Wyświetl plik

@ -168,8 +168,9 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper implements SignalDatab
private static final int CLEAN_UP_GV1_IDS = 84;
private static final int GV1_MIGRATION_REFACTOR = 85;
private static final int CLEAR_PROFILE_KEY_CREDENTIALS = 86;
private static final int LAST_RESET_SESSION_TIME = 87;
private static final int DATABASE_VERSION = 86;
private static final int DATABASE_VERSION = 87;
private static final String DATABASE_NAME = "signal.db";
private final Context context;
@ -1241,6 +1242,10 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper implements SignalDatab
Log.i(TAG, "Cleared profile key credentials for " + count + " rows");
}
if (oldVersion < LAST_RESET_SESSION_TIME) {
db.execSQL("ALTER TABLE recipient ADD COLUMN last_session_reset BLOB DEFAULT NULL");
}
db.setTransactionSuccessful();
} finally {
db.endTransaction();

Wyświetl plik

@ -7,6 +7,8 @@ import org.thoughtcrime.securesms.crypto.SessionUtil;
import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.MessageDatabase;
import org.thoughtcrime.securesms.database.RecipientDatabase;
import org.thoughtcrime.securesms.database.model.databaseprotos.DeviceLastResetTime;
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
import org.thoughtcrime.securesms.jobmanager.Data;
import org.thoughtcrime.securesms.jobmanager.Job;
@ -23,6 +25,7 @@ import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException;
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
/**
* - Archives the session associated with the specified device
@ -83,18 +86,35 @@ public class AutomaticSessionResetJob extends BaseJob {
@Override
protected void onRun() throws Exception {
SessionUtil.archiveSession(context, recipientId, deviceId);
insertLocalMessage();
if (FeatureFlags.automaticSessionReset()) {
SessionUtil.archiveSession(context, recipientId, deviceId);
insertLocalMessage();
sendNullMessage();
long resetInterval = TimeUnit.SECONDS.toMillis(FeatureFlags.automaticSessionResetIntervalSeconds());
DeviceLastResetTime resetTimes = DatabaseFactory.getRecipientDatabase(context).getLastSessionResetTimes(recipientId);
long timeSinceLastReset = System.currentTimeMillis() - getLastResetTime(resetTimes, deviceId);
Log.i(TAG, "DeviceId: " + deviceId + ", Reset interval: " + resetInterval + ", Time since last reset: " + timeSinceLastReset);
if (timeSinceLastReset > resetInterval) {
Log.i(TAG, "We're good! Sending a null message.");
DatabaseFactory.getRecipientDatabase(context).setLastSessionResetTime(recipientId, setLastResetTime(resetTimes, deviceId, System.currentTimeMillis()));
Log.i(TAG, "Marked last reset time: " + System.currentTimeMillis());
sendNullMessage();
Log.i(TAG, "Successfully sent!");
} else {
Log.w(TAG, "Too soon! Time since last reset: " + timeSinceLastReset);
}
} else {
insertLocalMessage();
Log.w(TAG, "Automatic session reset send disabled!");
}
}
@Override
protected boolean onShouldRetry(@NonNull Exception e) {
return e instanceof RetryLaterException;
return false;
}
@Override
@ -119,6 +139,29 @@ public class AutomaticSessionResetJob extends BaseJob {
}
}
private long getLastResetTime(@NonNull DeviceLastResetTime resetTimes, int deviceId) {
for (DeviceLastResetTime.Pair pair : resetTimes.getResetTimeList()) {
if (pair.getDeviceId() == deviceId) {
return pair.getLastResetTime();
}
}
return 0;
}
private @NonNull DeviceLastResetTime setLastResetTime(@NonNull DeviceLastResetTime resetTimes, int deviceId, long time) {
DeviceLastResetTime.Builder builder = DeviceLastResetTime.newBuilder();
for (DeviceLastResetTime.Pair pair : resetTimes.getResetTimeList()) {
if (pair.getDeviceId() != deviceId) {
builder.addResetTime(pair);
}
}
builder.addResetTime(DeviceLastResetTime.Pair.newBuilder().setDeviceId(deviceId).setLastResetTime(time));
return builder.build();
}
public static final class Factory implements Job.Factory<AutomaticSessionResetJob> {
@Override
public @NonNull AutomaticSessionResetJob create(@NonNull Parameters parameters, @NonNull Data data) {

Wyświetl plik

@ -67,7 +67,8 @@ public final class FeatureFlags {
private static final String SEND_VIEWED_RECEIPTS = "android.sendViewedReceipts";
private static final String CUSTOM_VIDEO_MUXER = "android.customVideoMuxer";
private static final String CDS_REFRESH_INTERVAL = "cds.syncInterval.seconds";
private static final String AUTOMATIC_SESSION_RESET = "android.automaticSessionReset";
private static final String AUTOMATIC_SESSION_RESET = "android.automaticSessionReset.2";
private static final String AUTOMATIC_SESSION_INTERVAL = "android.automaticSessionResetInterval";
private static final String DEFAULT_MAX_BACKOFF = "android.defaultMaxBackoff";
/**
@ -94,6 +95,7 @@ public final class FeatureFlags {
CDS_REFRESH_INTERVAL,
GROUP_NAME_MAX_LENGTH,
AUTOMATIC_SESSION_RESET,
AUTOMATIC_SESSION_INTERVAL,
DEFAULT_MAX_BACKOFF
);
@ -130,6 +132,7 @@ public final class FeatureFlags {
CDS_REFRESH_INTERVAL,
GROUP_NAME_MAX_LENGTH,
AUTOMATIC_SESSION_RESET,
AUTOMATIC_SESSION_INTERVAL,
DEFAULT_MAX_BACKOFF
);
@ -296,6 +299,11 @@ public final class FeatureFlags {
return getBoolean(AUTOMATIC_SESSION_RESET, true);
}
/** How often we allow an automatic session reset. */
public static int automaticSessionResetIntervalSeconds() {
return getInteger(AUTOMATIC_SESSION_RESET, (int) TimeUnit.HOURS.toSeconds(1));
}
public static int getDefaultMaxBackoffSeconds() {
return getInteger(DEFAULT_MAX_BACKOFF, 60);
}

Wyświetl plik

@ -82,3 +82,12 @@ message ProfileKeyCredentialColumnData {
bytes profileKey = 1;
bytes profileKeyCredential = 2;
}
message DeviceLastResetTime {
message Pair {
int32 deviceId = 1;
int64 lastResetTime = 2;
}
repeated Pair resetTime = 1;
}