kopia lustrzana https://github.com/ryukoposting/Signal-Android
Add an automatic session reset interval.
rodzic
2c1c6fab35
commit
a2dc781840
|
@ -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;
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
Ładowanie…
Reference in New Issue