mirror of
https://github.com/signalapp/Signal-Android.git
synced 2025-12-22 20:18:36 +00:00
Allow syncing additional types of messages to linked devices.
This commit is contained in:
@@ -23,13 +23,18 @@ object ArchiveValidator {
|
|||||||
/**
|
/**
|
||||||
* Validates the provided [backupFile] that is encrypted with the provided [backupKey].
|
* Validates the provided [backupFile] that is encrypted with the provided [backupKey].
|
||||||
*/
|
*/
|
||||||
fun validate(backupFile: File, backupKey: MessageBackupKey): ValidationResult {
|
fun validate(backupFile: File, backupKey: MessageBackupKey, forTransfer: Boolean): ValidationResult {
|
||||||
return try {
|
return try {
|
||||||
val backupId = backupKey.deriveBackupId(SignalStore.account.requireAci())
|
val backupId = backupKey.deriveBackupId(SignalStore.account.requireAci())
|
||||||
val libSignalBackupKey = LibSignalBackupKey(backupKey.value)
|
val libSignalBackupKey = LibSignalBackupKey(backupKey.value)
|
||||||
val backupKey = LibSignalMessageBackupKey(libSignalBackupKey, backupId.value)
|
val backupKey = LibSignalMessageBackupKey(libSignalBackupKey, backupId.value)
|
||||||
|
|
||||||
MessageBackup.validate(backupKey, MessageBackup.Purpose.REMOTE_BACKUP, { backupFile.inputStream() }, backupFile.length())
|
MessageBackup.validate(
|
||||||
|
backupKey,
|
||||||
|
if (forTransfer) MessageBackup.Purpose.DEVICE_TRANSFER else MessageBackup.Purpose.REMOTE_BACKUP,
|
||||||
|
{ backupFile.inputStream() },
|
||||||
|
backupFile.length()
|
||||||
|
)
|
||||||
|
|
||||||
ValidationResult.Success
|
ValidationResult.Success
|
||||||
} catch (e: IOException) {
|
} catch (e: IOException) {
|
||||||
|
|||||||
@@ -460,6 +460,7 @@ object BackupRepository {
|
|||||||
plaintext: Boolean = false,
|
plaintext: Boolean = false,
|
||||||
currentTime: Long = System.currentTimeMillis(),
|
currentTime: Long = System.currentTimeMillis(),
|
||||||
mediaBackupEnabled: Boolean = SignalStore.backup.backsUpMedia,
|
mediaBackupEnabled: Boolean = SignalStore.backup.backsUpMedia,
|
||||||
|
forTransfer: Boolean = false,
|
||||||
progressEmitter: ExportProgressListener? = null,
|
progressEmitter: ExportProgressListener? = null,
|
||||||
cancellationSignal: () -> Boolean = { false },
|
cancellationSignal: () -> Boolean = { false },
|
||||||
exportExtras: ((SignalDatabase) -> Unit)? = null
|
exportExtras: ((SignalDatabase) -> Unit)? = null
|
||||||
@@ -481,6 +482,7 @@ object BackupRepository {
|
|||||||
writer = writer,
|
writer = writer,
|
||||||
progressEmitter = progressEmitter,
|
progressEmitter = progressEmitter,
|
||||||
mediaBackupEnabled = mediaBackupEnabled,
|
mediaBackupEnabled = mediaBackupEnabled,
|
||||||
|
forTransfer = forTransfer,
|
||||||
cancellationSignal = cancellationSignal,
|
cancellationSignal = cancellationSignal,
|
||||||
exportExtras = exportExtras
|
exportExtras = exportExtras
|
||||||
)
|
)
|
||||||
@@ -500,6 +502,7 @@ object BackupRepository {
|
|||||||
isLocal: Boolean,
|
isLocal: Boolean,
|
||||||
writer: BackupExportWriter,
|
writer: BackupExportWriter,
|
||||||
mediaBackupEnabled: Boolean = SignalStore.backup.backsUpMedia,
|
mediaBackupEnabled: Boolean = SignalStore.backup.backsUpMedia,
|
||||||
|
forTransfer: Boolean = false,
|
||||||
progressEmitter: ExportProgressListener? = null,
|
progressEmitter: ExportProgressListener? = null,
|
||||||
cancellationSignal: () -> Boolean = { false },
|
cancellationSignal: () -> Boolean = { false },
|
||||||
exportExtras: ((SignalDatabase) -> Unit)? = null
|
exportExtras: ((SignalDatabase) -> Unit)? = null
|
||||||
@@ -515,7 +518,7 @@ object BackupRepository {
|
|||||||
val signalStoreSnapshot: SignalStore = createSignalStoreSnapshot(keyValueDbName)
|
val signalStoreSnapshot: SignalStore = createSignalStoreSnapshot(keyValueDbName)
|
||||||
eventTimer.emit("store-db-snapshot")
|
eventTimer.emit("store-db-snapshot")
|
||||||
|
|
||||||
val exportState = ExportState(backupTime = currentTime, mediaBackupEnabled = mediaBackupEnabled)
|
val exportState = ExportState(backupTime = currentTime, mediaBackupEnabled = mediaBackupEnabled, forTransfer = forTransfer)
|
||||||
val selfAci = signalStoreSnapshot.accountValues.aci!!
|
val selfAci = signalStoreSnapshot.accountValues.aci!!
|
||||||
val selfRecipientId = dbSnapshot.recipientTable.getByAci(selfAci).get().toLong().let { RecipientId.from(it) }
|
val selfRecipientId = dbSnapshot.recipientTable.getByAci(selfAci).get().toLong().let { RecipientId.from(it) }
|
||||||
|
|
||||||
@@ -1521,7 +1524,11 @@ data class ResumableMessagesBackupUploadSpec(
|
|||||||
|
|
||||||
data class ArchivedMediaObject(val mediaId: String, val cdn: Int)
|
data class ArchivedMediaObject(val mediaId: String, val cdn: Int)
|
||||||
|
|
||||||
class ExportState(val backupTime: Long, val mediaBackupEnabled: Boolean) {
|
class ExportState(
|
||||||
|
val backupTime: Long,
|
||||||
|
val mediaBackupEnabled: Boolean,
|
||||||
|
val forTransfer: Boolean
|
||||||
|
) {
|
||||||
val recipientIds: MutableSet<Long> = hashSetOf()
|
val recipientIds: MutableSet<Long> = hashSetOf()
|
||||||
val threadIds: MutableSet<Long> = hashSetOf()
|
val threadIds: MutableSet<Long> = hashSetOf()
|
||||||
val contactRecipientIds: MutableSet<Long> = hashSetOf()
|
val contactRecipientIds: MutableSet<Long> = hashSetOf()
|
||||||
|
|||||||
@@ -562,9 +562,14 @@ private fun BackupMessageRecord.toBasicChatItemBuilder(selfRecipientId: Recipien
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!MessageTypes.isExpirationTimerUpdate(record.type) && builder.expiresInMs != null && builder.expireStartDate != null && builder.expireStartDate!! + builder.expiresInMs!! < backupStartTime + 1.days.inWholeMilliseconds) {
|
if (!MessageTypes.isExpirationTimerUpdate(record.type) && builder.expiresInMs != null && builder.expireStartDate != null) {
|
||||||
Log.w(TAG, ExportSkips.messageExpiresTooSoon(record.dateSent))
|
val expiresAt = builder.expireStartDate!! + builder.expiresInMs!!
|
||||||
return null
|
val threshold = if (exportState.forTransfer) backupStartTime else backupStartTime + 1.days.inWholeMilliseconds
|
||||||
|
|
||||||
|
if (expiresAt < threshold) {
|
||||||
|
Log.w(TAG, ExportSkips.messageExpiresTooSoon(record.dateSent))
|
||||||
|
return null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (builder.expireStartDate != null && builder.expiresInMs == null) {
|
if (builder.expireStartDate != null && builder.expiresInMs == null) {
|
||||||
@@ -1500,10 +1505,6 @@ private fun Cursor.toBackupMessageRecord(pastIds: Set<Long>, backupStartTime: Lo
|
|||||||
val expiresIn = this.requireLong(MessageTable.EXPIRES_IN)
|
val expiresIn = this.requireLong(MessageTable.EXPIRES_IN)
|
||||||
val expireStarted = this.requireLong(MessageTable.EXPIRE_STARTED)
|
val expireStarted = this.requireLong(MessageTable.EXPIRE_STARTED)
|
||||||
|
|
||||||
if (expireStarted != 0L && expireStarted + expiresIn < backupStartTime + 1.days.inWholeMilliseconds) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
return BackupMessageRecord(
|
return BackupMessageRecord(
|
||||||
id = id,
|
id = id,
|
||||||
dateSent = this.requireLong(MessageTable.DATE_SENT).clampToValidBackupRange(),
|
dateSent = this.requireLong(MessageTable.DATE_SENT).clampToValidBackupRange(),
|
||||||
|
|||||||
@@ -143,7 +143,7 @@ class InternalBackupPlaygroundViewModel : ViewModel() {
|
|||||||
append = { bytes -> tempFile.appendBytes(bytes) }
|
append = { bytes -> tempFile.appendBytes(bytes) }
|
||||||
)
|
)
|
||||||
_state.value = _state.value.copy(statusMessage = "Export complete! Validating...")
|
_state.value = _state.value.copy(statusMessage = "Export complete! Validating...")
|
||||||
ArchiveValidator.validate(tempFile, SignalStore.backup.messageBackupKey)
|
ArchiveValidator.validate(tempFile, SignalStore.backup.messageBackupKey, forTransfer = false)
|
||||||
}
|
}
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
|||||||
@@ -215,7 +215,7 @@ class BackupMessagesJob private constructor(
|
|||||||
|
|
||||||
stopwatch.split("export")
|
stopwatch.split("export")
|
||||||
|
|
||||||
when (val result = ArchiveValidator.validate(tempBackupFile, backupKey)) {
|
when (val result = ArchiveValidator.validate(tempBackupFile, backupKey, forTransfer = false)) {
|
||||||
ArchiveValidator.ValidationResult.Success -> {
|
ArchiveValidator.ValidationResult.Success -> {
|
||||||
Log.d(TAG, "Successfully passed validation.")
|
Log.d(TAG, "Successfully passed validation.")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -254,6 +254,7 @@ object LinkDeviceRepository {
|
|||||||
append = { tempBackupFile.appendBytes(it) },
|
append = { tempBackupFile.appendBytes(it) },
|
||||||
messageBackupKey = ephemeralMessageBackupKey,
|
messageBackupKey = ephemeralMessageBackupKey,
|
||||||
mediaBackupEnabled = false,
|
mediaBackupEnabled = false,
|
||||||
|
forTransfer = true,
|
||||||
cancellationSignal = cancellationSignal
|
cancellationSignal = cancellationSignal
|
||||||
)
|
)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
@@ -268,7 +269,7 @@ object LinkDeviceRepository {
|
|||||||
return LinkUploadArchiveResult.BackupCreationCancelled
|
return LinkUploadArchiveResult.BackupCreationCancelled
|
||||||
}
|
}
|
||||||
|
|
||||||
when (val result = ArchiveValidator.validate(tempBackupFile, ephemeralMessageBackupKey)) {
|
when (val result = ArchiveValidator.validate(tempBackupFile, ephemeralMessageBackupKey, forTransfer = true)) {
|
||||||
ArchiveValidator.ValidationResult.Success -> {
|
ArchiveValidator.ValidationResult.Success -> {
|
||||||
Log.d(TAG, "[createAndUploadArchive] Successfully passed validation.")
|
Log.d(TAG, "[createAndUploadArchive] Successfully passed validation.")
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user